From b8acf37c248c62c3412aa2639499899c65e7ef9c Mon Sep 17 00:00:00 2001 From: Gemini CLI Date: Sun, 17 May 2026 17:14:35 +0200 Subject: [PATCH] fix: CI Dagger syntax, missing deps, and Stalwart startup --- DAGGER.md | 2 +- Taskfile.yml | 18 +++++++++--------- ci/main.go | 23 +++++++++++++++-------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/DAGGER.md b/DAGGER.md index 6965c52..b292e05 100644 --- a/DAGGER.md +++ b/DAGGER.md @@ -61,7 +61,7 @@ _DAGGER_RUNNER_HOST=tcp://127.0.0.1:8080 Once the environment is set up, you can run the Dagger pipeline. For non-interactive environments (CI, LLMs), use `--progress=plain` for readable logs: ```bash -nix develop --command dagger call --progress=plain -m ci check --source . +nix develop --command dagger call --progress=plain -m ci --source=. check ``` ## CI Integration (Codeberg/Forgejo) diff --git a/Taskfile.yml b/Taskfile.yml index 0fd2046..2f9856e 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -174,23 +174,23 @@ tasks: test-backend: desc: Backend tests against a local Stalwart mail server (via Dagger) cmds: - - dagger call --progress=plain -m ci test-backend --source . + - dagger call --progress=plain -m ci --source=. test-backend integration-ui: desc: UI E2E tests on Linux via Xvfb — headless, no emulator needed (via Dagger) cmds: - - dagger call --progress=plain -m ci test-integration --source . + - dagger call --progress=plain -m ci --source=. test-integration sync-reliability: desc: Run sync reliability runner (via Dagger) cmds: - - dagger call --progress=plain -m ci test-sync-reliability --source . + - dagger call --progress=plain -m ci --source=. test-sync-reliability stalwart: desc: Start a Stalwart instance for local development (via Dagger) cmds: - echo "Starting Stalwart on default ports (JMAP=8080, IMAP=1430, SMTP=1025, SIEVE=4190)" - - dagger call --progress=plain -m ci stalwart up --ports 8080:8080 --ports 1430:1430 --ports 1025:1025 --ports 4190:4190 + - dagger call --progress=plain -m ci --source=. stalwart up --ports 8080:8080 --ports 1430:1430 --ports 1025:1025 --ports 4190:4190 deploy-linux: desc: Build and deploy Linux release via Dagger @@ -198,7 +198,7 @@ tasks: - sh: test -n "$SSH_PRIVATE_KEY" msg: "SSH_PRIVATE_KEY is not set" cmds: - - HASH=$(git rev-parse --short HEAD) && dagger call --progress=plain -m ci deploy-linux --source . --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" --commit-hash "$HASH" + - HASH=$(git rev-parse --short HEAD) && dagger call --progress=plain -m ci --source=. deploy-linux --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" --commit-hash "$HASH" publish-android: desc: Build and publish Android App Bundle to Play Store via Dagger @@ -206,7 +206,7 @@ tasks: - sh: test -n "$PLAY_STORE_CONFIG_JSON" msg: "PLAY_STORE_CONFIG_JSON is not set" cmds: - - dagger call --progress=plain -m ci publish-android --source . --play-store-config env:PLAY_STORE_CONFIG_JSON + - dagger call --progress=plain -m ci --source=. publish-android --play-store-config env:PLAY_STORE_CONFIG_JSON deploy-apk: desc: Build and deploy Android APK via Dagger @@ -214,7 +214,7 @@ tasks: - sh: test -n "$SSH_PRIVATE_KEY" msg: "SSH_PRIVATE_KEY is not set" cmds: - - HASH=$(git rev-parse --short HEAD) && dagger call --progress=plain -m ci deploy-apk --source . --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" --commit-hash "$HASH" + - HASH=$(git rev-parse --short HEAD) && dagger call --progress=plain -m ci --source=. deploy-apk --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" --commit-hash "$HASH" publish-website: desc: Build and publish website via Dagger @@ -222,12 +222,12 @@ tasks: - sh: test -n "$SSH_PRIVATE_KEY" msg: "SSH_PRIVATE_KEY is not set" cmds: - - dagger call --progress=plain -m ci publish-website --source . --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" + - dagger call --progress=plain -m ci --source=. publish-website --ssh-key env:SSH_PRIVATE_KEY --ssh-user "$SSH_USER" --ssh-host "$SSH_HOST" check-dagger: desc: Run full check suite via Dagger cmds: - - dagger call --progress=plain -m ci check --source . + - dagger call --progress=plain -m ci --source=. check integration-android: desc: UI integration tests on a connected Android emulator (Stalwart on host, emulator reaches it via 10.0.2.2) diff --git a/ci/main.go b/ci/main.go index 71c386c..992dd36 100644 --- a/ci/main.go +++ b/ci/main.go @@ -41,7 +41,7 @@ func (m *Ci) Base() *dagger.Container { return dag.Container(). From("ghcr.io/cirruslabs/flutter:3.41.6"). WithExec([]string{"apt-get", "update"}). - WithExec([]string{"apt-get", "install", "-y", "clang", "cmake", "ninja-build", "pkg-config", "libgtk-3-dev", "liblzma-dev", "libsecret-1-dev", "libgcrypt20-dev", "libjsoncpp-dev", "sqlite3", "curl", "python3", "iproute2", "netcat-openbsd", "xvfb", "libosmesa6", "libgles2-mesa", "libegl1"}). + WithExec([]string{"apt-get", "install", "-y", "clang", "cmake", "ninja-build", "pkg-config", "libgtk-3-dev", "liblzma-dev", "libsecret-1-dev", "libgcrypt20-dev", "libjsoncpp-dev", "sqlite3", "curl", "python3", "iproute2", "netcat-openbsd", "xvfb", "libosmesa6", "libegl1", "lld"}). WithMountedCache("/root/.pub-cache", dag.CacheVolume("flutter-pub-cache")). WithMountedCache("/root/.gradle", dag.CacheVolume("gradle-cache")). WithEnvVariable("PUB_CACHE", "/root/.pub-cache"). @@ -72,12 +72,20 @@ func (m *Ci) Deployer(sshKey *dagger.Secret) *dagger.Container { func (m *Ci) Stalwart() *dagger.Service { config := m.Source.Directory("stalwart-dev").File("config.toml") - return dag.Container(). - From("stalwartlabs/stalwart:v0.14.1"). - WithFile("/etc/stalwart/config.toml", config). - // Pre-seed data directory and spam-filter version to avoid network hits on startup. + // Pre-seed data directory and spam-filter version to avoid network hits on startup. + // We use an alpine container to create the sqlite database file. + dataDir := dag.Container(). + From("alpine:3.21"). + WithExec([]string{"apk", "add", "--no-cache", "sqlite"}). WithExec([]string{"/bin/sh", "-c", "mkdir -p /tmp/stalwart && chmod 777 /tmp/stalwart"}). WithExec([]string{"sqlite3", "/tmp/stalwart/data.sqlite", "CREATE TABLE IF NOT EXISTS s (k BLOB PRIMARY KEY, v BLOB NOT NULL); INSERT OR REPLACE INTO s VALUES ('version.spam-filter', 'dev');"}). + Directory("/tmp/stalwart") + + return dag.Container(). + From("stalwartlabs/stalwart:v0.14.1"). + WithFile("/etc/stalwart/config.toml.orig", config). + WithExec([]string{"/bin/sh", "-c", "sed -e 's/hostname = \"localhost\"/hostname = \"stalwart\"/' -e 's/bind = \\[\"0.0.0.0:\\([0-9]*\\)\"\\]/bind = [\"0.0.0.0:\\1\", \"[::]:\\1\"]/g' /etc/stalwart/config.toml.orig > /etc/stalwart/config.toml"}). + WithDirectory("/tmp/stalwart", dataDir). WithExposedPort(8080). // JMAP WithExposedPort(1430). // IMAP WithExposedPort(1025). // SMTP @@ -108,8 +116,7 @@ func (m *Ci) WithStalwart(container *dagger.Container) *dagger.Container { func (m *Ci) Setup() *dagger.Container { return m.Base(). WithExec([]string{"flutter", "pub", "get"}). - // Use --delete-conflicting-outputs to ensure generated files match the current source - WithExec([]string{"flutter", "pub", "run", "build_runner", "build", "--delete-conflicting-outputs"}) + WithExec([]string{"flutter", "pub", "run", "build_runner", "build"}) } // Run hygiene check @@ -141,7 +148,7 @@ func (m *Ci) CheckMocks(ctx context.Context) (string, error) { WithExec([]string{"git", "config", "user.name", "CI"}). WithExec([]string{"git", "add", "."}). WithExec([]string{"git", "commit", "-m", "baseline"}). - WithExec([]string{"flutter", "pub", "run", "build_runner", "build", "--delete-conflicting-outputs"}). + WithExec([]string{"flutter", "pub", "run", "build_runner", "build"}). WithExec([]string{"/bin/bash", "-c", "CHANGED=$(find . -name '*.mocks.dart' | xargs -r git diff --exit-code); if [ $? -ne 0 ]; then echo \"ERROR: Mocks are out of date\"; exit 1; fi; echo \"Mocks are up to date.\""}). Stdout(ctx) }