4 Commits
Author SHA1 Message Date
moritz 99f687f5a2 test: pin that clean-deploy configures the apps around the purge
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2026-08-26 03:59:15 +02:00
moritz 6a781f0c0f fix(clean-deploy): create envs to remove all traces
continuous-integration/drone/tag Build is failing
continuous-integration/drone/push Build is failing
2026-08-26 03:56:05 +02:00
moritz 28ddad9e98 fix(config): warn instead of erroring on files outside the preflight
continuous-integration/drone/push Build is passing
2026-08-26 02:23:16 +02:00
moritz 0636d2271c ci: add make to image
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2026-08-26 01:56:16 +02:00
4 changed files with 51 additions and 19 deletions
+17 -17
View File
@@ -9,41 +9,41 @@ COPY abra/ ./
COPY .git/modules/abra /gitdir
# abra ships its dependencies in vendor/, so the build itself needs no network
RUN set -eu; \
sed -i '/worktree =/d' /gitdir/config; \
version="$(git --git-dir=/gitdir describe --tags)"; \
commit="$(git --git-dir=/gitdir rev-parse HEAD)"; \
echo "building abra $version"; \
go build -mod=vendor -trimpath \
-ldflags "-s -w -X 'main.Version=$version' -X 'main.Commit=$commit'" \
-o /out/abra ./cmd/abra
sed -i '/worktree =/d' /gitdir/config; \
version="$(git --git-dir=/gitdir describe --tags)"; \
commit="$(git --git-dir=/gitdir rev-parse HEAD)"; \
echo "building abra $version"; \
go build -mod=vendor -trimpath \
-ldflags "-s -w -X 'main.Version=$version' -X 'main.Commit=$commit'" \
-o /out/abra ./cmd/abra
FROM python:3.11-slim AS deps
RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc libc6-dev \
&& rm -rf /var/lib/apt/lists/*
&& apt-get install -y --no-install-recommends gcc libc6-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt /tmp/requirements.txt
RUN python -m venv /opt/alakazam \
&& /opt/alakazam/bin/pip install --no-cache-dir -r /tmp/requirements.txt
&& /opt/alakazam/bin/pip install --no-cache-dir -r /tmp/requirements.txt
FROM python:3.11-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends git openssh-client \
&& rm -rf /var/lib/apt/lists/* \
&& git config --global --add safe.directory '*'
&& apt-get install -y --no-install-recommends git openssh-client make \
&& rm -rf /var/lib/apt/lists/* \
&& git config --global --add safe.directory '*'
COPY --from=abra /out/abra /usr/local/bin/abra
COPY --from=deps /opt/alakazam /opt/alakazam
COPY alakazam.py combine.yml /opt/alakazam/
RUN printf '#!/bin/sh\nexec /opt/alakazam/bin/python /opt/alakazam/alakazam.py "$@"\n' \
> /usr/local/bin/alakazam \
&& chmod +x /usr/local/bin/alakazam
> /usr/local/bin/alakazam \
&& chmod +x /usr/local/bin/alakazam
# PYTHONUNBUFFERED so the streamed hook output arrives while a command is still running.
# LANG pins abra to its untranslated messages, which alakazam matches on to tell a missing
# secret or an empty generate run apart from a real failure.
ENV PYTHONUNBUFFERED=1 \
LANG=C.UTF-8 \
ABRA_DIR=/root/.abra
LANG=C.UTF-8 \
ABRA_DIR=/root/.abra
WORKDIR /config
CMD ["alakazam", "--help"]
+2 -1
View File
@@ -135,7 +135,7 @@ def read_config(configpath: str) -> Dict[str, Any]:
try:
yaml_config = yaml.load(file)
except Exception as e:
logging.error(f"Error reading config file {filepath}: {str(e)}")
logging.warning(f"config file {filepath} could not be read and is skipped: {str(e)}")
return {}
if not yaml_config:
@@ -2475,6 +2475,7 @@ def clean_deploy(recipes: Tuple[str], converge_checks: bool, timeout: int, nonin
print_all_apps(instance_apps)
if not (noninteractive or input(f"This deletes all data of these apps. Do you really want to rebuild them? Type YES: ") == "YES"):
return
configure_apps(recipes)
undeploy_apps(get_apps_by_deployment(recipes, deployed=True))
purge_apps(instance_apps)
setup_environment(recipes, converge_checks=converge_checks, timeout=timeout)
+14
View File
@@ -61,6 +61,20 @@ class TestCheckConfigReadable:
assert "\n" not in check_config_readable(path)
class TestReadConfigSeverity:
"""An unreadable file that reaches read_config is out of scope by construction."""
def test_an_unreadable_config_warns_rather_than_errors(self, config_root, caplog):
import logging
broken = config_root / "foreign" / "alaka-secrets.yml"
broken.parent.mkdir()
broken.write_bytes(GIT_CRYPT_HEADER)
with caplog.at_level(logging.DEBUG):
assert alakazam.read_config(str(broken)) == {}
assert [r.levelname for r in caplog.records] == ["WARNING"]
assert "is skipped" in caplog.text
class TestPreflightConfigs:
def test_passes_for_readable_configs(self, config_root):
preflight_configs([config_root / "alaka.yml", config_root / "config-sets.yml"])
+18 -1
View File
@@ -220,7 +220,24 @@ class TestCleanDeployCommand:
instance.write_text("")
result = self.invoke(["-n"], instance, monkeypatch)
assert result.exit_code == 0, result.exception
assert server.steps[:3] == ["undeploy", "purge", "config"]
assert server.steps[:4] == ["config", "undeploy", "purge", "config"]
def test_the_apps_are_configured_before_they_are_purged(self, monkeypatch, tmp_path):
"""purge_apps() skips an app without a local .env, so a fresh checkout would purge nothing."""
server = FakeServer(deployed=["login.a.org"]).install(monkeypatch)
instance = tmp_path / "example.com.yml"
instance.write_text("")
self.invoke(["-n"], instance, monkeypatch)
assert server.steps.index("config") < server.steps.index("purge")
def test_the_apps_are_configured_again_after_the_purge(self, monkeypatch, tmp_path):
"""'abra app rm' deletes the local .env as well, so setup has to write it a second time."""
server = FakeServer(deployed=["login.a.org"]).install(monkeypatch)
instance = tmp_path / "example.com.yml"
instance.write_text("")
self.invoke(["-n"], instance, monkeypatch)
assert server.steps.count("config") == 2
assert server.steps.index("purge") < len(server.steps) - 1 - server.steps[::-1].index("config")
def test_a_group_directory_is_rejected(self, monkeypatch, tmp_path):
server = FakeServer().install(monkeypatch)