# Builds the release source package in CI for a draft release (typically # created via support/release.py), uploads the zip to that release, and # attaches a SLSA v1.0 provenance attestation generated by the OpenSSF # slsa-github-generator. The maintainer reviews the draft (which by then has # both the zip and *.intoto.jsonl attached) and clicks Publish to finalize. # # This makes the provenance attest to the actual build that produced the # artifact, rather than just attesting to a hash observed after the fact. # # GitHub does not fire `release: created` for draft releases, so release.py # triggers this workflow explicitly via workflow_dispatch, passing the tag to # attach to and the ref to build from. The `release: created` trigger is kept # for non-draft releases created directly through the GitHub UI. name: release on: release: types: [created] workflow_dispatch: inputs: tag_name: description: "Release tag to attach the artifacts to (e.g. 12.2.0)" required: true type: string ref: description: "Git ref to build the source package from" required: false default: release type: string permissions: read-all jobs: build: name: Build source package runs-on: ubuntu-latest permissions: contents: write outputs: hashes: ${{ steps.hash.outputs.hashes }} package: ${{ steps.build.outputs.package }} tag: ${{ steps.vars.outputs.tag }} steps: - name: Resolve tag and ref for both event types id: vars run: | echo "tag=${{ github.event.release.tag_name || inputs.tag_name }}" >> "$GITHUB_OUTPUT" echo "ref=${{ github.event.release.target_commitish || inputs.ref }}" >> "$GITHUB_OUTPUT" - name: Checkout the release ref uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: ref: ${{ steps.vars.outputs.ref }} persist-credentials: false - name: Build source zip via CPack id: build run: | cmake -B build . cmake --build build --target package_source pkg=$(ls build/fmt-*.zip) test -f "$pkg" echo "package=$pkg" >> "$GITHUB_OUTPUT" - name: Compute base64-encoded SHA-256 subjects id: hash run: | file="${{ steps.build.outputs.package }}" subjects=$(cd "$(dirname "$file")" && sha256sum "$(basename "$file")") echo "hashes=$(printf '%s' "$subjects" | base64 -w0)" >> "$GITHUB_OUTPUT" - name: Upload zip to the release env: GH_TOKEN: ${{ github.token }} run: | gh release upload "${{ steps.vars.outputs.tag }}" \ "${{ steps.build.outputs.package }}" \ --repo "${{ github.repository }}" --clobber # Generate the provenance only; do not let the generator upload it. With # upload-assets, the generator creates and publishes its own release (and # tag) to host the attestation, which duplicates our draft. Instead we # download the attestation artifact and attach it to the draft below. provenance: needs: [build] permissions: actions: read id-token: write contents: read uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 with: base64-subjects: ${{ needs.build.outputs.hashes }} provenance-name: "fmt-${{ needs.build.outputs.tag }}.intoto.jsonl" upload-assets: false attach-provenance: name: Attach provenance to the release needs: [build, provenance] runs-on: ubuntu-latest permissions: contents: write steps: - name: Download the provenance attestation uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ needs.provenance.outputs.provenance-name }} - name: Attach provenance to the draft release env: GH_TOKEN: ${{ github.token }} run: | gh release upload "${{ needs.build.outputs.tag }}" \ "${{ needs.provenance.outputs.provenance-name }}" \ --repo "${{ github.repository }}" --clobber