mirror of
https://github.com/chatmail/relay.git
synced 2026-05-21 13:28:05 +00:00
Compare commits
3 Commits
ci-improve
...
ci-alxndr4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2521698093 | ||
|
|
8c85dddfa3 | ||
|
|
acf2bdefdf |
@@ -681,7 +681,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
|
|||||||
check_config(config)
|
check_config(config)
|
||||||
mail_domain = config.mail_domain
|
mail_domain = config.mail_domain
|
||||||
|
|
||||||
from .www import build_webpages, get_paths
|
from .www import build_webpages, find_merge_conflict, get_paths
|
||||||
|
|
||||||
server.group(name="Create vmail group", group="vmail", system=True)
|
server.group(name="Create vmail group", group="vmail", system=True)
|
||||||
server.user(name="Create vmail user", user="vmail", group="vmail", system=True)
|
server.user(name="Create vmail user", user="vmail", group="vmail", system=True)
|
||||||
@@ -823,6 +823,8 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
|
|||||||
# if www_folder was set to a non-existing folder, skip upload
|
# if www_folder was set to a non-existing folder, skip upload
|
||||||
if not www_path.is_dir():
|
if not www_path.is_dir():
|
||||||
logger.warning("Building web pages is disabled in chatmail.ini, skipping")
|
logger.warning("Building web pages is disabled in chatmail.ini, skipping")
|
||||||
|
elif (path := find_merge_conflict(src_dir)) is not None:
|
||||||
|
logger.warning(f"Merge conflict found in {path}, skipping")
|
||||||
else:
|
else:
|
||||||
# if www_folder is a hugo page, build it
|
# if www_folder is a hugo page, build it
|
||||||
if build_dir:
|
if build_dir:
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ def query_dns(typ, domain):
|
|||||||
|
|
||||||
# Query authoritative nameserver directly to bypass DNS cache.
|
# Query authoritative nameserver directly to bypass DNS cache.
|
||||||
res = shell(f"dig @{ns} -r -q {domain} -t {typ} +short", print=log_progress)
|
res = shell(f"dig @{ns} -r -q {domain} -t {typ} +short", print=log_progress)
|
||||||
return next((line for line in res.split("\n") if not line.startswith(';')), '')
|
if res:
|
||||||
|
return res.split("\n")[0]
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def check_zonefile(zonefile, verbose=True):
|
def check_zonefile(zonefile, verbose=True):
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
from copy import deepcopy
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from cmdeploy import remote
|
from cmdeploy import remote
|
||||||
@@ -10,63 +8,38 @@ from cmdeploy.dns import check_full_zone, check_initial_remote_data
|
|||||||
def mockdns_base(monkeypatch):
|
def mockdns_base(monkeypatch):
|
||||||
qdict = {}
|
qdict = {}
|
||||||
|
|
||||||
def shell(command, fail_ok=False, print=print):
|
def query_dns(typ, domain):
|
||||||
if command.startswith("dig"):
|
try:
|
||||||
if command == "dig":
|
return qdict[typ][domain]
|
||||||
return "."
|
except KeyError:
|
||||||
if "SOA" in command:
|
return ""
|
||||||
return (
|
|
||||||
"delta.chat. 21600 IN SOA ns1.first-ns.de. dns.hetzner.com."
|
|
||||||
" 2025102800 14400 1800 604800 3600"
|
|
||||||
)
|
|
||||||
command_chunks = command.split()
|
|
||||||
domain, typ = command_chunks[4], command_chunks[6]
|
|
||||||
try:
|
|
||||||
return qdict[typ][domain]
|
|
||||||
except KeyError:
|
|
||||||
return ""
|
|
||||||
return remote.rshell.shell(command=command, fail_ok=fail_ok, print=print)
|
|
||||||
|
|
||||||
monkeypatch.setattr(remote.rdns, shell.__name__, shell)
|
monkeypatch.setattr(remote.rdns, query_dns.__name__, query_dns)
|
||||||
return qdict
|
return qdict
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mockdns_expected():
|
def mockdns(mockdns_base):
|
||||||
return {
|
mockdns_base.update(
|
||||||
"A": {"some.domain": "1.1.1.1"},
|
{
|
||||||
"AAAA": {"some.domain": "fde5:cd7a:9e1c:3240:5a99:936f:cdac:53ae"},
|
"A": {"some.domain": "1.1.1.1"},
|
||||||
"CNAME": {
|
"AAAA": {"some.domain": "fde5:cd7a:9e1c:3240:5a99:936f:cdac:53ae"},
|
||||||
"mta-sts.some.domain": "some.domain.",
|
"CNAME": {
|
||||||
"www.some.domain": "some.domain.",
|
"mta-sts.some.domain": "some.domain.",
|
||||||
},
|
"www.some.domain": "some.domain.",
|
||||||
}
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@pytest.fixture(params=["plain", "with-dns-comments"])
|
|
||||||
def mockdns(request, mockdns_base, mockdns_expected):
|
|
||||||
mockdns_base.update(deepcopy(mockdns_expected))
|
|
||||||
match request.param:
|
|
||||||
case "plain":
|
|
||||||
pass
|
|
||||||
case "with-dns-comments":
|
|
||||||
for typ, data in mockdns_base.items():
|
|
||||||
for host, result in data.items():
|
|
||||||
mockdns_base[typ][host] = (
|
|
||||||
";; some unsuccessful attempt result\n"
|
|
||||||
"; and another with a single semicolon\n"
|
|
||||||
f"{result}"
|
|
||||||
)
|
|
||||||
return mockdns_base
|
return mockdns_base
|
||||||
|
|
||||||
|
|
||||||
class TestPerformInitialChecks:
|
class TestPerformInitialChecks:
|
||||||
def test_perform_initial_checks_ok1(self, mockdns, mockdns_expected):
|
def test_perform_initial_checks_ok1(self, mockdns):
|
||||||
remote_data = remote.rdns.perform_initial_checks("some.domain")
|
remote_data = remote.rdns.perform_initial_checks("some.domain")
|
||||||
assert remote_data["A"] == mockdns_expected["A"]["some.domain"]
|
assert remote_data["A"] == mockdns["A"]["some.domain"]
|
||||||
assert remote_data["AAAA"] == mockdns_expected["AAAA"]["some.domain"]
|
assert remote_data["AAAA"] == mockdns["AAAA"]["some.domain"]
|
||||||
assert remote_data["MTA_STS"] == mockdns_expected["CNAME"]["mta-sts.some.domain"]
|
assert remote_data["MTA_STS"] == mockdns["CNAME"]["mta-sts.some.domain"]
|
||||||
assert remote_data["WWW"] == mockdns_expected["CNAME"]["www.some.domain"]
|
assert remote_data["WWW"] == mockdns["CNAME"]["www.some.domain"]
|
||||||
|
|
||||||
@pytest.mark.parametrize("drop", ["A", "AAAA"])
|
@pytest.mark.parametrize("drop", ["A", "AAAA"])
|
||||||
def test_perform_initial_checks_with_one_of_A_AAAA(self, mockdns, drop):
|
def test_perform_initial_checks_with_one_of_A_AAAA(self, mockdns, drop):
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import time
|
|||||||
import traceback
|
import traceback
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
import markdown
|
import markdown
|
||||||
from chatmaild.config import read_config
|
from chatmaild.config import read_config
|
||||||
@@ -12,6 +13,9 @@ from jinja2 import Template
|
|||||||
from .genqr import gen_qr_png_data
|
from .genqr import gen_qr_png_data
|
||||||
|
|
||||||
|
|
||||||
|
_MERGE_CONFLICT_RE = re.compile(r"^<<<<<<<.+^=======.+^>>>>>>>", re.DOTALL | re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
def snapshot_dir_stats(somedir):
|
def snapshot_dir_stats(somedir):
|
||||||
d = {}
|
d = {}
|
||||||
for path in somedir.iterdir():
|
for path in somedir.iterdir():
|
||||||
@@ -116,6 +120,17 @@ def _build_webpages(src_dir, build_dir, config):
|
|||||||
return build_dir
|
return build_dir
|
||||||
|
|
||||||
|
|
||||||
|
def find_merge_conflict(src_dir) -> Path:
|
||||||
|
assert src_dir.exists(), src_dir
|
||||||
|
result = None
|
||||||
|
for path in src_dir.iterdir():
|
||||||
|
if path.suffix in [".css", ".html", ".md"]:
|
||||||
|
if _MERGE_CONFLICT_RE.search(path.read_text()):
|
||||||
|
result = path
|
||||||
|
break
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
path = importlib.resources.files(__package__)
|
path = importlib.resources.files(__package__)
|
||||||
reporoot = path.joinpath("../../../").resolve()
|
reporoot = path.joinpath("../../../").resolve()
|
||||||
|
|||||||
@@ -9,7 +9,11 @@
|
|||||||
<title>{{ config.mail_domain }} {{ pagename }}</title>
|
<title>{{ config.mail_domain }} {{ pagename }}</title>
|
||||||
<link rel="stylesheet" href="./main.css">
|
<link rel="stylesheet" href="./main.css">
|
||||||
<link rel="icon" href="/logo.svg">
|
<link rel="icon" href="/logo.svg">
|
||||||
<link rel=”mask-icon” href=”/logo.svg” color=”#000000">
|
<<<<<<< HEAD
|
||||||
|
<link rel="mask-icon" href="/logo.svg" color="#000000">
|
||||||
|
=======
|
||||||
|
<link rel=”mask-icon” href=”/logo.svg” color=”#000001">
|
||||||
|
>>>>>>> 2da7de8 (make logo slightly brighter)
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user