Skip to content

ci: check every pull request - #12

Merged
whtis merged 3 commits into
mainfrom
ci/pr-checks
Jul 16, 2026
Merged

ci: check every pull request#12
whtis merged 3 commits into
mainfrom
ci/pr-checks

Conversation

@whtis

@whtis whtis commented Jul 16, 2026

Copy link
Copy Markdown
Owner

The repo had no PR checks — release.yml only runs on a tag, so nothing stood between a pull request and main.
v1.2.0 shipped two bugs that had been sitting in released code for two months, and both were found by hand.

Jobs

Each is a separate signal, so a red run says what broke.

job what it does
wrapper validates gradle-wrapper.jar against known checksums
build assembleDebug, uploads the APK
test testDebugUnitTest, uploads reports even on failure
lint lintDebug, uploads HTML reports even on failure
release-metadata scripts/check_release_metadata.py

The metadata check

A release has to agree across four places, and every way of getting it wrong is quiet:

  • app/build.gradle.kts — versionCode / versionName
  • fastlane/metadata/android/{locale}/changelogs/N.txt — named by versionCode; a missing file shows the store nothing
  • version.json — read by the in-app update check; stale means every user is told to "update" to what they already run
  • CHANGELOG.md — section + link reference

Cutting v1.2.0 by hand needed all four kept in step, and the changelog still went out at 948 chars against the
stores' 500-char cap. Runs locally too: python3 scripts/check_release_metadata.py

Two existing violations this surfaced

Adding the checks immediately caught real problems, both fixed in their own commits here:

  • lintDebug fails on the current treeaccess_token_label, use_access_token, use_password have no zh
    entry, so the auth screen's token/password toggle renders in English on Chinese devices. This is why lint couldn't
    just be switched on.
  • the v1.2.0 en-US changelog was 948 chars, nearly double the store limit — it would have been truncated
    mid-sentence. Every other changelog in the repo is 104-379.

Fork PRs

google-services.json is gitignored but the plugin needs it to configure, so the setup action writes a placeholder
when the secret isn't readable — otherwise every fork PR would fail before compiling. Nothing in CI talks to Firebase.
Verified by building against the placeholder with the real file moved aside.

Gradle cache is read-only off main, so a PR can't poison what main restores.

Verification

  • assembleDebug + testDebugUnitTest + lintDebug all green locally against the placeholder google-services.json
  • metadata script negative-tested: exits 1 on a version.json mismatch, on a versionCode with no changelog, and on an
    over-length changelog; exits 0 once restored
  • and this PR is the check's own first run

🤖 Generated with Claude Code

https://claude.ai/code/session_01RZ9mXqLfk6PKwo8V9pVDEC

whtis and others added 3 commits July 17, 2026 01:06
access_token_label, use_access_token and use_password had no zh entry, so the
token/password toggle on the auth screen rendered in English on Chinese devices.

Android lint has been reporting these as MissingTranslation errors — lintDebug
fails on the current tree because of them, which is what kept lint out of CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RZ9mXqLfk6PKwo8V9pVDEC
It was 948 characters. F-Droid and Play both cap a changelog at 500 and
truncate past it, which would have cut the entry off mid-sentence — every
other changelog in the repo lands between 104 and 379.

Trimmed to 492, keeping the image fix and the "re-add and they will stick"
advice, which is the part a reader needs to act on.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RZ9mXqLfk6PKwo8V9pVDEC
The repo had no PR checks — release.yml only runs on a tag, so nothing stood
between a pull request and main. v1.2.0 shipped two bugs that had been sitting
in released code for two months, and both were found by hand.

Four jobs, each a separate signal so a red run says what broke:

  wrapper           validate gradle-wrapper.jar against the known checksums
  build             assembleDebug, uploads the APK
  test              testDebugUnitTest, uploads reports even on failure
  lint              lintDebug, uploads HTML reports even on failure
  release-metadata  scripts/check_release_metadata.py

The metadata check is the repo-specific one. A release has to agree across
app/build.gradle.kts, fastlane changelogs named by versionCode, version.json,
and CHANGELOG.md, and every way of getting that wrong is quiet: a missing
changelogs/N.txt shows the store nothing, a stale version.json prompts every
user to "update" to the version they already run. Cutting v1.2.0 by hand needed
all four kept in step, and the changelog still went out over the store's
500-char cap. The script also runs locally: python3 scripts/check_release_metadata.py

google-services.json is gitignored but the plugin needs it to configure, so the
setup action writes a placeholder when the secret isn't readable — otherwise
every fork PR would fail before compiling. Nothing in CI talks to Firebase.
Verified by building against the placeholder with the real file moved aside.

Gradle cache is read-only off main, so a PR can't poison what main restores.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RZ9mXqLfk6PKwo8V9pVDEC
@whtis
whtis merged commit cecf963 into main Jul 16, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant