mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-04 07:47:27 +01:00
Bumps the github-actions group with 2 updates in the / directory: [docker/login-action](https://github.com/docker/login-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action). Updates `docker/login-action` from 4.6.0 to 4.7.0 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/dbcb813823bdd20940b903addbd779551569679f...81c6f93d4bc991e510b342a00b419b3bb4efc5c6) Updates `github/codeql-action/upload-sarif` from 4.39.0 to 4.39.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee...9b3254085494b55a0f7c4c2b3d2d52cc712ce370) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 4.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.39.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com>
377 lines
18 KiB
YAML
377 lines
18 KiB
YAML
name: Stage CSO Runtime Images
|
|
|
|
# Pull requests build every reviewed input on its native architecture without
|
|
# publishing. The cso-runtime-release environment must require a maintainer
|
|
# reviewer and permit deployments from protected main only. Staging digests
|
|
# never enter the execution catalog automatically.
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- '.github/workflows/cso-runtime-images.yml'
|
|
- 'lib/cso/**'
|
|
- 'scripts/cso-image-matrix.ts'
|
|
- 'scripts/cso-verify-runtime-base.ts'
|
|
- 'scripts/cso-runtime-promotion.ts'
|
|
- 'scripts/cso-requalification.ts'
|
|
- 'scripts/cso-public-ghcr.ts'
|
|
- 'test/cso-*.test.ts'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: cso-runtime-images-${{ github.event.pull_request.number || 'release' }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
reviewed-inputs:
|
|
if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch')
|
|
runs-on: ubuntu-24.04
|
|
outputs:
|
|
matrix: ${{ steps.inputs.outputs.matrix }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: 1.4.2
|
|
- name: Validate committed image digests and complete platform matrix
|
|
id: inputs
|
|
run: |
|
|
set -eu
|
|
matrix="$(bun run scripts/cso-image-matrix.ts)"
|
|
printf 'matrix=%s\n' "$matrix" >> "$GITHUB_OUTPUT"
|
|
- name: Record the requalification trigger inputs of this source commit
|
|
run: bun run scripts/cso-requalification.ts triggers > requalification.json
|
|
- if: github.event_name == 'workflow_dispatch'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: cso-requalification-triggers
|
|
path: requalification.json
|
|
if-no-files-found: error
|
|
retention-days: 30
|
|
|
|
validate-native:
|
|
needs: reviewed-inputs
|
|
if: github.event_name == 'pull_request'
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.reviewed-inputs.outputs.matrix) }}
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 35
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
|
with:
|
|
bun-version: 1.4.2
|
|
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
|
- name: Require native Docker and verify reviewed source manifests
|
|
env:
|
|
CSO_ARCH: ${{ matrix.arch }}
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
run: |
|
|
set -eu
|
|
case "$CSO_ARCH:$(uname -m)" in
|
|
amd64:x86_64|arm64:aarch64) ;;
|
|
*) echo 'Native architecture mismatch; emulation cannot validate a runtime.' >&2; exit 1 ;;
|
|
esac
|
|
bun run scripts/cso-verify-runtime-base.ts
|
|
- name: Compile native trusted image helpers
|
|
run: |
|
|
bun build --compile \
|
|
--no-compile-autoload-dotenv \
|
|
--no-compile-autoload-bunfig \
|
|
--no-compile-autoload-tsconfig \
|
|
--no-compile-autoload-package-json \
|
|
lib/cso/verifier.ts --outfile lib/cso/images/gstack-cso-verifier
|
|
bun build --compile \
|
|
--no-compile-autoload-dotenv \
|
|
--no-compile-autoload-bunfig \
|
|
--no-compile-autoload-tsconfig \
|
|
--no-compile-autoload-package-json \
|
|
lib/cso/preparation-container.ts --outfile lib/cso/images/gstack-cso-preparation
|
|
- name: Build the reviewed runtime without publishing
|
|
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
|
with:
|
|
context: lib/cso/images
|
|
file: lib/cso/images/${{ matrix.stack }}.Dockerfile
|
|
platforms: ${{ matrix.platform }}
|
|
build-args: |
|
|
BASE_IMAGE=${{ matrix.baseImage }}
|
|
UV_IMAGE=${{ matrix.uvImage }}
|
|
tags: localhost/gstack-cso-pr-${{ matrix.stack }}:${{ github.sha }}-${{ matrix.arch }}
|
|
load: true
|
|
push: false
|
|
provenance: false
|
|
sbom: false
|
|
- name: Check the built image identity and fail-closed entrypoint
|
|
env:
|
|
CSO_IMAGE: localhost/gstack-cso-pr-${{ matrix.stack }}:${{ github.sha }}-${{ matrix.arch }}
|
|
run: |
|
|
set -eu
|
|
test "$(docker image inspect "$CSO_IMAGE" --format '{{.Config.User}}')" = "10001:10001"
|
|
test "$(docker image inspect "$CSO_IMAGE" --format '{{json .Config.Entrypoint}}')" = '["/opt/cso/entrypoint"]'
|
|
docker run --rm --pull never --network none --read-only --cap-drop ALL \
|
|
--security-opt no-new-privileges --entrypoint /opt/cso/entrypoint \
|
|
"$CSO_IMAGE" /bin/true
|
|
docker image rm "$CSO_IMAGE"
|
|
|
|
stage:
|
|
needs: reviewed-inputs
|
|
if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch'
|
|
environment: cso-runtime-release
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.reviewed-inputs.outputs.matrix) }}
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 40
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
id-token: write
|
|
attestations: write
|
|
artifact-metadata: write
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: 1.4.2
|
|
- name: Require the declared native architecture and Docker daemon
|
|
env:
|
|
CSO_ARCH: ${{ matrix.arch }}
|
|
run: |
|
|
set -eu
|
|
case "$CSO_ARCH:$(uname -m)" in
|
|
amd64:x86_64|arm64:aarch64) ;;
|
|
*) echo 'Native architecture mismatch; emulation cannot qualify a runtime.' >&2; exit 1 ;;
|
|
esac
|
|
docker --host unix:///var/run/docker.sock info
|
|
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
|
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
- name: Verify reviewed source manifests and exact base versions
|
|
env:
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
run: bun run scripts/cso-verify-runtime-base.ts
|
|
- name: Compile native trusted HTTP verifier for the runtime image
|
|
run: |
|
|
bun build --compile \
|
|
--no-compile-autoload-dotenv \
|
|
--no-compile-autoload-bunfig \
|
|
--no-compile-autoload-tsconfig \
|
|
--no-compile-autoload-package-json \
|
|
lib/cso/verifier.ts --outfile lib/cso/images/gstack-cso-verifier
|
|
bun build --compile \
|
|
--no-compile-autoload-dotenv \
|
|
--no-compile-autoload-bunfig \
|
|
--no-compile-autoload-tsconfig \
|
|
--no-compile-autoload-package-json \
|
|
lib/cso/preparation-container.ts --outfile lib/cso/images/gstack-cso-preparation
|
|
- name: Prepare immutable staging tag
|
|
id: image
|
|
env:
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
CSO_ARCH: ${{ matrix.arch }}
|
|
run: |
|
|
set -eu
|
|
image="ghcr.io/${GITHUB_REPOSITORY,,}/cso-staging/$CSO_STACK-$CSO_ARCH"
|
|
printf 'name=%s\n' "$image" >> "$GITHUB_OUTPUT"
|
|
printf 'tag=%s:%s-%s\n' "$image" "$GITHUB_SHA" "$GITHUB_RUN_ID" >> "$GITHUB_OUTPUT"
|
|
- name: Build native staging image with SBOM and provenance
|
|
id: build
|
|
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
|
with:
|
|
context: lib/cso/images
|
|
file: lib/cso/images/${{ matrix.stack }}.Dockerfile
|
|
platforms: ${{ matrix.platform }}
|
|
build-args: |
|
|
BASE_IMAGE=${{ matrix.baseImage }}
|
|
UV_IMAGE=${{ matrix.uvImage }}
|
|
tags: ${{ steps.image.outputs.tag }}
|
|
push: true
|
|
provenance: mode=max
|
|
attests: type=sbom,generator=${{ matrix.sbomGeneratorImage }}
|
|
- name: Extract the immutable image SBOM
|
|
env:
|
|
CSO_IMAGE: ${{ steps.image.outputs.name }}@${{ steps.build.outputs.digest }}
|
|
run: |
|
|
set -eu
|
|
docker buildx imagetools inspect "$CSO_IMAGE" --format '{{ json .SBOM.SPDX }}' > sbom.full.spdx.json
|
|
jq -c -f scripts/cso-sbom-packages.jq sbom.full.spdx.json > sbom.spdx.json
|
|
jq -e -f scripts/cso-sbom-packages-check.jq sbom.spdx.json >/dev/null
|
|
- name: Sign build provenance
|
|
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
|
|
with:
|
|
subject-name: ${{ steps.image.outputs.name }}
|
|
subject-digest: ${{ steps.build.outputs.digest }}
|
|
push-to-registry: true
|
|
- name: Sign the image SBOM
|
|
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
|
|
with:
|
|
subject-name: ${{ steps.image.outputs.name }}
|
|
subject-digest: ${{ steps.build.outputs.digest }}
|
|
sbom-path: sbom.spdx.json
|
|
push-to-registry: true
|
|
- name: Verify provenance and SBOM signer identities
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
CSO_IMAGE: ${{ steps.image.outputs.name }}@${{ steps.build.outputs.digest }}
|
|
run: |
|
|
set -eu
|
|
signer="https://github.com/$GITHUB_REPOSITORY/.github/workflows/cso-runtime-images.yml@refs/heads/main"
|
|
gh attestation verify "oci://$CSO_IMAGE" --repo "$GITHUB_REPOSITORY" --cert-identity "$signer" --source-ref refs/heads/main --source-digest "$GITHUB_SHA" --deny-self-hosted-runners --predicate-type https://slsa.dev/provenance/v1 --format json > provenance-verification.json
|
|
gh attestation verify "oci://$CSO_IMAGE" --repo "$GITHUB_REPOSITORY" --cert-identity "$signer" --source-ref refs/heads/main --source-digest "$GITHUB_SHA" --deny-self-hosted-runners --predicate-type https://spdx.dev/Document/v2.3 --format json > sbom-verification.json
|
|
- name: Require a public package and anonymously load the exact staged digest
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
CSO_IMAGE: ${{ steps.image.outputs.name }}@${{ steps.build.outputs.digest }}
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
run: |
|
|
set -euo pipefail
|
|
bun run scripts/cso-public-ghcr.ts verify \
|
|
--image "$CSO_IMAGE" --platform "$CSO_PLATFORM" \
|
|
--repository "$GITHUB_REPOSITORY" --output public-image.json
|
|
- name: Install helper dependencies and compile trusted tools
|
|
run: |
|
|
bun install --frozen-lockfile --ignore-scripts
|
|
bun run build:cso
|
|
- name: Exercise containment against the staged digest
|
|
env:
|
|
GSTACK_CSO_DOCKER_TESTS: "1"
|
|
GSTACK_CSO_TEST_IMAGE: ${{ steps.image.outputs.name }}@${{ steps.build.outputs.digest }}
|
|
GSTACK_CSO_TEST_PLATFORM: ${{ matrix.platform }}
|
|
GSTACK_CSO_TEST_STACK: ${{ matrix.stack }}
|
|
GSTACK_CSO_EXPECTED_VERSIONS: ${{ toJSON(matrix.versions) }}
|
|
DOCKER_HOST: unix:///var/run/docker.sock
|
|
run: bun test --max-concurrency 1 test/cso-docker-integration.test.ts
|
|
- name: Record staging evidence without promoting the catalog
|
|
env:
|
|
CSO_BUILD_REVISION: ${{ matrix.inputRevision }}
|
|
CSO_IMAGE: ${{ steps.image.outputs.name }}@${{ steps.build.outputs.digest }}
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
CSO_RUNTIME_ID: ${{ matrix.runtimeId }}
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
CSO_VERSIONS: ${{ toJSON(matrix.versions) }}
|
|
run: |
|
|
set -eu
|
|
sha256sum public-image.json sbom.spdx.json provenance-verification.json sbom-verification.json > evidence.sha256
|
|
sbom_digest="sha256:$(sha256sum sbom.spdx.json | cut -d ' ' -f 1)"
|
|
provenance_digest="sha256:$(sha256sum provenance-verification.json | cut -d ' ' -f 1)"
|
|
workflow="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
|
jq -n --arg buildRevision "$CSO_BUILD_REVISION" --arg runtimeId "$CSO_RUNTIME_ID" \
|
|
--arg image "$CSO_IMAGE" --arg platform "$CSO_PLATFORM" --arg stack "$CSO_STACK" \
|
|
--arg commit "$GITHUB_SHA" --arg workflow "$workflow" --arg sbom "$sbom_digest" \
|
|
--arg provenance "$provenance_digest" --argjson versions "$CSO_VERSIONS" \
|
|
'{schemaVersion:1,helperAbi:3,state:"staged",buildRevision:$buildRevision,runtimeId:$runtimeId,image:$image,platform:$platform,stack:$stack,versions:$versions,sourceCommit:$commit,workflow:$workflow,sbomDigest:$sbom,provenanceDigest:$provenance,verifiedProvenance:true,qualification:"pending native and private release gates; no automatic promotion"}' > staged-image.json
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: cso-staged-${{ matrix.stack }}-${{ matrix.arch }}
|
|
path: |
|
|
staged-image.json
|
|
public-image.json
|
|
sbom.spdx.json
|
|
provenance-verification.json
|
|
sbom-verification.json
|
|
evidence.sha256
|
|
if-no-files-found: error
|
|
retention-days: 30
|
|
|
|
qualify-native:
|
|
name: qualify-native ${{ matrix.runtimeId }}
|
|
needs: [reviewed-inputs, stage]
|
|
if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch'
|
|
environment: cso-runtime-release
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.reviewed-inputs.outputs.matrix) }}
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 40
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: 1.4.2
|
|
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
|
|
with:
|
|
name: cso-staged-${{ matrix.stack }}-${{ matrix.arch }}
|
|
path: staged-application
|
|
- if: matrix.stack == 'rails'
|
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
|
|
with:
|
|
name: cso-staged-postgresql-${{ matrix.arch }}
|
|
path: staged-postgresql
|
|
- name: Require native Docker and anonymously load the signed staged inputs
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
CSO_ARCH: ${{ matrix.arch }}
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
run: |
|
|
set -eu
|
|
case "$CSO_ARCH:$(uname -m)" in amd64:x86_64|arm64:aarch64) ;; *) exit 1 ;; esac
|
|
docker --host unix:///var/run/docker.sock info
|
|
(cd staged-application && sha256sum --check evidence.sha256)
|
|
if test "$CSO_STACK" = rails; then
|
|
(cd staged-postgresql && sha256sum --check evidence.sha256)
|
|
fi
|
|
app="$(jq -er --arg platform "$CSO_PLATFORM" --arg stack "$CSO_STACK" 'select(.state == "staged" and .platform == $platform and .stack == $stack) | .image' staged-application/staged-image.json)"
|
|
bun run scripts/cso-public-ghcr.ts verify \
|
|
--image "$app" --platform "$CSO_PLATFORM" \
|
|
--repository "$GITHUB_REPOSITORY" --output application-public-image.json
|
|
printf 'GSTACK_CSO_TEST_IMAGE=%s\n' "$app" >> "$GITHUB_ENV"
|
|
printf 'GSTACK_CSO_EXPECTED_VERSIONS=%s\n' "$(jq -c '.versions' staged-application/staged-image.json)" >> "$GITHUB_ENV"
|
|
if test "$CSO_STACK" = rails; then
|
|
pg="$(jq -er --arg platform "$CSO_PLATFORM" 'select(.state == "staged" and .platform == $platform and .stack == "postgresql") | .image' staged-postgresql/staged-image.json)"
|
|
bun run scripts/cso-public-ghcr.ts verify \
|
|
--image "$pg" --platform "$CSO_PLATFORM" \
|
|
--repository "$GITHUB_REPOSITORY" --output postgresql-public-image.json
|
|
printf 'GSTACK_CSO_TEST_POSTGRES_IMAGE=%s\n' "$pg" >> "$GITHUB_ENV"
|
|
printf 'GSTACK_CSO_TEST_POSTGRES_VERSION=%s\n' "$(jq -er '.versions.postgresql' staged-postgresql/staged-image.json)" >> "$GITHUB_ENV"
|
|
fi
|
|
- name: Compile trusted helpers and run the matching staged cold-start journey
|
|
env:
|
|
GSTACK_CSO_DOCKER_TESTS: "1"
|
|
GSTACK_CSO_TEST_PLATFORM: ${{ matrix.platform }}
|
|
GSTACK_CSO_TEST_STACK: ${{ matrix.stack }}
|
|
DOCKER_HOST: unix:///var/run/docker.sock
|
|
run: |
|
|
set -eu
|
|
bun install --frozen-lockfile --ignore-scripts
|
|
bun run build:cso
|
|
bun run test:cso:docker --reporter=junit --reporter-outfile=native-tests.junit.xml
|
|
- name: Derive native gate evidence from the executed test report
|
|
env:
|
|
CSO_STACK: ${{ matrix.stack }}
|
|
CSO_PLATFORM: ${{ matrix.platform }}
|
|
run: |
|
|
set -eu
|
|
bun run scripts/cso-native-evidence.ts --stack "$CSO_STACK" --platform "$CSO_PLATFORM" \
|
|
--junit native-tests.junit.xml --staged staged-application/staged-image.json \
|
|
--output qualification-evidence.json
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: cso-qualification-gates-${{ matrix.stack }}-${{ matrix.arch }}
|
|
path: |
|
|
qualification-evidence.json
|
|
native-tests.junit.xml
|
|
if-no-files-found: error
|
|
retention-days: 30
|