diff --git a/.github/actions/update-gradle-verification/action.yaml b/.github/actions/update-gradle-verification/action.yaml new file mode 100644 index 00000000..95ca6f19 --- /dev/null +++ b/.github/actions/update-gradle-verification/action.yaml @@ -0,0 +1,110 @@ +name: Update Gradle verification metadata +description: Restore optional previous Gradle verification files, update them, validate them, and upload the result. + +inputs: + output-artifact: + description: Name of the artifact to upload with the updated verification files. + required: true + previous-artifact: + description: Optional previous verification artifact to restore before running Gradle. + required: false + default: '' + clean-start: + description: Remove existing verification files before bootstrapping metadata. + required: false + default: 'false' + cache-gradle-wrapper-distribution: + description: Cache only the Gradle wrapper distribution, not Gradle dependency artifacts. + required: false + default: 'true' + +runs: + using: composite + steps: + - name: Download previous verification files + if: ${{ inputs.previous-artifact != '' }} + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ inputs.previous-artifact }} + path: build/previous-verification + + - name: Restore previous verification files + if: ${{ inputs.previous-artifact != '' }} + shell: bash + run: cp build/previous-verification/gradle/verification-* gradle/ + + - name: Bootstrap verification metadata + shell: bash + run: | + mkdir -p gradle + if [ "${{ inputs.clean-start }}" = "true" ]; then + rm -f gradle/verification-metadata.xml gradle/verification-keyring.keys + fi + if [ ! -f gradle/verification-metadata.xml ]; then + { + printf '%s\n' '' + printf '%s\n' '' + printf '%s\n' ' ' + printf '%s\n' ' true' + printf '%s\n' ' true' + printf '%s\n' ' armored' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' ' ' + printf '%s\n' '' + } > gradle/verification-metadata.xml + fi + + - name: Clear Java tool-cache for reproducibility + shell: bash + run: rm -rf "$RUNNER_TOOL_CACHE"/Java_* + + - name: Set up JDK 25.0.2 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + with: + distribution: temurin + java-version: '25.0.2' + + - name: Cache Gradle wrapper distribution + if: ${{ inputs.cache-gradle-wrapper-distribution == 'true' }} + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ~/.gradle/wrapper/dists + key: gradle-wrapper-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + + - name: Generate dependency verification metadata + shell: bash + run: | + ./gradlew --write-verification-metadata sha512 --refresh-keys \ + dependencies :drongo:dependencies :lark:dependencies jpackageImage + ./gradlew --write-verification-metadata pgp,sha512 --refresh-keys \ + dependencies :drongo:dependencies :lark:dependencies jpackageImage + ./gradlew --export-keys help + + - name: Validate dependency verification metadata + shell: bash + run: | + ./gradlew help dependencies :drongo:dependencies :lark:dependencies \ + --dependency-verification strict --refresh-keys + + - name: Stage verification files + shell: bash + run: | + mkdir -p build/dependency-verification/gradle + cp gradle/verification-metadata.xml build/dependency-verification/gradle/ + cp gradle/verification-keyring.keys build/dependency-verification/gradle/ + + - name: Upload verification files + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: ${{ inputs.output-artifact }} + path: build/dependency-verification + if-no-files-found: error diff --git a/.github/workflows/dependency-verification.yaml b/.github/workflows/dependency-verification.yaml new file mode 100644 index 00000000..92b6a5c3 --- /dev/null +++ b/.github/workflows/dependency-verification.yaml @@ -0,0 +1,186 @@ +name: Dependency Verification + +on: + workflow_dispatch: + schedule: + - cron: '17 3 * * *' + +permissions: + contents: read + +env: + ALLOW_ADDITIONAL_ARTIFACT_CHECKSUMS: 'false' + CLEAN_STALE_VERIFICATION_METADATA: 'false' + CACHE_GRADLE_WRAPPER_DISTRIBUTION: 'true' + +concurrency: + group: dependency-verification-${{ github.ref }} + cancel-in-progress: false + +jobs: + linux-x64: + name: Generate (Linux x64) + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - uses: ./.github/actions/update-gradle-verification + with: + cache-gradle-wrapper-distribution: ${{ env.CACHE_GRADLE_WRAPPER_DISTRIBUTION }} + clean-start: ${{ env.CLEAN_STALE_VERIFICATION_METADATA }} + output-artifact: gradle-verification-linux-x64 + + linux-arm64: + name: Generate (Linux arm64) + runs-on: ubuntu-22.04-arm + needs: linux-x64 + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - uses: ./.github/actions/update-gradle-verification + with: + cache-gradle-wrapper-distribution: ${{ env.CACHE_GRADLE_WRAPPER_DISTRIBUTION }} + previous-artifact: gradle-verification-linux-x64 + output-artifact: gradle-verification-linux-arm64 + + windows-x64: + name: Generate (Windows x64) + runs-on: windows-2022 + needs: linux-arm64 + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - uses: ./.github/actions/update-gradle-verification + with: + cache-gradle-wrapper-distribution: ${{ env.CACHE_GRADLE_WRAPPER_DISTRIBUTION }} + previous-artifact: gradle-verification-linux-arm64 + output-artifact: gradle-verification-windows-x64 + + macos-x64: + name: Generate (macOS x64) + runs-on: macos-15-intel + needs: windows-x64 + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - uses: ./.github/actions/update-gradle-verification + with: + cache-gradle-wrapper-distribution: ${{ env.CACHE_GRADLE_WRAPPER_DISTRIBUTION }} + previous-artifact: gradle-verification-windows-x64 + output-artifact: gradle-verification-macos-x64 + + macos-arm64: + name: Generate (macOS arm64) + runs-on: macos-14 + needs: macos-x64 + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - uses: ./.github/actions/update-gradle-verification + with: + cache-gradle-wrapper-distribution: ${{ env.CACHE_GRADLE_WRAPPER_DISTRIBUTION }} + previous-artifact: gradle-verification-macos-x64 + output-artifact: gradle-verification-final + + update-pr: + name: Open update PR + runs-on: ubuntu-22.04 + needs: macos-arm64 + permissions: + contents: write + pull-requests: write + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + submodules: recursive + + - name: Download final verification files + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: gradle-verification-final + path: build/final-verification + + - name: Create or update pull request + env: + GH_TOKEN: ${{ github.token }} + BRANCH_NAME: automation/update-gradle-verification-metadata + run: | + verification_metadata_diff() { + if git ls-files --error-unmatch gradle/verification-metadata.xml >/dev/null 2>&1; then + git diff -- gradle/verification-metadata.xml + else + git diff --no-index -- /dev/null gradle/verification-metadata.xml || true + fi + } + + reset_verification_files() { + for file in gradle/verification-metadata.xml gradle/verification-keyring.keys; do + if git ls-files --error-unmatch "$file" >/dev/null 2>&1; then + git restore "$file" + else + rm -f "$file" + fi + done + } + + mkdir -p /tmp/dependency-verification/gradle + cp build/final-verification/gradle/verification-* /tmp/dependency-verification/gradle/ + cp /tmp/dependency-verification/gradle/verification-* gradle/ + + if [ -z "$(git status --porcelain -- gradle/verification-metadata.xml gradle/verification-keyring.keys)" ]; then + echo "No dependency verification changes detected." + exit 0 + fi + if [ "$ALLOW_ADDITIONAL_ARTIFACT_CHECKSUMS" != "true" ] && verification_metadata_diff | grep -q '^[+] * /tmp/dependency-verification/existing/gradle/verification-metadata.xml && + git show "refs/remotes/origin/$BRANCH_NAME:gradle/verification-keyring.keys" > /tmp/dependency-verification/existing/gradle/verification-keyring.keys && + cmp -s /tmp/dependency-verification/gradle/verification-metadata.xml /tmp/dependency-verification/existing/gradle/verification-metadata.xml && + cmp -s /tmp/dependency-verification/gradle/verification-keyring.keys /tmp/dependency-verification/existing/gradle/verification-keyring.keys && + git merge-base --is-ancestor HEAD "refs/remotes/origin/$BRANCH_NAME"; then + echo "Existing automation branch already contains these verification changes." + exit 0 + fi + fi + + reset_verification_files + git checkout -B "$BRANCH_NAME" + cp /tmp/dependency-verification/gradle/verification-* gradle/ + git add gradle/verification-metadata.xml gradle/verification-keyring.keys + git commit -m "Update Gradle dependency verification metadata" + git push --force-with-lease origin "HEAD:$BRANCH_NAME" + + if gh pr list --base master --head "$BRANCH_NAME" --json number --jq '.[0].number' | grep -q .; then + echo "Existing dependency verification PR found; branch was updated." + else + gh pr create \ + --base master \ + --head "$BRANCH_NAME" \ + --title "Update Gradle dependency verification metadata" \ + --body "Regenerates Gradle dependency verification metadata across Linux, Windows, and macOS using Gradle's incremental verification metadata update flow." + fi