From a4de28b11cab5dc767f253e4b748b1cd87737ade Mon Sep 17 00:00:00 2001 From: Khoa Truong Date: Mon, 10 Aug 2026 14:23:57 -0700 Subject: [PATCH 1/2] ci: move workflow actions off the deprecated Node 20 runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v2.5.0+35 release run warned that checkout@v4, setup-java@v4, setup-gradle@v4 and action-gh-release@v2 all target Node 20 and were being force-run on Node 24, and that setup-java v4 is EOL. Builds still pass, but the forced-migration window closes eventually. actions/checkout v4 -> v7 actions/setup-java v4 -> v5 gradle/actions/setup-gradle v4 -> v5 (not v6 — see below) actions/upload-artifact v4 -> v7 softprops/action-gh-release v2 -> v3 Every one of these majors is a Node 20 -> 24 runtime bump; none changes an input this repo passes. checkout v7 also blocks fork checkouts for pull_request_target and workflow_run, neither of which these workflows use. upload-artifact v7 adds an optional `archive` input and leaves name/path/if-no-files-found/retention-days untouched. All require runner >= 2.327.1, which GitHub-hosted ubuntu-latest is well past. **setup-gradle deliberately stops at v5, not the latest v6.** v6 extracts caching into `gradle-actions-caching`, a proprietary component governed by Gradle's commercial Terms of Use instead of the MIT licence, and using v6 with caching enabled accepts those terms. v5 is the last MIT line and already runs on Node 24, so it fully resolves the deprecation without taking on a licensing commitment on behalf of an OSS project. Both workflows carry a comment saying so, with a link to Gradle's blog post, so the next person doesn't "helpfully" bump it. Note this PR exercises ci.yml only — release.yml runs on tag pushes, so its changes stay unverified until the next release tag. --- .github/workflows/ci.yml | 12 ++++++++---- .github/workflows/release.yml | 11 +++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b88cb22..60d335f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,18 +14,22 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - uses: actions/checkout@v7 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' - - uses: gradle/actions/setup-gradle@v4 + # Deliberately v5, not the latest v6: v6 extracts caching into `gradle-actions-caching`, + # a proprietary component under Gradle's commercial Terms of Use rather than the MIT + # licence. v5 is the last MIT line and already runs on Node 24, which is all this bump + # needs. Read https://blog.gradle.org/github-actions-for-gradle-v6 before moving to v6. + - uses: gradle/actions/setup-gradle@v5 - name: Unit tests run: ./gradlew --no-daemon testDebugUnitTest - name: Build debug APK run: ./gradlew --no-daemon :app:assembleDebug - name: Upload test APK - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: pulseloop-debug-apk path: app/build/outputs/apk/debug/*.apk diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f28c063..a430150 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Parse version from tag id: ver @@ -39,12 +39,15 @@ jobs: echo "prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT" echo "Building versionName=$NAME versionCode=$CODE prerelease=$PRERELEASE" - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' - - uses: gradle/actions/setup-gradle@v4 + # Deliberately v5, not the latest v6 — see the note in ci.yml: v6's caching moved to a + # proprietary component under Gradle's commercial Terms of Use. v5 is the last MIT line + # and already runs on Node 24. + - uses: gradle/actions/setup-gradle@v5 - name: Decode release keystore env: @@ -93,7 +96,7 @@ jobs: ls -la dist - name: Create / update release and attach APKs - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: tag_name: ${{ github.ref_name }} name: PulseLoop ${{ steps.ver.outputs.name }} (${{ steps.ver.outputs.code }}) From 2549598eaf5590e13fc67590350c6397e49db0e0 Mon Sep 17 00:00:00 2001 From: Khoa Truong Date: Tue, 11 Aug 2026 04:06:42 -0700 Subject: [PATCH 2/2] ci: take setup-gradle v6 with the open-source cache provider Supersedes this branch's earlier decision to stop at v5. Two things made that the wrong call: **v5 is a dead line.** Last release v5.0.2 (2026-02-23); v6.0.0 landed a month later and there has been nothing on v5 since. v6.0.0's notes cite dependency updates for security vulnerabilities. Pinning v5 would have fixed the Node 20 deprecation by parking on a branch that gets no security updates. **v6 has an open-source caching mode**, which the earlier note missed. The licensing concern was real but the choice it implied was false: `cache-provider` selects between 'enhanced' (default, the proprietary `gradle-actions-caching` under Gradle's commercial Terms of Use) and 'basic' (the open-source GitHub Actions cache implementation). Setting it to 'basic' gets Node 24, an actively maintained line, security updates and caching, without accepting those terms. Both workflows set it explicitly and say why, because the failure mode is silent: deleting the input doesn't break the build, it just opts into the commercial component on the next run. v6 also drops the rudimentary configuration-cache support pending a reimplementation. These workflows run --no-daemon and never enabled the configuration cache, so that costs nothing here. --- .github/workflows/ci.yml | 15 ++++++++++----- .github/workflows/release.yml | 9 +++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60d335f..fd2a2b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,11 +19,16 @@ jobs: with: distribution: temurin java-version: '17' - # Deliberately v5, not the latest v6: v6 extracts caching into `gradle-actions-caching`, - # a proprietary component under Gradle's commercial Terms of Use rather than the MIT - # licence. v5 is the last MIT line and already runs on Node 24, which is all this bump - # needs. Read https://blog.gradle.org/github-actions-for-gradle-v6 before moving to v6. - - uses: gradle/actions/setup-gradle@v5 + # `cache-provider: basic` is load-bearing, not a tuning knob. v6 moved the default caching + # implementation into `gradle-actions-caching`, a proprietary component governed by Gradle's + # commercial Terms of Use (https://blog.gradle.org/github-actions-for-gradle-v6); 'basic' is + # the open-source GitHub-Actions-cache implementation and keeps this repo off those terms. + # Don't drop this line to "take the default" — that silently opts into the commercial + # component. (v5 was the last fully-MIT line but is dead: v5.0.2, 2026-02, no security + # updates since.) + - uses: gradle/actions/setup-gradle@v6 + with: + cache-provider: basic - name: Unit tests run: ./gradlew --no-daemon testDebugUnitTest - name: Build debug APK diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a430150..a51a017 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,10 +44,11 @@ jobs: distribution: temurin java-version: '17' - # Deliberately v5, not the latest v6 — see the note in ci.yml: v6's caching moved to a - # proprietary component under Gradle's commercial Terms of Use. v5 is the last MIT line - # and already runs on Node 24. - - uses: gradle/actions/setup-gradle@v5 + # cache-provider: basic — see the note in ci.yml. Keeps caching on the open-source + # implementation rather than v6's default commercial `gradle-actions-caching`. + - uses: gradle/actions/setup-gradle@v6 + with: + cache-provider: basic - name: Decode release keystore env: