Commit Graph
448 Commits
Author SHA1 Message Date
Thomas SharedInbox 1393a31d61 ci: empty commit to verify pub get fully cached after date_created fix 2026-05-19 18:45:40 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 59dfb0cfb3 fix(ci): also strip date_created from .flutter-plugins-dependencies
flutter pub get writes a date_created timestamp into .flutter-plugins-
dependencies in addition to the generated field in package_config.json.
Both files are part of the pub-get execution snapshot, so both timestamps
must be removed to make the layer deterministic and cacheable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:33:20 +02:00
Thomas SharedInbox df0c3910cb ci: empty commit to verify pub get determinism caching 2026-05-19 17:59:50 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 4daf47f7a3 fix(ci): make pub get layer deterministic to enable test caching
Remove non-deterministic "generated" and "generatorVersion" fields from
.dart_tool/package_config.json after flutter pub get, so the snapshot
hash is stable across runs and all downstream test steps can be cached.
Mount only .dart_tool/build as a mutable cache volume so the incremental
build graph persists without polluting the deterministic snapshot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 17:39:20 +02:00
Thomas SharedInbox dd9bd24f09 perf(ci): cache pub get separately from source to fix downstream cache misses
flutter pub get embeds a timestamp in .dart_tool/package_config.json, making
its output snapshot non-deterministic and busting the cache for dart format,
flutter analyze, unit tests, mocks, and integration tests on every run.

Fix: isolate pub get into its own layer using only pubspec.yaml + pubspec.lock
as inputs, then normalise the generated timestamp. setup() now overlays the
full source on top of this stable layer before running build_runner.

Result: on an empty commit, all steps downstream of pub get should be cached.
2026-05-19 16:59:19 +02:00
Thomas SharedInbox 1e0679c324 ci: second empty commit — sdkmanager should be cached now 2026-05-19 16:06:21 +02:00
Thomas SharedInbox d826522072 ci: empty commit to verify sdkmanager cache after GC policy fix 2026-05-19 15:55:18 +02:00
Thomas SharedInbox ec60566a33 ci: empty commit to verify Dagger cache after disk pressure resolved 2026-05-19 14:21:16 +02:00
Thomas SharedInbox 00625e318a ci: empty commit to verify SDK pre-install caching 2026-05-19 11:57:49 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 354f7959f6 fix(ci): pre-install Android SDK components in container layer
Cache volumes for NDK/CMake proved unreliable on the remote Dagger
engine: the android-ndk-cache volume was empty on each run, causing
Gradle to re-download NDK + CMake + build-tools + platform during every
`flutter build appbundle` (~3-4 min of extra downloads).

Pre-install all four SDK components via sdkmanager in Base() so Dagger's
execution cache captures them. Base() is CACHED on subsequent runs with
identical inputs, eliminating the per-run SDK downloads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:35:44 +02:00
Thomas SharedInbox 75a7b947cd ci: retry after transient ghcr.io 502 2026-05-19 11:11:54 +02:00
Thomas SharedInbox fda0210bd0 ci: empty commit to verify source-scoped Dagger cache hits 2026-05-19 11:09:15 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 9e709873b9 refactor(ci): scope source inputs per pipeline — android/linux builds no longer bust on unrelated changes
Base() no longer mounts m.Source. Each function gets only the files it
needs via a narrow filter, so Dagger's content-addressed cache is scoped
correctly: changing website/, scripts/, or stalwart-dev/ no longer
invalidates the Android or Linux build cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 10:52:57 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 45c3a8088b ci: empty commit to verify Dagger cache hits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:44:30 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 f60beaa199 fix: XmlNode.element is at proto field 1, not 2 — versionCode patch was silently skipping all elements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:49:10 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 d9cde7cacf debug: dump manifest proto structure when versionCode not found
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:23:44 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 bb163542bb fix: add versionCode read-back verification and handle fixed-width wire types
- _parse now handles wire types 1 (fixed64) and 5 (fixed32) so it doesn't
  crash on unknown fields in the manifest proto
