The old workflow built with build-android-bundle (debug-signed) then uploaded
separately. publish-android stamps the versionCode, re-signs with the release
keystore, and uploads in one Dagger call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pass --build-number $(date +%s) to flutter build for both APK and AAB
so each CI run gets a unique version code (fixes "already been used" error)
- Extract UploadToPlayStore(aab, playStoreConfig) as its own Dagger function
so the build and upload are independently callable
- Add build-android-bundle task (exports AAB via dagger export) and
upload-android-bundle task (calls UploadToPlayStore with the local file)
- CI deploy-playstore job now has two steps: Build Android Bundle and
Upload to Play Store, so a failed upload can be retried without rebuilding
- deploy-apk also gets --build-number to avoid version code collisions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both BuildAndroidApk and BuildAndroidRelease were using the debug
signing config because the keystore and password were never forwarded
into the Dagger container. Add setupKeystore() helper that decodes
ANDROID_KEYSTORE_BASE64 into android/app/upload-keystore.jks and
sets ANDROID_KEYSTORE_PASSWORD, then wire both secrets through
DeployApk, PublishAndroid, and the Taskfile/CI env blocks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Decodes ANDROID_KEYSTORE_BASE64 and prints the SHA1 fingerprint via
keytool before invoking the Dagger build, to confirm which key is in
the secret vs. what the build actually uses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The ubuntu-latest pool now includes nodes that run Docker containers with
user namespace isolation, causing chown of the workspace to fail before
checkout can run. The codeberg-small label routes consistently to the
actions-tiny nodes (act-latest image, no user namespace restriction) where
Dagger CI succeeded previously.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The ubuntu-latest runner uses Docker containers (ghcr.io/catthehacker/ubuntu:act-22.04)
which don't have task or dagger pre-installed. These steps were mistakenly removed when
switching from the dagger-dagger host runner back to ubuntu-latest.
Also adds DAGGER_NO_NAG=1 to all dagger-invoking steps.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Dagger to flake.nix
- Create Dagger module in ci/ with Flutter build/test logic
- Update .forgejo/workflows/ci.yml to use Dagger
- Move Android emulator tests to separate disabled workflow
- Add .daggerignore to exclude host junk
The standalone "Check mocks are up to date" step ran build_runner AOT
compilation separately, then task check ran it again (check-mocks is
already a dep of check). The double invocation caused the build_runner
AOT compile to receive SIGTERM on the CI runner in run 4027578.
task check already verifies mocks via its check-mocks dep, so the
standalone step is redundant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The deploy steps in build-linux and deploy-playstore already use
continue-on-error: true when SSH secrets may be absent, but
publish-website did not — causing a hard failure when SSH_USER is unset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The builds page at /builds/ was empty because generate-build-history
only ran inside deploy-playstore; if that job failed early (e.g. Play
Store secrets not configured) the website was never updated, and the
build-linux job never triggered a website update at all.
Changes:
- generate_build_history.py: extend to cover Linux tarballs in addition
to Android APKs, capped at MAX_BUILDS_PER_PLATFORM (30) each
- Taskfile: add website-publish task (generate-build-history +
website-deploy), exclude *.tar.gz from rsync, update descriptions
- .forgejo/workflows/ci.yml: add publish-website job that waits for
both build-linux and deploy-playstore (using always() so it runs
even when deploy-playstore fails), then removes the duplicate
generate/deploy steps from deploy-playstore
- .github/workflows/ci.yml: add deploy job that deploys Linux build,
generates build history, builds Hugo site, and rsyncs to server
- .gitignore: ignore website/content/builds/_index.md (generated),
Python __pycache__, and widget test failure screenshots
- stalwart-dev/integration_ui_test.sh: use ${USER:-$(id -un)} for
robustness in environments where USER is unset
- scripts/test_generate_build_history.py: unit tests for parse_builds
and render_entries covering both platforms
Generated content (builds/_index.md and per-day pages) is not tracked
in git; it is produced at CI time and rsynced to the server.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add check-mocks task that re-runs build_runner and fails if any
*.mocks.dart file differs from what is committed. Wired into
check-fast (pre-commit) and added as an early CI step so stale
mocks are caught before the full test suite runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Builds and deploys Windows once a day (02:00 UTC) instead of on every
push to main. Skips the build if no commits landed on main in the last
24 hours. Kept disabled (if: false) until a windows-runner is
registered.
Closes#77
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
timeout-minutes doesn't start until a runner accepts the job, so the
job would queue indefinitely. Disable with if: false for now — change
back to github.ref == 'refs/heads/main' once a windows-runner runner
is set up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60-minute wait blocks every run. 5 minutes lets it fail fast with
continue-on-error, leaving the rest of the workflow unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The windows-runner self-hosted runner doesn't exist yet, so the job
would block the run indefinitely. With continue-on-error + timeout it
fails gracefully once a runner is registered and picks up the job.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds build-windows-release and deploy-windows-to-server Taskfile tasks,
a build-windows CI job (requires a windows-runner self-hosted runner),
and extends updateInfoProvider to also cover Platform.isWindows.
latest.json is now extended with a 'windows' key; both deploy tasks
preserve the other platform's URL when updating the file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Build task embeds GIT_HASH via --dart-define; new deploy-linux-to-server task
packages a tar.gz and updates latest.json on the server. The account list screen
shows a MaterialBanner when a newer Linux build is available.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SSH secrets (SSH_USER, SSH_HOST, SSH_PRIVATE_KEY) are not yet configured
as repository secrets. Mark the four SSH-dependent steps continue-on-error
so the Play Store deploy job succeeds while those secrets are pending.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The deploy-apk-to-server task depends on build-android which signs the
APK — it needs the keystore password or the packageRelease Gradle task
fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scripts/generate_build_history.py: SSH into server, list APKs under
public_html/builds/YYYY/MM/DD/, fetch commit titles from Codeberg API,
and write Hugo content pages to website/content/builds/
- Taskfile: add deploy-apk-to-server and generate-build-history tasks;
add --exclude='*.apk' to website-deploy rsync so APKs survive redeploy
- CI: after Play Store deploy, set up SSH key, scp APK, generate history,
then deploy website
- .gitignore: exclude website/content/builds/ (generated at deploy time)
- website/hugo.toml: add Builds nav item
Closes#73
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
actions/checkout defaults to fetch-depth: 1 (shallow clone).
generate-changelog runs git log -n 50, so only one entry appeared
in the built app. Fetching 50 commits gives a complete changelog.
Closes#64
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add --no-warn-dirty to all nix develop calls to suppress Git dirty-tree warnings
- Switch integration test reporter from expanded to compact (per-test names suppressed on success)
- Show only summary line on integration test success, matching unit/widget test behavior
Closes#8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
workflow_run is not supported by Forgejo Actions — release.yml never
fired after CI passed. Port the deploy-playstore job into ci.yml with
needs: check + if: main, matching the pattern already used by build-linux.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The U7 onboarding view replaced "No accounts yet." with "Welcome to
SharedInbox", causing the E2E test to spin for the full timeout budget
(pumping slowly in headless CI) before failing. Fix the finder and
bump per-attempt timeout from 240s → 360s and CI job ceiling from
20 min → 30 min to give the full account-add → send → verify flow
room to complete.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Splitting into separate steps breaks the Dart compilation cache that task
check builds up via parallelism. Without the shared cache, flutter test
integration_test/ -d linux rebuilds cold (9+ min instead of ~24s).
Keep the single 'nix develop --command task check' step which runs
analyze+build-linux+test in parallel (Task deps) and warms the cache
before the E2E test. Add timeout-minutes: 20 as a job-level safety net.
The xvfb-run timeout 600 (already in integration_ui_test.sh) still
prevents infinite hangs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sequential CI steps leave the runner under heavier load than the parallel
task check approach, so the E2E test can legitimately take 4-5 min.
Raise timeout 300→600 in integration_ui_test.sh and step timeout 6→12 min.
Job-level ceiling raised to 30 min to match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The assets/ directory is created by generate-changelog. Splitting CI into
separate steps meant analyze ran before any step created it, causing a
pubspec.yaml asset_directory_does_not_exist warning that fails the check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Split single 'Run Full Check Suite' step into named steps so per-step
timing is visible in the CI UI
- Add timeout-minutes: 20 to the overall job and timeout-minutes: 6 to
the UI E2E step — previously a stuck xvfb-run could hang for 23+ min
- Add 'timeout 300' to xvfb-run in integration_ui_test.sh so the E2E
test exits with a clear error instead of hanging indefinitely
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>