Android/F-Droid release tooling + widget-test harness repair #706

Merged
raisondetredev merged 5 commits from refs/pull/706/head into main 2026-07-01 00:20:42 +02:00
raisondetredev commented 2026-07-01 00:15:42 +02:00 (Migrated from codeberg.org)

Android / F-Droid release tooling

  • build(android): release builds sign with the release keystore when HALKYON_KEYSTORE_PASSWORD is set (the publish path provides it via pass-cli); otherwise they fall back to debug signing, so local --release runs and IDE Gradle syncs work without the keystore. The previous variant threw on any release build lacking the password, which blocked local release runs.
  • scripts/flutter.sh: one wrapper with a leading --signed flag — default injects non-secret config from .env/dev.json (no keystore, no Proton Pass prompt); --signed resolves .env/.env.build via pass-cli for release-signed builds.
  • pubspec → 0.1.0+2: pre-1.0 versioning while the app is unstable; v0.1.0 is the first F-Droid release.

Widget-test harness repair (14 pre-existing VM failures)

Recent feature merges outgrew their test harnesses and surfaced two latent production bugs:

  • main.dart (real bug): the GoRouter is built in didChangeDependencies (not a late-final initialiser), so dispose() never calls DependenciesScope.of(context) on a deactivated element. The pomodoro clock is read in build() and closed over, rather than via DependenciesScope.of inside BlocProvider.create (provider forbids listening lookups there — it threw under asserts/widget tests).
  • grammar_enablement: grammarGatewayIfEnabled uses DependenciesScope.maybeOf, so a scope-less thin widget test degrades to "no grammar" instead of throwing.
  • app_router_test: provides the app-level PomodoroBloc above the routes and stubs the Home PdfDeadlinesOverviewBloc's watchDueCountsByPdf subscription.
  • Dictionary gateway injectable via Dependencies: dictionaryGateway is an optional param defaulting to the Supabase-backed gateway (production and the ~45 other test sites unchanged), and the studyset language picker reads it — letting the previously-skipped "attach a reference dictionary across the subtree" test drive the real picker through a mock.

Full suite: 3854 passed, 0 skipped, 0 failed.

Notes

  • Rebased onto current main (incl. #704); the only conflict was the MaterialApp.router block in main.dart — kept #704's device-locale delegates plus the _router! null-check from the dispose fix.
  • The v0.1.0 tag points at the pre-rebase release commit; re-tag after merge (especially if squashed).
## Android / F-Droid release tooling - **build(android):** release builds sign with the release keystore when `HALKYON_KEYSTORE_PASSWORD` is set (the publish path provides it via pass-cli); otherwise they fall back to debug signing, so local `--release` runs and IDE Gradle syncs work without the keystore. The previous variant threw on any release build lacking the password, which blocked local release runs. - **`scripts/flutter.sh`:** one wrapper with a leading `--signed` flag — default injects non-secret config from `.env/dev.json` (no keystore, no Proton Pass prompt); `--signed` resolves `.env/.env.build` via pass-cli for release-signed builds. - **pubspec → 0.1.0+2:** pre-1.0 versioning while the app is unstable; `v0.1.0` is the first F-Droid release. ## Widget-test harness repair (14 pre-existing VM failures) Recent feature merges outgrew their test harnesses and surfaced two latent production bugs: - **`main.dart` (real bug):** the `GoRouter` is built in `didChangeDependencies` (not a late-final initialiser), so `dispose()` never calls `DependenciesScope.of(context)` on a deactivated element. The pomodoro clock is read in `build()` and closed over, rather than via `DependenciesScope.of` inside `BlocProvider.create` (provider forbids listening lookups there — it threw under asserts/widget tests). - **`grammar_enablement`:** `grammarGatewayIfEnabled` uses `DependenciesScope.maybeOf`, so a scope-less thin widget test degrades to "no grammar" instead of throwing. - **`app_router_test`:** provides the app-level `PomodoroBloc` above the routes and stubs the Home `PdfDeadlinesOverviewBloc`'s `watchDueCountsByPdf` subscription. - **Dictionary gateway injectable via `Dependencies`:** `dictionaryGateway` is an optional param defaulting to the Supabase-backed gateway (production and the ~45 other test sites unchanged), and the studyset language picker reads it — letting the previously-skipped "attach a reference dictionary across the subtree" test drive the real picker through a mock. Full suite: **3854 passed, 0 skipped, 0 failed.** ## Notes - Rebased onto current `main` (incl. #704); the only conflict was the `MaterialApp.router` block in `main.dart` — kept #704's device-locale delegates plus the `_router!` null-check from the dispose fix. - The `v0.1.0` tag points at the pre-rebase release commit; re-tag after merge (especially if squashed).
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
project-halkyon/halkyon-learn!706
No description provided.