- _patch_prim patches both int_decimal_value (field 6) and int_hexadecimal_value
  (field 7) — AAPT2 may use either
- patch() reads versionCode before and after patching and exits with a clear
  error if the patch didn't take effect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:11:20 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 8319002e0c fix: use publish-android task for Play Store deploy (stamps + signs + uploads)
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>
2026-05-18 16:42:23 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 02e8c2200a fix: fail fast with clear error when keystore secrets are empty
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:17:41 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 8518715bcf ci: retrigger to verify Dagger cache hits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:54:23 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 2d559d4947 feat: cache Android AAB build; stamp versionCode + resign after cache hit
BuildAndroidRelease() drops all params and builds with --build-number 1
(no keystore injected, Gradle uses debug signing). The command is now
stable across all commits — full Dagger cache hit whenever source is
unchanged.

Three new Dagger functions handle the post-cache steps:
- StampAndroidVersionCode(aab, versionCode): pure-stdlib Python patches
  the AAB's compiled manifest proto (android:versionCode resource ID
  0x0101021b) and strips META-INF/ to clear the old signature.
- SignAndroidBundle(aab, keystoreBase64, keystorePassword): decodes the
  base64 keystore secret and re-signs with jarsigner.
- PublishAndroid(ctx, playStoreConfig, keystoreBase64, keystorePassword):
  chains all three + UploadToPlayStore, computing time.Now().Unix() as
  the versionCode internally.

Taskfile: build-android-bundle simplified (no keystore params); publish-
android now calls publish-android in a single Dagger call instead of the
two-step build-then-upload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:35:20 +02:00
Thomas GüttlerandClaude Sonnet 4.6 f6bb6aed82 ci: empty commit to verify Dagger cache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:34:21 +02:00
Thomas GüttlerandClaude Sonnet 4.6 007e7b57f1 fix: revert CacheSharingModeLocked to fix deadlock in Check()
Locked exclusive cache access caused concurrent Dagger operations inside
Check() to deadlock waiting on each other, resulting in a 60-minute timeout.
Shared mode is correct here — cache volumes are pre-warmed so pub get is fast.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:19:41 +02:00
Thomas GüttlerandClaude Sonnet 4.6 0ea06e8634 fix: use CacheSharingModeLocked instead of dagger.Locked
dagger.Locked is not exported in this SDK version; the correct
constant is dagger.CacheSharingModeLocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 10:16:02 +02:00
Thomas GüttlerandClaude Sonnet 4.6 592efae934 perf: lock cache volumes and add --no-pub to fix Dagger cache misses
flutter pub get was not being cached by Dagger because the pub-cache
CacheVolume used Shared mode: concurrent writes from the check and
deploy-playstore jobs made the mount non-deterministic, causing a cache
miss on every run. Locked mode gives each operation exclusive access so
the output snapshot is stable and Dagger can cache subsequent steps.

Also add --no-pub to both flutter build commands: pub get already ran
explicitly in Setup(), so skipping it again inside the build step avoids
a duplicate network-touching operation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:45:39 +02:00
Thomas GüttlerandClaude Sonnet 4.6 9466f03936 perf: use commit timestamp as build number to enable Dagger cache hits
$(date +%s) changed every run, making the flutter build WithExec args
unique each time and busting the Dagger layer cache (500s build every run).

