ci: leave release-please's scaffold.json bump out of oxfmt (#284) #9
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
| # Same-run Rust release: release-please owns version, tag, and a draft Release; | |
| # verify and build legs run downstream in this run; the archives are attested in | |
| # the no-compile upload-assets job; the terminal job verifies every remote asset | |
| # and flips the draft. Requires .github/scripts/resolve-release-gate.sh and | |
| # .github/scripts/publish-release-draft.sh from the shared asset set. | |
| name: Release | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| description: "Existing draft release tag to rebuild, for example v1.2.3" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| BINARY_NAME: codegraph | |
| CRATE_NAME: codegraph-rs | |
| CARGO_TERM_COLOR: always | |
| CARGO_INCREMENTAL: 0 | |
| SCCACHE_GHA_ENABLED: "true" | |
| RUSTC_WRAPPER: sccache | |
| jobs: | |
| release-please: | |
| name: Release Please | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| outputs: | |
| build_artifacts: ${{ steps.gate.outputs.build_artifacts }} | |
| prerelease: ${{ steps.gate.outputs.prerelease }} | |
| release_sha: ${{ steps.gate.outputs.release_sha }} | |
| tag_name: ${{ steps.gate.outputs.tag_name }} | |
| version: ${{ steps.gate.outputs.version }} | |
| steps: | |
| - name: Run release-please | |
| id: release | |
| if: github.event_name == 'push' | |
| uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| config-file: release-please-config.json | |
| manifest-file: .release-please-manifest.json | |
| - name: Checkout release tooling | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ github.sha }} | |
| persist-credentials: false | |
| - name: Resolve release gate | |
| id: gate | |
| shell: bash | |
| env: | |
| DEFAULT_BRANCH: main | |
| EVENT_NAME: ${{ github.event_name }} | |
| GH_TOKEN: ${{ github.token }} | |
| INPUT_TAG: ${{ inputs.tag_name }} | |
| REF_PROTECTED: ${{ github.ref_protected }} | |
| RELEASE_CREATED: ${{ steps.release.outputs.release_created }} | |
| RELEASE_SHA: ${{ steps.release.outputs.sha }} | |
| RELEASE_TAG: ${{ steps.release.outputs.tag_name }} | |
| RELEASE_VERSION: ${{ steps.release.outputs.version }} | |
| REPO: ${{ github.repository }} | |
| RUN_REF: ${{ github.ref }} | |
| run: bash .github/scripts/resolve-release-gate.sh | |
| source-gate: | |
| name: Release Source Gate | |
| needs: release-please | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout release tag | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ needs.release-please.outputs.tag_name }} | |
| persist-credentials: false | |
| - name: Require the tag to resolve to the release commit | |
| shell: bash | |
| env: | |
| RELEASE_SHA: ${{ needs.release-please.outputs.release_sha }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$(git rev-parse HEAD)" != "$RELEASE_SHA" ]; then | |
| echo "::error title=Release source::checked-out tag differs from the release commit" | |
| exit 1 | |
| fi | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master 2026-08-21 | |
| with: | |
| toolchain: 1.96.0 | |
| - name: Require the version gate's parser | |
| run: command -v jq >/dev/null 2>&1 || { echo "jq is required"; exit 1; } | |
| # The first Cargo subprocess in a release is the non-mutating version gate. | |
| - name: Verify workspace version surfaces | |
| run: bash scripts/check-workspace-versions.sh | |
| verify-ci: | |
| name: Verify CI Passed | |
| needs: release-please | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 35 | |
| permissions: | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout release tag | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ needs.release-please.outputs.tag_name }} | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Require the tag to resolve to the release commit | |
| shell: bash | |
| env: | |
| RELEASE_SHA: ${{ needs.release-please.outputs.release_sha }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$(git rev-parse HEAD)" != "$RELEASE_SHA" ]; then | |
| echo "::error title=Release CI::checked-out tag differs from the release commit" | |
| exit 1 | |
| fi | |
| - name: Wait for exact-SHA CI Success | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| HEAD_SHA: ${{ needs.release-please.outputs.release_sha }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| run_id="" | |
| for _ in $(seq 1 120); do | |
| run_id=$(gh api "repos/${REPO}/actions/runs?head_sha=${HEAD_SHA}&event=push&branch=main&per_page=100" \ | |
| --jq '[.workflow_runs[] | select(.name == "CI")] | sort_by(.created_at) | last | .id // empty') | |
| [ -z "$run_id" ] || break | |
| sleep 15 | |
| done | |
| if [ -z "$run_id" ]; then | |
| echo "::error title=Release CI::no CI push run found for ${HEAD_SHA}" | |
| exit 1 | |
| fi | |
| for _ in $(seq 1 120); do | |
| job=$(gh api "repos/${REPO}/actions/runs/${run_id}/jobs?per_page=100" \ | |
| --jq '[.jobs[] | select(.name == "CI Success")] | last // {}') | |
| status=$(jq -r '.status // empty' <<<"$job") | |
| conclusion=$(jq -r '.conclusion // empty' <<<"$job") | |
| if [ "$status" != completed ]; then | |
| sleep 15 | |
| continue | |
| fi | |
| if [ "$conclusion" = success ]; then | |
| echo "CI Success passed for exact release SHA ${HEAD_SHA} (run ${run_id})." | |
| exit 0 | |
| fi | |
| echo "::error title=Release CI::CI Success concluded ${conclusion:-<missing>} for ${HEAD_SHA}" | |
| exit 1 | |
| done | |
| echo "::error title=Release CI::timed out waiting for CI Success in run ${run_id}" | |
| exit 1 | |
| verify: | |
| name: Verify release tag | |
| needs: [release-please, source-gate] | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout release tag | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ needs.release-please.outputs.tag_name }} | |
| persist-credentials: false | |
| - name: Require the tag to resolve to the release commit | |
| shell: bash | |
| env: | |
| RELEASE_SHA: ${{ needs.release-please.outputs.release_sha }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$(git rev-parse HEAD)" != "$RELEASE_SHA" ]; then | |
| echo "::error title=Release verify::checked-out tag differs from the release commit" | |
| exit 1 | |
| fi | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master 2026-08-21 | |
| with: | |
| toolchain: 1.96.0 | |
| components: rustfmt,clippy | |
| - name: Verify workspace version surfaces before Cargo/cache | |
| run: bash scripts/check-workspace-versions.sh | |
| - name: Cache Rust artifacts | |
| uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| with: | |
| shared-key: cargo-home-${{ runner.os }}-${{ runner.arch }} | |
| cache-targets: false | |
| - name: Configure compiler cache | |
| uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 | |
| with: | |
| version: "v0.16.0" | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "24" | |
| - name: Install verification tools | |
| run: npm install --global oxfmt@0.64.0 | |
| - name: Install pinned actionlint | |
| run: bash .github/scripts/install-actionlint.sh | |
| - name: Require fixture parsers and shell linter | |
| run: | | |
| set -euo pipefail | |
| command -v shellcheck >/dev/null 2>&1 || { echo "shellcheck is required"; exit 1; } | |
| python3 -c 'import yaml' \ | |
| || python3 -m pip install --break-system-packages PyYAML==6.0.3 \ | |
| || python3 -m pip install PyYAML==6.0.3 | |
| - name: Check | |
| run: make check | |
| - name: Install cargo-audit | |
| uses: taiki-e/install-action@a2a5f6e99e1a31540baa0468acfa302cff0f359f # v2.86.4 | |
| with: | |
| tool: cargo-audit@0.22.2 | |
| - name: Audit dependencies | |
| run: cargo audit | |
| build-binaries: | |
| name: Build ${{ matrix.target }} | |
| needs: [release-please, source-gate] | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| # Build legs execute build scripts and dependency code, so they hold no | |
| # id-token or attestations permission; upload-assets attests the archives. | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: x86_64-unknown-linux-musl | |
| runner: ubuntu-24.04 | |
| platform: linux | |
| use_zigbuild: true | |
| archive: tar.gz | |
| - target: aarch64-unknown-linux-musl | |
| runner: ubuntu-24.04-arm | |
| platform: linux | |
| use_zigbuild: true | |
| archive: tar.gz | |
| - target: x86_64-apple-darwin | |
| runner: macos-15 | |
| platform: macos | |
| execution_arch: x86_64 | |
| use_zigbuild: false | |
| archive: tar.gz | |
| - target: aarch64-apple-darwin | |
| runner: macos-15 | |
| platform: macos | |
| execution_arch: arm64 | |
| use_zigbuild: false | |
| archive: tar.gz | |
| - target: x86_64-pc-windows-msvc | |
| runner: windows-2025 | |
| platform: windows | |
| use_zigbuild: false | |
| archive: zip | |
| - target: aarch64-pc-windows-msvc | |
| runner: windows-11-arm | |
| platform: windows | |
| use_zigbuild: false | |
| archive: zip | |
| steps: | |
| - name: Checkout release tag | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ needs.release-please.outputs.tag_name }} | |
| persist-credentials: false | |
| - name: Require the tag to resolve to the release commit | |
| shell: bash | |
| env: | |
| RELEASE_SHA: ${{ needs.release-please.outputs.release_sha }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$(git rev-parse HEAD)" != "$RELEASE_SHA" ]; then | |
| echo "::error title=Release build::checked-out tag differs from the release commit" | |
| exit 1 | |
| fi | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master 2026-08-21 | |
| with: | |
| toolchain: 1.96.0 | |
| targets: ${{ matrix.target }} | |
| - name: Verify workspace version surfaces before Cargo/cache | |
| shell: bash | |
| run: bash scripts/check-workspace-versions.sh | |
| - name: Cache Rust artifacts | |
| uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| with: | |
| shared-key: cargo-home-${{ runner.os }}-${{ runner.arch }} | |
| key: ${{ matrix.target }} | |
| cache-targets: false | |
| cache-workspace-crates: false | |
| - name: Configure compiler cache | |
| uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 | |
| with: | |
| version: "v0.16.0" | |
| - name: Install Zig | |
| if: matrix.use_zigbuild | |
| uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 | |
| with: | |
| version: 0.15.1 | |
| - name: Install cargo-zigbuild | |
| if: matrix.use_zigbuild | |
| uses: taiki-e/install-action@a2a5f6e99e1a31540baa0468acfa302cff0f359f # v2.86.4 | |
| with: | |
| tool: cargo-zigbuild@0.23.0 | |
| - name: Populate the Cargo registry | |
| run: cargo fetch --locked | |
| - name: Compute the archive name once | |
| id: names | |
| shell: bash | |
| env: | |
| ARCHIVE_KIND: ${{ matrix.archive }} | |
| TARGET: ${{ matrix.target }} | |
| VERSION: ${{ needs.release-please.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| echo "archive=${BINARY_NAME}-${VERSION}-${TARGET}.${ARCHIVE_KIND}" >>"$GITHUB_OUTPUT" | |
| - name: Build with cargo-zigbuild | |
| if: matrix.use_zigbuild | |
| shell: bash | |
| env: | |
| TARGET: ${{ matrix.target }} | |
| run: cargo zigbuild --locked --release --timings -p "$CRATE_NAME" --target "$TARGET" | |
| - name: Build natively | |
| if: ${{ !matrix.use_zigbuild }} | |
| shell: bash | |
| env: | |
| TARGET: ${{ matrix.target }} | |
| run: cargo build --locked --release --timings -p "$CRATE_NAME" --target "$TARGET" | |
| - name: Package and unpack tar.gz | |
| if: matrix.archive == 'tar.gz' | |
| shell: bash | |
| env: | |
| ARCHIVE: ${{ steps.names.outputs.archive }} | |
| TARGET: ${{ matrix.target }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p dist unpacked | |
| tar -czf "dist/${ARCHIVE}" -C "target/${TARGET}/release" "$BINARY_NAME" | |
| tar -xzf "dist/${ARCHIVE}" -C unpacked | |
| chmod +x "unpacked/$BINARY_NAME" | |
| - name: Package and unpack zip | |
| if: matrix.archive == 'zip' | |
| shell: pwsh | |
| env: | |
| ARCHIVE: ${{ steps.names.outputs.archive }} | |
| TARGET: ${{ matrix.target }} | |
| run: | | |
| New-Item -ItemType Directory -Force -Path dist,unpacked | Out-Null | |
| Compress-Archive ` | |
| -Path "target/${env:TARGET}/release/${env:BINARY_NAME}.exe" ` | |
| -DestinationPath "dist/${env:ARCHIVE}" | |
| Expand-Archive -Path "dist/${env:ARCHIVE}" -DestinationPath unpacked -Force | |
| - name: Smoke packaged artifact on Linux | |
| if: matrix.platform == 'linux' | |
| shell: bash | |
| run: '"unpacked/$BINARY_NAME" --version' | |
| - name: Smoke packaged artifact on macOS | |
| if: matrix.platform == 'macos' | |
| shell: bash | |
| env: | |
| EXECUTION_ARCH: ${{ matrix.execution_arch }} | |
| run: | | |
| set -euo pipefail | |
| /usr/bin/lipo "unpacked/$BINARY_NAME" -verify_arch "$EXECUTION_ARCH" | |
| /usr/bin/arch "-${EXECUTION_ARCH}" "unpacked/$BINARY_NAME" --version | |
| - name: Smoke packaged artifact on Windows | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: '& "unpacked/${env:BINARY_NAME}.exe" --version' | |
| - name: Upload smoked build artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: dist-${{ matrix.target }} | |
| path: dist/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Collect compiler-cache statistics | |
| if: always() | |
| shell: bash | |
| run: | | |
| mkdir -p diagnostics | |
| sccache --show-stats --stats-format=json >diagnostics/sccache-stats.json || true | |
| - name: Upload build diagnostics | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: diagnostics-${{ matrix.target }} | |
| path: | | |
| target/cargo-timings/*.html | |
| diagnostics/ | |
| if-no-files-found: warn | |
| retention-days: 3 | |
| upload-assets: | |
| name: Attach release assets | |
| needs: [release-please, source-gate, verify-ci, verify, build-binaries] | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| # Downloads, hashes, attests, and uploads; executes no project code, so it | |
| # is the only job holding id-token: write. | |
| permissions: | |
| attestations: write | |
| contents: write | |
| id-token: write | |
| steps: | |
| - name: Checkout release tooling | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ github.sha }} | |
| persist-credentials: false | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: dist-* | |
| path: dist | |
| merge-multiple: true | |
| - name: Generate SHA256SUMS | |
| shell: bash | |
| working-directory: dist | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| archives=(*.tar.gz *.zip) | |
| ((${#archives[@]} > 0)) || { echo "::error::no release archives found"; exit 1; } | |
| printf '%s\n' "${archives[@]}" | LC_ALL=C sort | xargs sha256sum >SHA256SUMS | |
| - name: Attest release archives | |
| uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2 | |
| with: | |
| subject-checksums: dist/SHA256SUMS | |
| - name: Attach assets to draft | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TAG: ${{ needs.release-please.outputs.tag_name }} | |
| run: | | |
| set -euo pipefail | |
| mapfile -t files < <(awk '{ print "dist/" $2 }' dist/SHA256SUMS) | |
| gh release upload "$TAG" "${files[@]}" dist/SHA256SUMS \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --clobber | |
| - name: Verify remote asset bytes | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| TAG: ${{ needs.release-please.outputs.tag_name }} | |
| run: | | |
| bash .github/scripts/publish-release-draft.sh --verify-only \ | |
| --checksums dist/SHA256SUMS --asset dist/SHA256SUMS --exact | |
| - name: Upload checksums for the publish job | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: checksums | |
| path: dist/SHA256SUMS | |
| if-no-files-found: error | |
| retention-days: 1 | |
| publish-release: | |
| name: Publish Release | |
| needs: [release-please, upload-assets] | |
| if: needs.release-please.outputs.build_artifacts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| environment: release | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout release tooling | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ github.sha }} | |
| persist-credentials: false | |
| - name: Download checksums | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: checksums | |
| path: dist | |
| - name: Verify remote assets and publish the draft | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| TAG: ${{ needs.release-please.outputs.tag_name }} | |
| run: | | |
| bash .github/scripts/publish-release-draft.sh --publish \ | |
| --checksums dist/SHA256SUMS --asset dist/SHA256SUMS --exact |