badges #9
Workflow file for this run
This file contains 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
# Build the app with ko and push image incl. provenance, sbom, everything signed | |
name: Release workflow | |
on: | |
push: | |
tags: | |
- "*" | |
env: | |
KO_DOCKER_REPO: "ghcr.io/${{ github.repository}}" | |
jobs: | |
build: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
outputs: | |
image: ${{ steps.build.outputs.image }} | |
digest: ${{ steps.build.outputs.digest }} | |
steps: | |
- name: checkout repo | |
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 #v3.5.3 | |
- uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 #v4.0.1 | |
with: | |
go-version: '1.19' | |
# setup-ko could do KO_DOCKER_REPO and login for us, but I prefer to show it explicitly | |
- uses: ko-build/setup-ko@ace48d793556083a76f1e3e6068850c1f4a369aa #v0.6 | |
with: | |
version: 'v0.14.1' | |
- name: Build and push with ko | |
id: build | |
if: startsWith(github.ref, 'refs/tags/') # just to be safe, don't push if it's not a tag | |
run: | | |
tag=$(echo ${{ github.ref }} | cut -d'/' -f3) | |
echo "${{ github.token }}" | ko login ghcr.io --username ${{ github.actor }} --password-stdin | |
# fetch go deps to local and generate ent files | |
go generate ./... | |
go mod tidy | |
# build the SPA UI so it can be embedded into the binary when `ko` builds | |
make fe-build | |
# Build & push the image. Save the image name. | |
# NOTICE the '--bare' flag, this uses the value of KO_DOCKER_REPO | |
# directly without adding anything to the end, which ko likes to do | |
# don't let ko upload the SBOM, we want to do it differently | |
image_and_digest=$(ko build --tags="${tag}" --bare --sbom=none .) | |
# Output the image name and digest so we can generate provenance. | |
digest=$(echo "${image_and_digest}" | cut -d'@' -f2) | |
echo "digest=$digest" >> "$GITHUB_OUTPUT" | |
# image is defined fully by the KO_DOCKER_REPO, so just use that | |
echo "image=$KO_DOCKER_REPO" >> "$GITHUB_OUTPUT" | |
sign-image: | |
runs-on: ubuntu-latest | |
needs: [build] | |
permissions: | |
packages: write | |
id-token: write | |
env: | |
image: ${{ needs.build.outputs.image }} | |
digest: ${{ needs.build.outputs.digest }} | |
steps: | |
- name: Install cosign | |
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1 | |
with: | |
cosign-release: v2.1.1 | |
- name: Login to ghcr.io | |
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc #v2.2.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Sign image | |
run: | | |
cosign sign "${image}@${digest}" --yes | |
sbom: | |
runs-on: ubuntu-latest | |
needs: [build] | |
permissions: | |
packages: write | |
id-token: write | |
env: | |
image: ${{ needs.build.outputs.image }} | |
digest: ${{ needs.build.outputs.digest }} | |
steps: | |
- name: checkout repo (verinotes) | |
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 #v3.5.3 | |
- name: checkout repo of sbom-merge, compile during build | |
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 #v3.5.3 | |
with: | |
repository: verifa/sbom-merge | |
path: sbom-merge | |
ref: e279f901130689f7576ff33ad65e34cb9767150b # v0.0.1 | |
- name: Install cosign | |
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1 | |
with: | |
cosign-release: v2.1.1 | |
- name: Install Syft | |
uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 #v0.14.3 | |
- uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 #v4.0.1 | |
with: | |
go-version: '1.19' | |
- name: Login to ghcr.io | |
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc #v2.2.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Attach SBOM to image | |
run: | | |
# syft pull the image and analyses the contents to generate an SBOM | |
syft "${image}@${digest}" --output spdx-json --file sbom.spdx.json | |
# ui SBOM is generated explicitly since syft cannot find it inside Go binary | |
# this is an example why SBOM is good to create at build time, not afterwards | |
syft --output spdx-json file:./ui/package-lock.json --file sbom-ui.spdx.json | |
# use the experimental sbom-merge tool to merge the ui and container(+go backend) SBOMs | |
cd sbom-merge && go mod tidy && go build -o ../sbom-merge-tool && cd .. | |
ls -l | |
./sbom-merge-tool sbom.spdx.json sbom-ui.spdx.json > sbom-final.spdx.json | |
# attach merged sbom as attestation (signed) | |
cosign attest --predicate sbom-final.spdx.json --type spdxjson "${image}@${digest}" --yes | |
# slsa-github-generator creates and pushes the provenance attestation | |
provenance: | |
needs: [build] | |
permissions: | |
actions: read | |
id-token: write | |
# contents: read | |
packages: write | |
if: startsWith(github.ref, 'refs/tags/') # just to be safe, don't push if it's not a tag | |
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected] | |
with: | |
image: ${{ needs.build.outputs.image }} | |
digest: ${{ needs.build.outputs.digest }} | |
registry-username: ${{ github.actor }} | |
compile-generator: true | |
secrets: | |
registry-password: ${{ secrets.GITHUB_TOKEN }} |