PipeForge

release.yml

Snapshot 2263a414fe628107f433d708f83dd82cc29e55a6 from main.

GitHub blob for release.yml

  1# Publish a tagged release to GHCR and GitHub Releases.
  2# No server rollout. The container tags are the version and a short sha.
  3# The floating tag named latest is disabled below.
  4name: release
  5
  6on:
  7  push:
  8    tags: ["v*.*.*"]
  9
 10permissions:
 11  contents: read
 12
 13defaults:
 14  run:
 15    shell: bash
 16
 17jobs:
 18  ci:
 19    # Workspace-relative on purpose: actionlint 1.7.12 rejects the $/ form.
 20    uses: ./.github/workflows/ci.yml # zizmor: ignore[self-repository]
 21    permissions:
 22      actions: read
 23      contents: read
 24      security-events: write
 25
 26  publish:
 27    needs: ci
 28    runs-on: ubuntu-latest
 29    timeout-minutes: 20
 30    permissions:
 31      actions: read
 32      attestations: write
 33      contents: write
 34      id-token: write
 35      packages: write
 36    steps:
 37      - name: Download distributions
 38        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
 39        with:
 40          name: dist
 41          path: dist
 42
 43      - name: Download SBOMs
 44        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
 45        with:
 46          name: sbom
 47          path: sbom
 48
 49      - name: Download the scanned image
 50        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
 51        with:
 52          name: image
 53          path: image
 54
 55      - name: Log in to GHCR
 56        uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
 57        with:
 58          registry: ghcr.io
 59          username: ${{ github.actor }}
 60          password: ${{ secrets.GITHUB_TOKEN }}
 61
 62      - name: Image tags
 63        id: meta
 64        uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
 65        with:
 66          images: ghcr.io/${{ github.repository }}
 67          flavor: |
 68            latest=false
 69          tags: |
 70            type=semver,pattern={{version}}
 71            type=sha,prefix=sha-,format=short
 72
 73      - name: Load, tag, and push the scanned image
 74        env:
 75          TAGS: ${{ steps.meta.outputs.tags }}
 76        run: |
 77          set -euo pipefail
 78          archive="$(find image -name 'image.tar' -print -quit)"
 79          test -n "${archive}"
 80          docker load -i "${archive}"
 81          test -n "${TAGS}"
 82          printf '%s\n' "${TAGS}" | while IFS= read -r tag; do
 83            if [ -z "${tag}" ]; then
 84              continue
 85            fi
 86            docker tag ratecard-api:ci "${tag}"
 87            docker push "${tag}"
 88          done
 89
 90      - name: Read the registry digest
 91        id: digest
 92        env:
 93          TAGS: ${{ steps.meta.outputs.tags }}
 94        run: |
 95          set -euo pipefail
 96          first="${TAGS%%$'\n'*}"
 97          test -n "${first}"
 98          name="${first%%:*}"
 99          digest="$(docker image inspect "${first}" --format '{{range .RepoDigests}}{{println .}}{{end}}' | head -n 1)"
100          digest="${digest##*@}"
101          case "${digest}" in
102            sha256:*) ;;
103            *)
104              echo "registry digest missing" >&2
105              exit 1
106              ;;
107          esac
108          printf 'name=%s\n' "${name}" >> "${GITHUB_OUTPUT}"
109          printf 'digest=%s\n' "${digest}" >> "${GITHUB_OUTPUT}"
110
111      - name: Attest the image
112        uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
113        with:
114          subject-name: ${{ steps.digest.outputs.name }}
115          subject-digest: ${{ steps.digest.outputs.digest }}
116          push-to-registry: true
117
118      - name: Locate the wheel and sdist
119        id: packages
120        run: |
121          set -euo pipefail
122          wheel="$(find dist -name '*.whl' -print -quit)"
123          sdist="$(find dist -name '*.tar.gz' -print -quit)"
124          test -n "${wheel}"
125          test -n "${sdist}"
126          printf 'wheel=%s\n' "${wheel}" >> "${GITHUB_OUTPUT}"
127          printf 'sdist=%s\n' "${sdist}" >> "${GITHUB_OUTPUT}"
128
129      - name: Attest the wheel
130        uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
131        with:
132          subject-path: ${{ steps.packages.outputs.wheel }}
133
134      - name: Attest the sdist
135        uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
136        with:
137          subject-path: ${{ steps.packages.outputs.sdist }}
138
139      - name: Write SHA256SUMS
140        run: |
141          set -euo pipefail
142          find dist sbom -type f -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS
143
144      - name: GitHub Release
145        uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
146        with:
147          generate_release_notes: true
148          fail_on_unmatched_files: true
149          files: |
150            dist/*
151            sbom/*
152            SHA256SUMS
153          token: ${{ secrets.GITHUB_TOKEN }}