feat(crafting-schema): support schema v2 during attestation process (… #298
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: Build, Package and Release | |
| on: | |
| push: | |
| tags: | |
| - "v*.*.*" | |
| # https://github.com/ossf/scorecard/blob/7ed886f1bd917d19cb9d6ce6c10e80e81fa31c39/docs/checks.md#token-permissions | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| uses: chainloop-dev/chainloop/.github/workflows/test.yml@main | |
| init_attestation: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write # required for SLSA provenance - https://docs.chainloop.dev/guides/slsa/ | |
| needs: test | |
| if: github.ref_type == 'tag' # Guard to make sure we are releasing once | |
| outputs: | |
| attestation_id: ${{ steps.init_attestation.outputs.attestation_id }} | |
| steps: | |
| - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
| - name: Install Chainloop | |
| run: | | |
| curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s | |
| - name: Initialize Attestation | |
| id: init_attestation | |
| run: | | |
| attestation_id=$(chainloop attestation init --workflow ${CHAINLOOP_WORKFLOW_NAME} --project ${CHAINLOOP_PROJECT_NAME} --release --remote-state -o json | jq -r .attestationID) | |
| echo "attestation_id=$attestation_id" >> $GITHUB_OUTPUT | |
| env: | |
| CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }} | |
| CHAINLOOP_WORKFLOW_NAME: "release" | |
| CHAINLOOP_PROJECT_NAME: "chainloop" | |
| release: | |
| name: Release CLI and control-plane/artifact-cas container images | |
| needs: init_attestation | |
| runs-on: ubuntu-latest | |
| if: github.ref_type == 'tag' # Guard to make sure we are releasing once | |
| permissions: | |
| contents: write # required for goreleaser to upload the release assets | |
| packages: write # to push container images | |
| pull-requests: write | |
| id-token: write # required for SLSA provenance | |
| attestations: write # required for SLSA provenance | |
| env: | |
| CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }} | |
| ATTESTATION_ID: ${{ needs.init_attestation.outputs.attestation_id }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| outputs: | |
| attestation_hash: ${{ steps.attest_goreleaser.outputs.attestation_hash }} | |
| steps: | |
| - name: Install Cosign | |
| uses: sigstore/cosign-installer@ef6a6b364bbad08abd36a5f8af60b595d12702f8 # main | |
| with: | |
| cosign-release: "v2.2.3" | |
| - name: Install Chainloop | |
| run: | | |
| curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s | |
| - name: Checkout | |
| uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
| - name: Docker login to Github Packages | |
| uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Go | |
| uses: actions/setup-go@be3c94b385c4f180051c996d336f57a34c397495 # v3.6.1 | |
| with: | |
| go-version: "1.25.0" | |
| # install qemu binaries for multiarch builds (needed by goreleaser/buildx) | |
| - name: Setup qemu | |
| id: qemu | |
| uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 | |
| - name: Install Syft | |
| run: | | |
| # Install Syft | |
| wget --no-verbose https://raw.githubusercontent.com/anchore/syft/c43f4fb416c34c1c4b3997373689d8d4c0fb9b36/install.sh -O - | sh -s -- -b /usr/local/bin | |
| - name: Run GoReleaser | |
| id: release | |
| uses: goreleaser/goreleaser-action@b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757 # v3.2.0 | |
| with: | |
| distribution: goreleaser | |
| version: latest | |
| args: release --clean | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} | |
| COSIGN_KEY: ${{ secrets.COSIGN_KEY }} | |
| POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} | |
| POSTHOG_ENDPOINT: ${{ secrets.POSTHOG_ENDPOINT }} | |
| - name: Generate SBOMs, upload to release and attest | |
| id: attest_goreleaser | |
| env: | |
| SYFT_GOLANG_SEARCH_REMOTE_LICENSES: "true" | |
| run: | | |
| # goreleaser output resides in dist/artifacts.json | |
| # Attest all built containers and manifests | |
| images=$(cat dist/artifacts.json | jq -r '.[] | select(.type=="Docker Image" or .type=="Docker Manifest") | .path') | |
| for entry in $images; do | |
| # exclude latest tag | |
| if [[ $entry != *latest ]]; then | |
| material_name="$(echo $entry | sed 's#.*/##')" | |
| # Extract repository with tag from the full image path (format: ghcr.io/org/repo:tag) | |
| repo_with_tag="$(echo $entry | awk -F'/' '{print $4}')" | |
| # Extract just the repository name by splitting at the colon and taking the first part | |
| repo_name="$(echo $repo_with_tag | awk -F':' '{print $1}')" | |
| # Extract the tag by splitting at the colon and taking the second part | |
| tag="$(echo $repo_with_tag | awk -F':' '{print $2}')" | |
| # Extract the architecture from the tag (assumed to be the last part after the dash) | |
| # and replace dots with dashes for consistency | |
| arch="$(echo $tag | awk -F'-' '{print $NF}' | tr '.' '-')" | |
| container_name="${repo_name}-${arch}" | |
| sbom_name="${repo_name}-sbom-${arch}" | |
| syft -o cyclonedx-json=/tmp/sbom-$material_name.cyclonedx.json $entry | |
| chainloop attestation add --name $container_name --value $entry --kind CONTAINER_IMAGE --attestation-id ${{ env.ATTESTATION_ID }} | |
| chainloop attestation add --name $sbom_name --value /tmp/sbom-$material_name.cyclonedx.json --kind SBOM_CYCLONEDX_JSON --attestation-id ${{ env.ATTESTATION_ID }} | |
| # Upload the SBOM to the release | |
| gh release upload ${{ github.ref_name }} /tmp/sbom-$material_name.cyclonedx.json --clobber | |
| fi | |
| done | |
| # Attest the cli binaries | |
| binaries=$(cat dist/artifacts.json | jq -r '.[] | select(.type=="Binary" and .extra.ID!="binaries-cli") | select(.path | startswith("dist/cli")) | .path') | |
| echo "$binaries" | while IFS= read -r entry; do | |
| # Extract OS and ARCH | |
| os_arch=$(echo "$entry" | sed -E 's|dist/cli_([^_]+)_([^/_]+).*|\1-\2|') | |
| # Format as chainloop-OS-ARCH | |
| material_name="chainloop-$os_arch" | |
| chainloop attestation add --name $material_name --value $entry --kind ARTIFACT --attestation-id ${{ env.ATTESTATION_ID }} | |
| done | |
| - name: Include source code on attestation | |
| run: | | |
| # This needs to run AFTER goreleaser to make sure the source code is available | |
| gh release download ${{ github.ref_name }} -A tar.gz -O /tmp/source-code.tar.gz | |
| chainloop attestation add --name source-code --value /tmp/source-code.tar.gz --kind ARTIFACT --attestation-id ${{ env.ATTESTATION_ID }} | |
| - name: Bump Chart and Dagger Version | |
| run: .github/workflows/utils/bump-chart-and-dagger-version.sh deployment/chainloop extras/dagger ${{ github.ref_name }} | |
| - name: Bump Project Version | |
| run: .github/workflows/utils/bump-project-version.sh | |
| - name: Create Pull Request | |
| uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2 | |
| with: | |
| commit-message: Bump Chart and Dagger Version ${{ github.ref_name }} | |
| signoff: true | |
| base: main | |
| title: Bump Helm Chart and Dagger Version => ${{ github.ref_name }} | |
| body: | | |
| A new Chainloop release is available! Bumping Helm Chart reference and Dagger version to ${{ github.ref_name }} | |
| labels: | | |
| automated | |
| helm | |
| finish_attestation: | |
| name: Finish Attestation | |
| runs-on: ubuntu-latest | |
| needs: | |
| - init_attestation | |
| - release | |
| env: | |
| CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }} | |
| outputs: | |
| attestation_hash: ${{ steps.attestation_push.outputs.attestation_sha }} | |
| steps: | |
| - name: Install Chainloop | |
| run: | | |
| curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s | |
| - name: Finish and Record Attestation | |
| id: attestation_push | |
| if: ${{ success() }} | |
| run: | | |
| chainloop attestation push --attestation-id ${{ needs.init_attestation.outputs.attestation_id }} | |
| attestation_sha=$(chainloop wf run describe --id ${{ needs.init_attestation.outputs.attestation_id }} -o json | jq -r '.attestation.digest') | |
| # check that the command succeeded | |
| if [ -n "$attestation_sha" ]; then | |
| echo "attestation_sha=$attestation_sha" >> $GITHUB_OUTPUT | |
| else | |
| exit 1 | |
| fi | |
| - name: Mark attestation as failed | |
| if: ${{ failure() }} | |
| run: | | |
| chainloop attestation reset --attestation-id ${{ needs.init_attestation.outputs.attestation_id }} | |
| - name: Mark attestation as cancelled | |
| if: ${{ cancelled() }} | |
| run: | | |
| chainloop attestation reset --trigger cancellation --attestation-id ${{ needs.init_attestation.outputs.attestation_id }} | |
| modify_release_notes: | |
| if: ${{ success() }} | |
| needs: finish_attestation | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
| - name: Add attestation link to release notes | |
| if: ${{ success() }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ATTESTATION_SHA: ${{ needs.finish_attestation.outputs.attestation_hash }} | |
| run: | | |
| chainloop_release_url="## Chainloop Attestation"$'\n'"[View the attestation of this release](https://app.chainloop.dev/attestation/${{ env.ATTESTATION_SHA }})" | |
| current_notes=$(gh release view ${{github.ref_name}} --json body -q '.body') | |
| if echo "$current_notes" | grep -q "## Chainloop Attestation"; then | |
| # Replace the existing Chainloop Attestation section with the new URL | |
| modified_notes=$(echo "$current_notes" | sed -E "s|## Chainloop Attestation[^\n]*\n\[View the attestation of this release\]\(https://app\.chainloop\.dev/attestation/[^\)]*\)|$chainloop_release_url|") | |
| else | |
| # Add the Chainloop Attestation section to the top | |
| modified_notes="$chainloop_release_url"$'\n\n'"$current_notes" | |
| fi | |
| # Update the release notes and ignore if it fails since we might be lacking permissions to update the release notes | |
| gh release edit ${{github.ref_name}} -n "$modified_notes" || echo -n "Not enough permissions to edit the release notes. Skipping..." |