name: Set up Java and Gradle description: >- Installs the repository's pinned Temurin JDK, then configures Gradle through the official setup-gradle action — which validates every checked-in wrapper jar and manages the Gradle cache. Every Gradle job used to carry the JDK block verbatim, so the JDK patch level lived in fifty-nine places; every job also carried a separate three-line wrapper-validation step, so the pinned action SHA lived in forty. # Wrapper validation is INSIDE this action now. # # It could not be before, and the reason was not a GitHub limitation: .github/scripts/ # verify-gradle-wrapper.sh read every workflow job and required it to contain, literally and in this # order, an `actions/checkout@` step, the exact three-field pinned wrapper-validation step, and then # the Gradle invocation. That literalness was the whole guard — "this job validated the wrapper" had # to be answerable from the workflow file alone — and it is what made the step uninlineable. # # That script is gone (it also byte-hashed all twelve workflow files, so a comment change needed a # hash update, while an attacker with write access would simply have updated both). The guarantee it # was protecting is now the official action's own: `gradle/actions/setup-gradle` validates all # wrapper jars by default (`validate-wrappers`, default true), and the action is pinned to a full # commit SHA here — which GitHub's own hardening guide calls the only immutable action reference. # # `actions/checkout` still cannot move here: a `./.github/actions/...` reference is resolved from the # checked-out working copy, so this file does not exist until checkout has already run. A composite # action cannot contain the step that makes itself readable. # # So a Gradle job is two lines — checkout, then this action. runs: using: composite steps: - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # actions/setup-java@v4.7.1 with: distribution: temurin java-version: "21.0.11+10" # Gradle's own caching, not setup-java's `cache: gradle`. The two cache the same directory with # different keys, and running both is how a job restores one cache and saves the other. - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # gradle/actions@v6 with: build-scan-publish: false cache-read-only: ${{ github.ref != 'refs/heads/main' }}