$(git log -1 --format=%ct HEAD) is stable for the same commit, so a
retry of a failed upload gets a full cache hit on the build step.
Still monotonically increasing across commits, satisfying Play Store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:20:05 +02:00
Thomas Güttler b79ea77f69 ci: empty commit to measure cache performance 2026-05-18 09:06:56 +02:00
Thomas GüttlerandClaude Sonnet 4.6 ef8268a41e fix: rename duplicate build-android-bundle task to build-android-bundle-local
The old fvm-based task had the same name as the new Dagger-based one,
causing go-task to error immediately (1-second CI failure).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:37:18 +02:00
Thomas GüttlerandClaude Sonnet 4.6 8783bcf5f0 fix: unique build number and split build/upload steps
- 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>
2026-05-18 08:18:33 +02:00
Thomas GüttlerandClaude Sonnet 4.6 484a183a19 fix: pass release keystore into Dagger Android builds
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>
2026-05-18 07:49:45 +02:00
Thomas GüttlerandClaude Sonnet 4.6 3c403369fb ci: verify keystore SHA1 before Play Store build
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>
2026-05-18 07:20:25 +02:00
Thomas Güttler 24cafd1a93 ci: retrigger to capture Play Store error with debug logging 2026-05-18 06:25:12 +02:00
Thomas Güttler 2cc6188a43 fix: log HTTP status and response body on Play Store upload failure
Without the response body we can't tell why Google Play rejects the
upload. Logs the status code and first 500 bytes of the response for
both the init POST and the upload PUT on each failed attempt. Also
moves the init call inside the try/except so init failures are retried.
2026-05-18 05:49:55 +02:00
Thomas Güttler 83654fb4c9 fix: re-initialize resumable upload URL on each retry attempt
The resumable upload URL returned by Google Play is session-specific and
expires after a failed attempt. Retrying with the same URL always fails.
Also broadens the caught exception from HTTPError to RequestException so
timeouts and connection errors are retried too.
2026-05-18 05:06:42 +02:00
Thomas Güttler 0733a4bf8a ci: trigger run after runner security fix 2026-05-17 22:58:11 +02:00
Thomas Güttler 21cc94110d Revert "ci: switch to codeberg-small runner to avoid workspace permission failure"
This reverts commit 32b465bd1a.
2026-05-17 22:50:18 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 32b465bd1a ci: switch to codeberg-small runner to avoid workspace permission failure
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>
2026-05-17 22:36:26 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 91ec75c82f ci: restore Dagger & Task installation steps for Docker-based runner
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>
2026-05-17 22:23:49 +02:00
Thomas SharedInbox c712199d0b feat: decrease dagger output size with -q and DAGGER_NO_NAG=1 (#124)
Add -q (quiet) flag to all dagger call invocations to suppress INFO-level
engine messages while keeping warnings and errors visible. Set DAGGER_NO_NAG=1
globally to suppress the Dagger Cloud tracing nag line. --progress=plain
is retained on all calls as required.
2026-05-17 22:15:25 +02:00
Thomas GüttlerandClaude Sonnet 4.6 5562f82f35 ci: rename runner label from dagger-dagger to ubuntu-latest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:11:57 +02:00
Gemini CLI 6863e309cd ci: use sharedinbox-runner for GitHub Actions 2026-05-17 22:02:02 +02:00
Gemini CLI 896886e130 ci: trigger run for dagger-dagger switch 2026-05-17 22:00:13 +02:00
Gemini CLI 9f636a992d ci: switch to dagger-dagger runner and remove manual setup steps 2026-05-17 21:53:44 +02:00
Gemini CLI b76b05307a ci: install Dagger and Task to local bin to avoid sudo issues 2026-05-17 21:52:11 +02:00
Gemini CLI 0a121979f8 ci: use sudo for Dagger and Task installation on self-hosted runner 2026-05-17 21:51:27 +02:00
Gemini CLI a617af70d5 ci: use ubuntu-latest runner for Forgejo workflows 2026-05-17 21:50:00 +02:00
Gemini CLI 9a0cb93970 ci: switch back to codeberg-small and rely on Dagger NDK caching 2026-05-17 19:43:09 +02:00
Gemini CLI cd0a807cb2 ci: switch to codeberg-medium runner and fix fetch-depth for website build 2026-05-17 19:41:51 +02:00
Gemini CLI f93198c0ca ci: optimize Android NDK installation and switch to ubuntu-latest runner 2026-05-17 19:39:46 +02:00
Gemini CLI 146baa50ea fix: include website directory in Dagger source filter 2026-05-17 18:18:16 +02:00