Compare commits

..
Author SHA1 Message Date
guettlibot 412c8883bc chore: drop dead DAGGER_HOST export from dev shell
The shellHook exported DAGGER_HOST=unix:///run/dagger/engine.sock, but
DAGGER_HOST is a legacy variable that dagger 0.21 ignores (the runner is
selected via _EXPERIMENTAL_DAGGER_RUNNER_HOST), and that socket path only
exists on the remote engine host — locally it is never present. The line
did nothing except imply the client was wired to an engine when it was
not. Remove it so the dev shell relies on dagger's normal runner
selection (runner host if set, otherwise local docker/podman).
2026-06-07 22:14:36 +02:00
guettlibot c1a24fedfd fix: skip dart-check pre-commit hook when no Dagger engine is available
The dart-check hook runs `dagger call ... check-fast`, which needs a
Dagger engine. On a dev machine or in CI the engine is provisioned from
a local container runtime (docker/podman) or reached via
_EXPERIMENTAL_DAGGER_RUNNER_HOST. In engine-less sandboxes (the agentloop
agent pods that commit on our behalf) none of those exist, so dagger
falls back to its default engine image reference and aborts with:

    start engine: driver for scheme "image" was not available

That failed every commit the agent tried to make.

Wrap the hook in scripts/precommit_dart_check.sh, which probes for a
reachable engine (runner host set, or a working docker/podman daemon)
and, when none is found, warns and exits 0 instead of failing. Codeberg
CI still runs check-fast on every push, so the check is not lost.
2026-06-07 21:59:47 +02:00
4 changed files with 43 additions and 73 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ repos:
- id: dart-check
name: dart format (autofix) + check-fast (parallel)
language: system
entry: bash -c 'cd "$(git rev-parse --show-toplevel)" && nix develop --command dagger call --progress=plain -q -m ci --source=. check-fast'
entry: bash -c 'cd "$(git rev-parse --show-toplevel)" && scripts/precommit_dart_check.sh'
pass_filenames: false
always_run: true
- id: ci-no-direct-dagger
-69
View File
@@ -1,69 +0,0 @@
## Background — what already exists in this repo
The Android AAB build-and-upload pipeline is already fully automated. The user does **not** need to drop a file into Play Console at all — the same machinery that publishes to `internal` can publish to the closed-testing track.
- `ci/main.go:952``PublishAndroid()` builds a release AAB, stamps the versionCode (`time.Now().Unix()`), re-signs with the upload key, and uploads to Play Store.
- `ci/main.go:899``UploadToPlayStore()` invokes `scripts/deploy_playstore.py` inside a container.
- `scripts/deploy_playstore.py:14` — pinned to `TRACK = "internal"`. This is the only thing limiting the existing pipeline to internal testing.
- `Taskfile.yml:230``task publish-android` wraps the Dagger call.
- `.forgejo/workflows/deploy.yml``deploy-playstore` job runs every hour (`0 * * * *`) and calls `task publish-android` whenever android-relevant files changed since the last successful deploy.
- `Taskfile.yml:214``task build-android-bundle` builds an **unsigned** AAB locally to `build/app/outputs/bundle/release/app-release.aab`. The signed AAB built by `PublishAndroid` lives only inside Dagger and is **not** currently exported to disk on the runner.
## Recommended path (A): publish to the closed-testing track from CI — no manual upload
This piggybacks on what's already running every hour.
1. **In Play Console**, decide which track maps to "closed testing":
- The built-in `alpha` track is treated as closed testing by the API.
- Or create a custom closed-testing track (e.g. `closed-testers`) under Testing → Closed testing → Create track. Configure the testers list there. Note the track ID exactly as it appears in the URL/console.
2. **Edit `scripts/deploy_playstore.py`** so the upload goes to both internal and the closed track in the same Play edit (one commit, atomic). Concretely:
- Replace `TRACK = "internal"` (line 14) with `TRACKS = ["internal", "alpha"]` (or `["internal", "<custom-track-id>"]`).
- Replace the single `track_resp = session.put(... /tracks/{TRACK} ...)` block (lines 97-101) with a loop that PUTs the same `versionCodes: [version_code]` payload to each track in `TRACKS` before the commit at line 104.
- Internal stays as the smoke-test target; the closed track is what gets the testers.
3. **Update the test fixture** in `scripts/test_deploy_playstore.py` (and any test for `verify_playstore_deploy.py`) to expect the new track list. Run `python3 scripts/test_deploy_playstore.py` locally.
4. **Trigger a deploy**: push the change to `main` and either wait for the next hourly run or `workflow_dispatch` `.forgejo/workflows/deploy.yml` from the Forgejo UI. Note that `deploy.yml:114` already includes `scripts/deploy_playstore\.py` in the change-detection regex, so any normal hourly tick after the merge will pick it up.
5. **Result**: closed-testing release appears in Play Console with the AAB pre-attached. Reviewers only need to edit the release notes (already generated by `task generate-changelog` — see `Taskfile.yml:232`) and click "Roll out". No "Drop app bundles here" step.
Caveat — first time a track is used, Google requires that internal testing has been previously published; that is already true here, so no blocker.
## Alternative path (B): one-shot manual drop — export the signed AAB as a CI artifact
Use this if you want to do this single closed-testing release by hand and decide on full automation later.
1. **Modify `ci/main.go`** to expose the signed AAB as a file return: add a thin wrapper exporting the result of `SignAndroidBundle(StampAndroidVersionCode(BuildAndroidRelease(commitHash), versionCode), ...)` as `*dagger.File` (something like `SignedAndroidBundle(...) *dagger.File`). The existing `PublishAndroid` discards the signed bundle after upload, so a separate entry point is cleaner than reshaping it.
2. **Add a `Taskfile.yml` target** `build-android-bundle-signed` that calls the new Dagger function with `-o build/app/outputs/bundle/release/app-release.aab` (mirroring `build-android-bundle` at `Taskfile.yml:218`).
3. **Add to `.forgejo/workflows/deploy.yml` `deploy-playstore` job** (after `task publish-android`) — or to a new dedicated job — these two steps:
```yaml
- name: Export signed AAB locally
env: { DAGGER_NO_NAG: "1" }
run: task build-android-bundle-signed
- name: Upload AAB artifact
uses: actions/upload-artifact@v4
with:
name: app-release-aab
path: build/app/outputs/bundle/release/app-release.aab
if-no-files-found: error
```
4. **Trigger the workflow** (`workflow_dispatch`), then download `app-release-aab` from the run's artifacts page on Forgejo. Drop it into Play Console.
Risk to flag: the version code stamped via the artifact path must be strictly greater than every version code already on internal. Since the same Unix-timestamp scheme is used everywhere this naturally holds, but if the artifact run and a regular publish run race, the closed release may fail with "Version code N has already been used." Easy fix: only run one or the other.
## Alternative path (C): build locally — fastest one-off
```bash
export ANDROID_KEYSTORE_BASE64=... # same secret used by CI
bash scripts/build_android_bundle_local.sh
```
AAB lands at `build/app/outputs/bundle/release/app-release.aab`. Note this script uses `fvm flutter build appbundle` directly and does **not** match the Dagger pipeline's stamp/sign step exactly — the keystore path is wired via `ANDROID_KEYSTORE_PATH` and the signing config in `android/app/build.gradle.kts` reads from there. Verify the bundle is correctly signed (`jarsigner -verify -verbose -certs`) before uploading.
## Recommendation
Go with path A. The diff is small (~10 lines in `deploy_playstore.py` + test update), reuses the build-and-sign pipeline that has already been proven in `deploy.yml` for months, and removes the "Drop app bundles here" step entirely instead of just satisfying it once.
-3
View File
@@ -124,9 +124,6 @@
# nix develop --command does not set IN_NIX_SHELL; set it so _preflight passes in CI
export IN_NIX_SHELL=1
# Point Dagger client at the running engine socket
export DAGGER_HOST=unix:///run/dagger/engine.sock
# Disable Flutter telemetry inside dev shell
export FLUTTER_SUPPRESS_ANALYTICS=true
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Pre-commit wrapper for the `dart-check` hook.
#
# `dagger call ... check-fast` needs a Dagger engine. On a dev machine or in
# CI that engine is provisioned from a local container runtime (docker/podman)
# or reached through _EXPERIMENTAL_DAGGER_RUNNER_HOST. In engine-less sandboxes
# (e.g. the agentloop agent pods that commit on our behalf) none of those
# exist, so dagger falls back to its default engine image reference and aborts
# with:
# start engine: driver for scheme "image" was not available
# which blocked every commit the agent tried to make.
#
# Codeberg CI still runs check-fast on every push, so skipping here is safe:
# warn loudly and let the commit through when no engine can be reached.
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
# True when dagger has some way to reach/provision an engine.
engine_available() {
# A shared engine reached over the wire wins outright.
[ -n "${_EXPERIMENTAL_DAGGER_RUNNER_HOST:-}" ] && return 0
# Otherwise dagger provisions the engine from a local container runtime.
# `info` (not `version`) confirms the daemon is actually reachable; cap it
# with a timeout so a stale docker context cannot hang the commit.
if command -v docker >/dev/null 2>&1 && timeout 10 docker info >/dev/null 2>&1; then
return 0
fi
if command -v podman >/dev/null 2>&1 && timeout 10 podman info >/dev/null 2>&1; then
return 0
fi
return 1
}
if ! engine_available; then
echo "WARNING: no Dagger engine available (no container runtime, and" \
"_EXPERIMENTAL_DAGGER_RUNNER_HOST is unset); skipping dart-check." \
"Codeberg CI still runs check-fast on push." >&2
exit 0
fi
exec nix develop --command dagger call --progress=plain -q -m ci --source=. check-fast