ci: move workflow actions off the deprecated Node 20 runtime - #48
Merged
Conversation
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
v2.5.0+35release run warned that four actions target Node 20 and are being force-run on Node 24, and thatsetup-javav4 is EOL. Builds pass today; this closes it out before the forced-migration window does.actions/checkoutactions/setup-javagradle/actions/setup-gradlecache-provider: basicactions/upload-artifactsoftprops/action-gh-releaseEvery one of these majors is a Node 20 → 24 runtime bump. I read the release notes for each; none changes an input this repo passes. Specifically:
pull_request_targetandworkflow_run— neither workflow uses those events (CI is onpull_request).archiveinput and leavesname/path/if-no-files-found/retention-daysuntouched.ubuntu-latestis well past that.setup-gradle: v6 with
cache-provider: basicv6 moved the default caching implementation into
gradle-actions-caching, a proprietary component governed by Gradle's commercial Terms of Use. An earlier revision of this PR stopped at v5 to avoid that. Two things make v6 the better call:v5.0.2(2026-02-23);v6.0.0landed a month later and there has been nothing on v5 since. v6.0.0's notes cite dependency updates for security vulnerabilities — so pinning v5 would fix the Node 20 deprecation by parking on a branch that gets no security updates.cache-providerselects betweenenhanced(default, the commercial component) andbasic(the open-source GitHub Actions cache implementation).cache-provider: basictherefore gets Node 24, an actively maintained line, security updates and caching, without accepting those terms:basicBoth workflows set the input explicitly and comment why, because the failure mode is silent: deleting the line 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-daemonand never enabled the configuration cache, so that costs nothing here.Verification
Workflow YAML parses cleanly with the expected structure (ci: 1 job / 6 steps; release: 1 job / 8 steps). The real check is CI on this PR.
Caveat: this PR exercises
ci.ymlonly.release.ymlruns on tag pushes, so its changes stay unverified until the next release tag — worth knowing if the next release is time-sensitive. The changes are identical in kind to the ones CI does cover.