Merge branch 'main' into restore/pre-0.9.3-backlog #57
Workflow file for this run
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
| name: Draft Release | ||
|
Check failure on line 1 in .github/workflows/release.yml
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: "Release tag (e.g. v1.2.3)" | ||
| required: true | ||
| type: string | ||
| permissions: | ||
| contents: read | ||
| packages: read | ||
| id-token: none | ||
| actions: read | ||
| attestations: read | ||
| checks: read | ||
| deployments: read | ||
| issues: read | ||
| discussions: read | ||
| pull-requests: read | ||
| repository-projects: read | ||
| security-events: read | ||
| statuses: read | ||
| models: read | ||
| # Job-level permissions grant write scopes only where required. | ||
| concurrency: | ||
| group: release-${{ inputs.tag }} | ||
| cancel-in-progress: false | ||
| jobs: | ||
| resolve-tag: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| outputs: | ||
| commit: ${{ steps.resolve.outputs.commit }} | ||
| steps: | ||
| - name: Checkout main | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: main | ||
| fetch-depth: 0 | ||
| - name: Resolve tag to commit | ||
| id: resolve | ||
| run: | | ||
| git cat-file -e "refs/tags/${{ inputs.tag }}" 2>/dev/null || { | ||
| echo "❌ Tag ${{ inputs.tag }} does not exist" | ||
| exit 1 | ||
| } | ||
| COMMIT=$(git rev-parse "refs/tags/${{ inputs.tag }}^{}") | ||
| echo "commit=$COMMIT" >> $GITHUB_OUTPUT | ||
| echo "Resolved tag ${{ inputs.tag }} to commit $COMMIT" | ||
| # Determines whether this tag should update :latest on GHCR. | ||
| # Runs once; the Docker job consumes its output via matrix. | ||
| determine-latest: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 2 | ||
| outputs: | ||
| value: ${{ steps.is_latest.outputs.value }} | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Check is-latest | ||
| id: is_latest | ||
| run: | | ||
| VALUE=$(python .github/workflows/release/release.py is-latest "${{ inputs.tag }}") | ||
| echo "value=$VALUE" >> $GITHUB_OUTPUT | ||
| # Builds the x64 and arm64 binaries for Linux, for all 3 crates, via the Docker builder | ||
| build-binaries-linux: | ||
| needs: [resolve-tag] | ||
| timeout-minutes: 60 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| target: | ||
| - amd64 | ||
| - arm64 | ||
| name: | ||
| - commit-boost | ||
| include: | ||
| - target: amd64 | ||
| package-suffix: x86-64 | ||
| - target: arm64 | ||
| package-suffix: arm64 | ||
| - name: commit-boost | ||
| target-crate: commit-boost | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ needs.resolve-tag.outputs.commit }} | ||
| fetch-depth: 0 | ||
| submodules: true | ||
| - name: Log commit hash | ||
| run: | | ||
| echo "Releasing commit: $(git rev-parse HEAD)" | ||
| - name: Set lowercase owner | ||
| run: echo "OWNER=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | ||
| - name: Set up QEMU | ||
| uses: docker/setup-qemu-action@v3 | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Build binary (Linux) | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| push: false | ||
| platforms: linux/${{ matrix.target }} | ||
| file: provisioning/build.Dockerfile | ||
| outputs: type=local,dest=build/linux_${{ matrix.target }} | ||
| build-args: | | ||
| TARGET_CRATE=${{ matrix.name }} | ||
| - name: Package binary (Linux) | ||
| run: | | ||
| cd build/linux_${{ matrix.target }} | ||
| tar -czvf ${{ matrix.name }}-${{ inputs.tag }}-linux_${{ matrix.package-suffix }}.tar.gz ${{ matrix.name }} | ||
| mv ${{ matrix.name }}-${{ inputs.tag }}-linux_${{ matrix.package-suffix }}.tar.gz ../../ | ||
| - name: Upload artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ matrix.name }}-${{ inputs.tag }}-linux_${{ matrix.package-suffix }} | ||
| path: | | ||
| ${{ matrix.name }}-${{ inputs.tag }}-linux_${{ matrix.package-suffix }}.tar.gz | ||
| # Builds the arm64 binary for Darwin natively | ||
| build-binaries-darwin: | ||
| needs: [resolve-tag] | ||
| timeout-minutes: 60 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| target: | ||
| # x64 requires macos-latest-large which is not available in the free tier | ||
| # - x86_64-apple-darwin | ||
| - aarch64-apple-darwin | ||
| name: | ||
| - commit-boost | ||
| include: | ||
| # - target: x86_64-apple-darwin | ||
| # os: macos-latest-large | ||
| # package-suffix: x86-64 | ||
| - target: aarch64-apple-darwin | ||
| os: macos-latest | ||
| package-suffix: arm64 | ||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ needs.resolve-tag.outputs.commit }} | ||
| fetch-depth: 0 | ||
| submodules: true | ||
| - name: Log commit hash | ||
| run: | | ||
| echo "Releasing commit: $(git rev-parse HEAD)" | ||
| - name: Install Protoc | ||
| run: | ||
| # Brew's version is much more up to date than the Linux ones, and installing the latest via script runs into curl issues so for now, brew's easier to use | ||
| # provisioning/protoc.sh | ||
| brew install protobuf | ||
| - name: Cache Cargo registry | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ~/.cargo/registry | ||
| key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} | ||
| - name: Cache Cargo index | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ~/.cargo/git | ||
| key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} | ||
| - name: Cache Cargo build | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: target | ||
| key: ${{ runner.os }}-cargo-build-${{ matrix.target }}-${{ matrix.name }}-${{ hashFiles('**/Cargo.lock') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-cargo-build-${{ matrix.target }}-${{ matrix.name }}- | ||
| ${{ runner.os }}-cargo-build-${{ matrix.target }}- | ||
| ${{ runner.os }}-cargo-build- | ||
| - name: Build binary (Darwin) | ||
| run: cargo build --release --target ${{ matrix.target }} --bin ${{ matrix.name }} | ||
| - name: Package binary (Darwin) | ||
| run: | | ||
| cd target/${{ matrix.target }}/release | ||
| tar -czvf ${{ matrix.name }}-${{ inputs.tag }}-darwin_${{ matrix.package-suffix }}.tar.gz ${{ matrix.name }} | ||
| mv ${{ matrix.name }}-${{ inputs.tag }}-darwin_${{ matrix.package-suffix }}.tar.gz ../../../ | ||
| - name: Upload artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ matrix.name }}-${{ inputs.tag }}-darwin_${{ matrix.package-suffix }} | ||
| path: | | ||
| ${{ matrix.name }}-${{ inputs.tag }}-darwin_${{ matrix.package-suffix }}.tar.gz | ||
| # Builds and pushes Docker images for both PBS and Signer | ||
| build-and-push-docker: | ||
| needs: [resolve-tag, build-binaries-linux, determine-latest] | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| strategy: | ||
| matrix: | ||
| crate: [pbs, signer] | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 45 | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ needs.resolve-tag.outputs.commit }} | ||
| fetch-depth: 0 | ||
| submodules: true | ||
| - name: Download binary archives | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| pattern: "commit-boost*" | ||
| - name: Extract binaries | ||
| run: | | ||
| mkdir -p ./artifacts/bin/linux_amd64 | ||
| mkdir -p ./artifacts/bin/linux_arm64 | ||
| tar -xzf ./artifacts/commit-boost-${{ matrix.crate }}-${{ inputs.tag }}-linux_x86-64/commit-boost-${{ matrix.crate }}-${{ inputs.tag }}-linux_x86-64.tar.gz -C ./artifacts/bin | ||
| mv ./artifacts/bin/commit-boost-${{ matrix.crate }} ./artifacts/bin/linux_amd64/commit-boost-${{ matrix.crate }} | ||
| tar -xzf ./artifacts/commit-boost-${{ matrix.crate }}-${{ inputs.tag }}-linux_arm64/commit-boost-${{ matrix.crate }}-${{ inputs.tag }}-linux_arm64.tar.gz -C ./artifacts/bin | ||
| mv ./artifacts/bin/commit-boost-${{ matrix.crate }} ./artifacts/bin/linux_arm64/commit-boost-${{ matrix.crate }} | ||
| - name: Set lowercase owner | ||
| run: echo "OWNER=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | ||
| - name: Set up QEMU | ||
| uses: docker/setup-qemu-action@v3 | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Build and push Docker image | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| push: true | ||
| platforms: linux/amd64,linux/arm64 | ||
| build-args: | | ||
| BINARIES_PATH=./artifacts/bin | ||
| tags: | | ||
| ghcr.io/${{ env.OWNER }}/${{ matrix.crate }}:${{ inputs.tag }} | ||
| ${{ needs.determine-latest.outputs.value == 'true' && format('ghcr.io/{0}/{1}:latest', env.OWNER, matrix.crate) || '' }} | ||
| file: provisioning/${{ matrix.crate }}.Dockerfile | ||
| # Signs all binaries with Sigstore for provenance | ||
| sign-binaries: | ||
| needs: [build-binaries-linux, build-binaries-darwin] | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| steps: | ||
| - name: Download binary artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| pattern: "commit-boost*" | ||
| - name: Sign all binaries with Sigstore | ||
| uses: sigstore/gh-action-sigstore-python@v3.0.0 | ||
| with: | ||
| inputs: ./artifacts/**/*.tar.gz | ||
| - name: Upload signed artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: signed-${{ inputs.tag }} | ||
| path: ./artifacts/**/*.sigstore* | ||
| # Creates a release on GitHub with the binaries | ||
| finalize-release: | ||
| needs: | ||
| - build-binaries-linux | ||
| - build-binaries-darwin | ||
| - build-and-push-docker | ||
| - sign-binaries | ||
| permissions: | ||
| contents: write | ||
| packages: read | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Download binary artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| pattern: "commit-boost*" | ||
| - name: Download signatures | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| pattern: "signatures-${{ github.ref_name }}*" | ||
| - name: Download signed artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| pattern: "signed-*" | ||
| - name: Finalize Release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| files: ./artifacts/**/* | ||
| draft: true | ||
| prerelease: false | ||
| tag_name: ${{ inputs.tag }} | ||
| name: ${{ inputs.tag }} | ||
| env: | ||
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| # Fast-forwards stable (full release) or beta (RC) to the new tag. | ||
| # Runs after all artifacts are built and the draft release is created, | ||
| # so stable/beta are never touched if any part of the pipeline fails. | ||
| fast-forward-branch: | ||
| needs: | ||
| - finalize-release | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/create-github-app-token@v1 | ||
| id: app-token | ||
| with: | ||
| app-id: ${{ secrets.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| - name: Configure git | ||
| run: | | ||
| git config user.name "commit-boost-release-bot[bot]" | ||
| git config user.email "commit-boost-release-bot[bot]@users.noreply.github.com" | ||
| - name: Fast-forward beta branch (RC releases) | ||
| if: contains(github.ref_name, '-rc') | ||
| run: | | ||
| git checkout beta | ||
| git merge --ff-only "${{ github.ref_name }}" | ||
| git push origin beta | ||
| - name: Fast-forward stable branch (full releases) | ||
| if: "!contains(github.ref_name, '-rc')" | ||
| run: | | ||
| git checkout stable | ||
| git merge --ff-only "${{ github.ref_name }}" | ||
| git push origin stable | ||
| # Deletes the tag if any job in the release pipeline fails. | ||
| # This keeps the tag and release artifacts in sync — a tag should only | ||
| # exist if the full pipeline completed successfully. | ||
| # stable/beta are never touched on failure since fast-forward-branch | ||
| # only runs after finalize-release succeeds. | ||
| # | ||
| # Note: if finalize-release specifically fails, a draft release may already | ||
| # exist on GitHub pointing at the now-deleted tag and will need manual cleanup. | ||
| cleanup-on-failure: | ||
| needs: | ||
| - build-binaries-linux | ||
| - build-binaries-darwin | ||
| - sign-binaries | ||
| - build-and-push-pbs-docker | ||
| - build-and-push-signer-docker | ||
| - finalize-release | ||
| - fast-forward-branch | ||
| runs-on: ubuntu-latest | ||
| if: failure() | ||
| steps: | ||
| - uses: actions/create-github-app-token@v1 | ||
| id: app-token | ||
| with: | ||
| app-id: ${{ secrets.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| - name: Delete tag | ||
| run: git push origin --delete ${{ github.ref_name }} | ||