You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Carved out of #98 (Phase 3, item 13) so the foundation lands as its own small, reviewable PR. Everything else in #98's Phase 3 builds on top of this.
What
Add the repo's first Gradle build/test workflow to GitHub Actions: on every PR and push to main, build the app, run the unit test suite, and produce the lint report. Build + unit tests are hard gates; lint stays advisory per the repo's documented tier design.
Why
There is currently no Gradle workflow in .github/workflows/ (only static-analysis.yml for Markdown, doc-layout.yml, and crashlytics-autotriage.yml). The unit test suite exists and is meaningful (Robolectric + JUnit under app/src/test/), but nothing runs it automatically — a PR that breaks the build or the tests shows green. Same argument as stozo04/stevengates#31: a repo whose README claims Google-grade engineering discipline needs a green check on every commit proving the basics.
Decisions already made by Steven (2026-07-07, in-session) — do not re-litigate
google-services.json in CI: use the REAL file via a repo secret. No dummy/placeholder config. The CI build must be valid and match what ships. Note for the implementer: the build script gracefully skips the Google Services + Crashlytics plugins when the file is absent (app/build.gradle.kts ~line 313: if (file("google-services.json").exists())), so a secretless build would technically pass — that path is NOT acceptable for CI per this decision, because it silently builds a non-production variant. The workflow must materialize the real config from the secret and fail loudly if the secret is missing/empty.
Steven (blocking prerequisite): add the repo secret — from a machine with the real config: gh secret set GOOGLE_SERVICES_JSON --repo stozo04/OpenLoop < app/google-services.json
(The local working copy at the time of writing did NOT contain app/google-services.json — it may need to be re-downloaded from Firebase console → Project settings → your apps. See app/google-services.json.README.)
Workflow.github/workflows/android-ci.yml:
Triggers: pull_request, push: branches: [main], plus workflow_dispatch (matches the repo's existing convention in static-analysis.yml).
actions/checkout → actions/setup-java with temurin JDK 17 (the project pins Java 17: app/build.gradle.kts — jvmToolchain(17), sourceCompatibility = JavaVersion.VERSION_17, with a comment explaining JDK 21 is deliberately avoided; do NOT use 21) → gradle/actions/setup-gradle for dependency + build caching.
Materialize the config: write ${{ secrets.GOOGLE_SERVICES_JSON }} to app/google-services.json; fail with a clear message if empty. Mind fork PRs: secrets are unavailable to PRs from forks — the step should fail with an explanatory message rather than silently building without Crashlytics (repo currently takes PRs from branches, so this is an edge case to document in a workflow comment, not solve).
Upload artifacts: unit test results (app/build/reports/tests/) and the lint report (app/build/reports/lint-results-debug.*). Lint must NOT fail the job — abortOnError = false is already set in app/build.gradle.kts with the rationale "the SKILL decides the PR verdict, not the build"; the workflow surfaces the report for the pr-reviewer skill, nothing more.
A concurrency group keyed on the ref with cancel-in-progress: true so superseded pushes don't queue.
README badge once green, mirroring what stozo04/stevengates#12 did there.
Any change to lint severity or promotion of advisory checks to hard gates.
Verification — required
The workflow runs green on the PR that introduces it (this requires prerequisite 1 to be done first — if the secret is missing, STOP and ask Steven rather than shipping a fallback).
Deliberately breaking a unit test on the branch (then reverting) to prove the gate actually fails — include the red run's link in the PR as evidence, same spirit as stevengates#35's verification section.
Terminal output or screenshot of the artifact listing (test results + lint report) in the PR.
Cache effectiveness noted: cold vs warm run duration.
Process
Same rules as #98: read CLAUDE.md and docs/STATIC_ANALYSIS.md first, verify file/line references against current code, one branch (issue-{N}-android-ci), conventional commits, plan in the PR description, do not merge.
Carved out of #98 (Phase 3, item 13) so the foundation lands as its own small, reviewable PR. Everything else in #98's Phase 3 builds on top of this.
What
Add the repo's first Gradle build/test workflow to GitHub Actions: on every PR and push to
main, build the app, run the unit test suite, and produce the lint report. Build + unit tests are hard gates; lint stays advisory per the repo's documented tier design.Why
There is currently no Gradle workflow in
.github/workflows/(onlystatic-analysis.ymlfor Markdown,doc-layout.yml, andcrashlytics-autotriage.yml). The unit test suite exists and is meaningful (Robolectric + JUnit underapp/src/test/), but nothing runs it automatically — a PR that breaks the build or the tests shows green. Same argument as stozo04/stevengates#31: a repo whose README claims Google-grade engineering discipline needs a green check on every commit proving the basics.Decisions already made by Steven (2026-07-07, in-session) — do not re-litigate
google-services.jsonin CI: use the REAL file via a repo secret. No dummy/placeholder config. The CI build must be valid and match what ships. Note for the implementer: the build script gracefully skips the Google Services + Crashlytics plugins when the file is absent (app/build.gradle.kts~line 313:if (file("google-services.json").exists())), so a secretless build would technically pass — that path is NOT acceptable for CI per this decision, because it silently builds a non-production variant. The workflow must materialize the real config from the secret and fail loudly if the secret is missing/empty.How
gh secret set GOOGLE_SERVICES_JSON --repo stozo04/OpenLoop < app/google-services.json(The local working copy at the time of writing did NOT contain
app/google-services.json— it may need to be re-downloaded from Firebase console → Project settings → your apps. Seeapp/google-services.json.README.).github/workflows/android-ci.yml:pull_request,push: branches: [main], plusworkflow_dispatch(matches the repo's existing convention instatic-analysis.yml).actions/checkout→actions/setup-javawith temurin JDK 17 (the project pins Java 17:app/build.gradle.kts—jvmToolchain(17),sourceCompatibility = JavaVersion.VERSION_17, with a comment explaining JDK 21 is deliberately avoided; do NOT use 21) →gradle/actions/setup-gradlefor dependency + build caching.${{ secrets.GOOGLE_SERVICES_JSON }}toapp/google-services.json; fail with a clear message if empty. Mind fork PRs: secrets are unavailable to PRs from forks — the step should fail with an explanatory message rather than silently building without Crashlytics (repo currently takes PRs from branches, so this is an edge case to document in a workflow comment, not solve)../gradlew :app:assembleDebug :app:testDebugUnitTest :app:lintDebug --stacktraceapp/build/reports/tests/) and the lint report (app/build/reports/lint-results-debug.*). Lint must NOT fail the job —abortOnError = falseis already set inapp/build.gradle.ktswith the rationale "the SKILL decides the PR verdict, not the build"; the workflow surfaces the report for the pr-reviewer skill, nothing more.concurrencygroup keyed on the ref withcancel-in-progress: trueso superseded pushes don't queue.Explicitly out of scope (stays in #98)
Verification — required
Process
Same rules as #98: read
CLAUDE.mdanddocs/STATIC_ANALYSIS.mdfirst, verify file/line references against current code, one branch (issue-{N}-android-ci), conventional commits, plan in the PR description, do not merge.