CI (SIAX Cloud) / sonar (pull_request) Skipped
masterplan-lock / check (push) Successful in 5s
masterplan-lock / check (pull_request) Successful in 4s
CI (SIAX Cloud) / security (pull_request) Successful in 16s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 17s
CI (SIAX Cloud) / integration (pull_request) Successful in 9m49s
CI (SIAX Cloud) / quality (pull_request) Successful in 10m1s
The runbook still described Vercel and an unprovisioned Coolify app. It now documents the verified chain (ci -> release attestation -> cd -> Coolify), the proven manual dispatch, the verification endpoints and the rollback.
185 lines
9.5 KiB
YAML
185 lines
9.5 KiB
YAML
name: Release chain (G17, ADR-W16-003)
|
|
|
|
# Builds + pushes the 0pt image, then hands off to the shared
|
|
# sax3l/siax-templates G17 reference hook for every ADR-W16-003 bar item
|
|
# 1-7 (pinned-tool install, SBOM, blocking vuln scan, in-toto attestation,
|
|
# scoped-key signing, pubkey verification, AUD0/ST0RE evidence storage).
|
|
#
|
|
# REPLACES this repo's own ad hoc "P007 pattern" release chain (added
|
|
# 2026-09-14). An audit (2026-09-15) found that chain failed most of the
|
|
# real promotion bar it claimed to meet: syft/cosign installed via a `curl`
|
|
# + freshly-refetched checksums file (not a pinned, out-of-band-verified
|
|
# digest -- see siax-templates' `lib/pinned-tools.sh` header for exactly
|
|
# why that is not a verified digest), NO vulnerability scan of the built
|
|
# digest at all, `cosign sign` on the bare digest only (no in-toto/SLSA
|
|
# statement, no source-SHA/build-identity/environment/SBOM-hash bound
|
|
# together, no scoped key identity), and evidence committed straight back
|
|
# into this same mutable repo (`siax/production-evidence/*.json`,
|
|
# `siax/source-bundles/*.json` -- nine such commits already existed in this
|
|
# repo's history before this change; deleted in this same PR, superseded by
|
|
# the real AUD0 write below). This file keeps ONLY what is genuinely
|
|
# 0pt-specific (image name, tag scheme, registry push, Dockerfile) and
|
|
# delegates everything else to `.siax/hooks/G17.sh` -> the shared reference
|
|
# implementation. See `.siax/hooks/README.md` for the pin status and
|
|
# required secrets (none of which were provisioned for the old gate either
|
|
# -- see that file's own note).
|
|
#
|
|
# DELIBERATELY ONE JOB. Gitea 1.26 on this fleet resolves org-level
|
|
# secrets (SIAX_CI_TOKEN below is org-level) only for the FIRST job of a
|
|
# workflow file -- learned the hard way on sax3l/h0st's and sax3l/aud0's
|
|
# own G17 migrations. 0pt does not wire a G20 post-deploy step in this
|
|
# pass at all (see `.siax/hooks/README.md` "G20 -- deliberately not wired
|
|
# yet": the app is now provisioned and `/api/version` exists, but G20 is still
|
|
# not wired in this pass), so the single-job constraint that forces G20 into its own
|
|
# workflow file elsewhere does not yet bite here -- documented anyway so a
|
|
# future PR adding G20 does not repeat the mistake.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
|
|
concurrency:
|
|
group: release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
IMAGE_REPO: git.cloud.siax.io/sax3l/0pt
|
|
DOCKERFILE: Dockerfile
|
|
SIAX_TEMPLATES_REPO: sax3l/siax-templates
|
|
# PIN STATUS 2026-09-15: sax3l/siax-templates PR #51
|
|
# (feat/g17-signed-deploy-gate-adr-w16-003) MERGED to main, plus three
|
|
# real follow-up fixes on top -- #56/#57 (SPDX compound-license-
|
|
# expression evaluation, exercised live by this repo's own
|
|
# G17_LICENSE_ALLOW policy in .siax/hooks/G17.sh) and #59 (G20 retry
|
|
# logic -- not used by 0pt yet, but the pin picks up main's current tip
|
|
# rather than an older commit, matching what a fresh migration reviews).
|
|
#
|
|
# Re-pin 2026-09-25 (medveten, granskad): 9a3a0aa -> 09504e3a. Deltaet ar
|
|
# EN merge, siax-templates #138 "Upload complete release evidence and
|
|
# validate artifact receipt". Enda berorda filer under ci/v2 ar
|
|
# reference-hooks/{G17.sh, G17-ADR-W16-003.md, lib/emit-release-evidence.py,
|
|
# lib/test_emit_release_evidence.py}. Andringen ar bakatkompatibel by
|
|
# design: ST0RE-uppladdningen ar OPT-IN via G17_REQUIRE_ST0RE (default 0),
|
|
# sa en AUD0-only-konsument som 0pt kor exakt samma vag som forut.
|
|
#
|
|
# Deliberately NO branch name here: the pinned commit is checked out
|
|
# DIRECTLY (see the step below). The previous shape -- clone `main`, then
|
|
# require its HEAD to equal this pin -- turned every unrelated merge in
|
|
# siax-templates into a red release chain here (CD-03 / CI-RED-02) while
|
|
# nothing was actually unsafe. Checking the pin out directly keeps the pin
|
|
# a real supply-chain control (the gate runs exactly this reviewed commit,
|
|
# or it fails) without coupling it to someone else's branch tip.
|
|
SIAX_TEMPLATES_PINNED_SHA: 09504e3a593ee8ce0eaba606df31c349a3d52277
|
|
SIAX_TEMPLATES_DIR: /tmp/siax-templates-g17-ref
|
|
|
|
jobs:
|
|
release:
|
|
name: Build, push, G17 (SBOM/scan/attest/verify/evidence)
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
steps:
|
|
- uses: https://git.siax.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4, mirrored + SHA-pinned (SUP-06, same pin n0d/cl0ud/st0re/h0st already use)
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# --- fetch the shared G17 reference implementation -----------------
|
|
# Same authenticated-fetch-at-runtime mechanism this repo's OLD
|
|
# release.yml already used SIAX_CI_TOKEN for (the evidence-commit
|
|
# push a prior PR deleted) -- see .siax/hooks/G17.sh's header for why
|
|
# NOT a `uses:` reusable workflow / submodule / vendored copy. Fails
|
|
# closed if the exact commit this adapter was reviewed against cannot
|
|
# be checked out (removed or rewritten upstream); an unrelated merge
|
|
# on siax-templates' own main is NOT a failure and never was a real
|
|
# signal.
|
|
- name: Fetch siax-templates G17 reference (pinned commit)
|
|
env:
|
|
SIAX_CI_TOKEN: ${{ secrets.SIAX_CI_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
rm -rf "$SIAX_TEMPLATES_DIR"
|
|
mkdir -p "$SIAX_TEMPLATES_DIR"
|
|
git -C "$SIAX_TEMPLATES_DIR" init --quiet
|
|
git -C "$SIAX_TEMPLATES_DIR" remote add origin \
|
|
"https://oauth2:${SIAX_CI_TOKEN}@git.siax.io/${SIAX_TEMPLATES_REPO}.git"
|
|
# Ask for the pinned commit by SHA -- one shallow commit, no branch
|
|
# involved. A server with uploadpack.allowReachableSHA1InWant off
|
|
# refuses that, so fall back to fetching the branches and taking the
|
|
# same commit out of them. Either way the work tree ends up at
|
|
# exactly $SIAX_TEMPLATES_PINNED_SHA, never at a branch tip.
|
|
if ! git -C "$SIAX_TEMPLATES_DIR" fetch --quiet --depth 1 origin "$SIAX_TEMPLATES_PINNED_SHA"; then
|
|
echo "note: server refused a by-SHA fetch; falling back to fetching all branches"
|
|
git -C "$SIAX_TEMPLATES_DIR" fetch --quiet origin
|
|
fi
|
|
if ! git -C "$SIAX_TEMPLATES_DIR" -c advice.detachedHead=false \
|
|
checkout --quiet --detach "$SIAX_TEMPLATES_PINNED_SHA"; then
|
|
echo "::error::siax-templates commit $SIAX_TEMPLATES_PINNED_SHA not found in $SIAX_TEMPLATES_REPO -- the reviewed commit was removed or rewritten upstream. Re-review siax-templates and update SIAX_TEMPLATES_PINNED_SHA deliberately."
|
|
exit 1
|
|
fi
|
|
actual_sha="$(git -C "$SIAX_TEMPLATES_DIR" rev-parse HEAD)"
|
|
if [ "$actual_sha" != "$SIAX_TEMPLATES_PINNED_SHA" ]; then
|
|
echo "::error::checked-out siax-templates HEAD is $actual_sha, expected the pinned $SIAX_TEMPLATES_PINNED_SHA -- refusing to run an unreviewed version of the gate."
|
|
exit 1
|
|
fi
|
|
chmod +x "$SIAX_TEMPLATES_DIR/ci/v2/reference-hooks/"*.sh "$SIAX_TEMPLATES_DIR/ci/v2/reference-hooks/lib/"*.sh
|
|
echo "siax-templates G17 reference @ $actual_sha (pinned commit, checked out directly)"
|
|
|
|
- name: Resolve SHA + tag (never :latest)
|
|
id: sha
|
|
run: |
|
|
set -euo pipefail
|
|
full="$(git rev-parse HEAD)"
|
|
short="$(git rev-parse --short=12 HEAD)"
|
|
echo "full=$full" >> "$GITHUB_OUTPUT"
|
|
echo "short=$short" >> "$GITHUB_OUTPUT"
|
|
echo "image_tag=sha-$short" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Docker login (git.cloud.siax.io)
|
|
env:
|
|
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
registry_host="$(echo "$IMAGE_REPO" | cut -d/ -f1)"
|
|
echo "$REGISTRY_TOKEN" | docker login "$registry_host" -u "$REGISTRY_USER" --password-stdin
|
|
|
|
- name: Build
|
|
env:
|
|
IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
docker build -f "$DOCKERFILE" -t "${IMAGE_REPO}:${IMAGE_TAG}" .
|
|
|
|
- name: Push (immutable sha-<12> tag, never :latest)
|
|
env:
|
|
IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
|
run: docker push "${IMAGE_REPO}:${IMAGE_TAG}"
|
|
|
|
# --- G17: everything else, delegated -------------------------------
|
|
- name: G17 (bar items 1-7, delegated to siax-templates)
|
|
env:
|
|
ARTIFACT_COMMIT_SHA: ${{ steps.sha.outputs.full }}
|
|
ARTIFACT_IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
|
CI_RUN_ID: ${{ github.run_id }}
|
|
CI_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
G17_COSIGN_KEY: /tmp/0pt-g17-cosign.key
|
|
G17_COSIGN_KEY_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
|
AUD0_INGEST_TOKEN: ${{ secrets.AUD0_INGEST_TOKEN }}
|
|
AUD0_TENANT_ID: ${{ secrets.AUD0_TENANT_ID }}
|
|
run: |
|
|
set -euo pipefail
|
|
echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > "$G17_COSIGN_KEY"
|
|
trap 'rm -f "$G17_COSIGN_KEY"' EXIT
|
|
bash .siax/hooks/G17.sh
|
|
|
|
# NOTE: deliberately NO `actions/upload-artifact@v4` step here.
|
|
# sax3l/cl0ud's release.yml (run 23340, 2026-09-14) documents that
|
|
# this Gitea instance's act_runner does not reliably support
|
|
# upload-artifact@v4 even with continue-on-error: true, and that it
|
|
# can abort the whole job before later steps run. G17.sh's own AUD0
|
|
# submission (bar item 7, step above) is already the durable evidence
|
|
# record; a convenience local copy is not worth re-triggering that
|
|
# known breakage.
|
|
|