diff --git a/CHANGELOG.md b/CHANGELOG.md index 4727133f..da339afc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## untagged +- Make www upload path configurable + ([#618](https://github.com/chatmail/relay/pull/618)) + - Check whether GCC is installed in initenv.sh ([#608](https://github.com/chatmail/relay/pull/608)) diff --git a/README.md b/README.md index 7ba08fdb..9f60d113 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,18 @@ This starts a local live development cycle for chatmail web pages: - Starts a browser window automatically where you can "refresh" as needed. +#### Custom web pages + +You can skip uploading a web page +by setting `www_folder=disabled` in `chatmail.ini`. + +If you want to manage your web pages outside this git repository, +you can set `www_folder` in `chatmail.ini` to a custom directory on your computer. +`cmdeploy run` will upload it as the server's home page, +and if it contains a `src/index.md` file, +will build it with hugo. + + ## Mailbox directory layout Fresh chatmail addresses have a mailbox directory that contains: diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index 0cac3ea4..ae5f4423 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -33,6 +33,7 @@ def __init__(self, inipath, params): self.password_min_length = int(params["password_min_length"]) self.passthrough_senders = params["passthrough_senders"].split() self.passthrough_recipients = params["passthrough_recipients"].split() + self.www_folder = params.get("www_folder", "") self.filtermail_smtp_port = int(params["filtermail_smtp_port"]) self.filtermail_smtp_port_incoming = int( params["filtermail_smtp_port_incoming"] diff --git a/cmdeploy/src/cmdeploy/__init__.py b/cmdeploy/src/cmdeploy/__init__.py index 9a4e4229..4523be1d 100644 --- a/cmdeploy/src/cmdeploy/__init__.py +++ b/cmdeploy/src/cmdeploy/__init__.py @@ -11,7 +11,7 @@ from pathlib import Path from chatmaild.config import Config, read_config -from pyinfra import facts, host +from pyinfra import facts, host, logger from pyinfra.api import FactBase from pyinfra.facts.files import File from pyinfra.facts.server import Sysctl @@ -618,7 +618,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None: check_config(config) mail_domain = config.mail_domain - from .www import build_webpages + from .www import build_webpages, get_paths server.group(name="Create vmail group", group="vmail", system=True) server.user(name="Create vmail user", user="vmail", group="vmail", system=True) @@ -751,12 +751,16 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None: packages=["fcgiwrap"], ) - www_path = importlib.resources.files(__package__).joinpath("../../../www").resolve() - - build_dir = www_path.joinpath("build") - src_dir = www_path.joinpath("src") - build_webpages(src_dir, build_dir, config) - files.rsync(f"{build_dir}/", "/var/www/html", flags=["-avz"]) + www_path, src_dir, build_dir = get_paths(config) + # if www_folder was set to a non-existing folder, skip upload + if not www_path.is_dir(): + logger.warning("Building web pages is disabled in chatmail.ini, skipping") + else: + # if www_folder is a hugo page, build it + if build_dir: + www_path = build_webpages(src_dir, build_dir, config) + # if it is not a hugo page, upload it as is + files.rsync(f"{www_path}/", "/var/www/html", flags=["-avz"]) _install_remote_venv_with_chatmaild(config) debug = False diff --git a/cmdeploy/src/cmdeploy/tests/test_cmdeploy.py b/cmdeploy/src/cmdeploy/tests/test_cmdeploy.py index 3084c8ec..bdbc3db0 100644 --- a/cmdeploy/src/cmdeploy/tests/test_cmdeploy.py +++ b/cmdeploy/src/cmdeploy/tests/test_cmdeploy.py @@ -1,8 +1,10 @@ +import importlib import os import pytest from cmdeploy.cmdeploy import get_parser, main +from cmdeploy.www import get_paths @pytest.fixture(autouse=True) @@ -27,3 +29,28 @@ def test_init_not_overwrite(self, capsys): assert main(["init", "chat.example.org"]) == 1 out, err = capsys.readouterr() assert "path exists" in out.lower() + + +def test_www_folder(example_config, tmp_path): + reporoot = importlib.resources.files(__package__).joinpath("../../../../").resolve() + assert not example_config.www_folder + www_path, src_dir, build_dir = get_paths(example_config) + assert www_path.absolute() == reporoot.joinpath("www").absolute() + assert src_dir == reporoot.joinpath("www").joinpath("src") + assert build_dir == reporoot.joinpath("www").joinpath("build") + example_config.www_folder = "disabled" + www_path, _, _ = get_paths(example_config) + assert not www_path.is_dir() + example_config.www_folder = str(tmp_path) + www_path, src_dir, build_dir = get_paths(example_config) + assert www_path == tmp_path + assert not src_dir.exists() + assert not build_dir + src_path = tmp_path.joinpath("src") + os.mkdir(src_path) + with open(src_path / "index.md", "w") as f: + f.write("# Test") + www_path, src_dir, build_dir = get_paths(example_config) + assert www_path == tmp_path + assert src_dir == src_path + assert build_dir == tmp_path.joinpath("build") diff --git a/cmdeploy/src/cmdeploy/www.py b/cmdeploy/src/cmdeploy/www.py index 9dd404ba..c013d741 100644 --- a/cmdeploy/src/cmdeploy/www.py +++ b/cmdeploy/src/cmdeploy/www.py @@ -3,6 +3,7 @@ import time import traceback import webbrowser +from pathlib import Path import markdown from chatmaild.config import read_config @@ -30,9 +31,25 @@ def prepare_template(source): return render_vars, page_layout -def build_webpages(src_dir, build_dir, config): +def get_paths(config) -> (Path, Path, Path): + reporoot = importlib.resources.files(__package__).joinpath("../../../").resolve() + www_path = Path(config.www_folder) + # if www_folder was not set, use default directory + if config.www_folder == "": + www_path = reporoot.joinpath("www") + src_dir = www_path.joinpath("src") + # if www_folder is a hugo page, build it + if src_dir.joinpath("index.md").is_file(): + build_dir = www_path.joinpath("build") + # if it is not a hugo page, upload it as is + else: + build_dir = None + return www_path, src_dir, build_dir + + +def build_webpages(src_dir, build_dir, config) -> Path: try: - _build_webpages(src_dir, build_dir, config) + return _build_webpages(src_dir, build_dir, config) except Exception: print(traceback.format_exc()) @@ -106,15 +123,11 @@ def main(): config = read_config(inipath) config.webdev = True assert config.mail_domain - www_path = reporoot.joinpath("www") - src_path = www_path.joinpath("src") - stats = None - build_dir = www_path.joinpath("build") - src_dir = www_path.joinpath("src") - index_path = build_dir.joinpath("index.html") # start web page generation, open a browser and wait for changes - build_webpages(src_dir, build_dir, config) + www_path, src_path, build_dir = get_paths(config) + build_dir = build_webpages(src_path, build_dir, config) + index_path = build_dir.joinpath("index.html") webbrowser.open(str(index_path)) stats = snapshot_dir_stats(src_path) print(f"\nOpened URL: file://{index_path.resolve()}\n") @@ -135,7 +148,7 @@ def main(): changenum += 1 stats = newstats - build_webpages(src_dir, build_dir, config) + build_webpages(src_path, build_dir, config) print(f"[{changenum}] regenerated web pages at: {index_path}") print(f"URL: file://{index_path.resolve()}\n\n") count = 0