From 2aa8d99f45492920b3e641cbea42ef3a5dd7fb39 Mon Sep 17 00:00:00 2001 From: Steven Gates Date: Mon, 7 Sep 2026 16:18:40 -0500 Subject: [PATCH 1/2] chore: stop ignoring gradle-wrapper.jar The jar is tracked as of the previous commit, so the ignore line is stale and actively misleading: it would force `git add -f` on every wrapper upgrade and invite someone to untrack it again. --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 84bbbe75..1b7cba7a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,10 +24,12 @@ keystore.properties local/ docs/local/ -# Files generated by Gradle +# Files generated by Gradle. NOTE: gradle/wrapper/gradle-wrapper.jar is deliberately TRACKED, not +# ignored — it is what makes ./gradlew work on a clean clone with no Gradle installed, and CI +# cannot build without it. gradle/actions/setup-gradle checksums it against Gradle's published +# hashes on every run, so the usual "don't commit binaries" worry is covered. Do not re-add it here. .gradle /local.properties -/gradle/wrapper/gradle-wrapper.jar # Kotlin build-session data (Kotlin Gradle plugin 2.x) .kotlin/ From 0bbb90bb512200e1b1d3c7f46cff8bc1d813acdf Mon Sep 17 00:00:00 2001 From: Steven Gates Date: Mon, 7 Sep 2026 16:19:36 -0500 Subject: [PATCH 2/2] ci(release): build through the wrapper now that the jar is tracked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With gradle/wrapper/gradle-wrapper.jar committed, ./gradlew works on a clean checkout, so CI uses the same entry point as every other environment instead of installing Gradle separately. Drops the version-reading step — setup-gradle takes the version from the wrapper, and from v4 it also checksums the jar against Gradle's published hashes on every run. chmod stays: git on Windows does not track the executable bit, so gradlew is still mode 100644 in the index. --- .github/workflows/release.yml | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 48ab75fb..d3cf14e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -162,26 +162,11 @@ jobs: - name: Set up Android SDK uses: android-actions/setup-android@v3 - # gradle-wrapper.jar is gitignored in this repo (.gitignore), so ./gradlew has no engine - # behind it on a fresh checkout. Take the version the wrapper pins and have setup-gradle - # provide exactly that — same Gradle the wrapper would have downloaded, read from the same - # file, so upgrading the wrapper still moves CI with it. - - name: Read the pinned Gradle version - id: gradle_version - run: | - set -euo pipefail - version=$(grep -oP 'gradle-\K[0-9.]+(?=-bin\.zip)' gradle/wrapper/gradle-wrapper.properties) - if [[ -z "$version" ]]; then - echo "::error::Could not read the Gradle version from gradle/wrapper/gradle-wrapper.properties." - exit 1 - fi - echo "version=$version" >> "$GITHUB_OUTPUT" - echo "Wrapper pins Gradle $version" - + # Takes the Gradle version from gradle/wrapper/gradle-wrapper.properties, and from v4 also + # checksums gradle-wrapper.jar against Gradle's published hashes on every run — which is what + # makes committing that jar safe. - name: Set up Gradle uses: gradle/actions/setup-gradle@v4 - with: - gradle-version: ${{ steps.gradle_version.outputs.version }} # keystore.properties and google-services.json are both gitignored, so CI has to # reconstitute them. Actions masks these values in the log. @@ -213,7 +198,12 @@ jobs: echo "Keystore opens and contains the alias." - name: Build the release bundle - run: gradle :app:bundleRelease --no-daemon --stacktrace + run: | + set -euo pipefail + # git on Windows does not track the executable bit, so gradlew is mode 100644 in the + # index and arrives non-executable on a Linux runner. Set it rather than assume it. + chmod +x gradlew + ./gradlew :app:bundleRelease --no-daemon --stacktrace - name: Verify the signature id: sign