forked from ChelseaKR/olive-bark-logger
-
Notifications
You must be signed in to change notification settings - Fork 0
160 lines (148 loc) · 7.36 KB
/
Copy pathrelease.yml
File metadata and controls
160 lines (148 loc) · 7.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
name: release
# Tag-triggered release (REL-14; see docs/GAP-LEDGER.md#gap-rel-1 for the wider
# supply-chain gap this is a slice of). Never trust the PR's green check for a
# release: this re-runs the literal `make verify` gate set (lint, types,
# coverage >=85%, security, accessibility, PWA tests, i18n) at the exact tagged
# commit, then builds sdist + wheel, generates a CycloneDX SBOM, attests build
# provenance via GitHub's native (keyless, no stored signing key) attestation,
# and publishes a GitHub Release with the CHANGELOG section as notes.
#
# Deliberately NOT in scope here (see GAP-REL-1 — these are live, externally
# visible actions with real infrastructure/registry decisions this remediation
# pass does not make on the maintainer's behalf):
# - PyPI publishing (no trusted-publisher project configured yet)
# - GHCR / container registry push of the Dockerfile image (no registry
# decision made yet; ci.yml already CVE-scans the image build on every PR)
# - cosign key-based signing (would require provisioning/protecting a
# long-lived signing key; native attestation below needs no key at all)
#
# NOT YET USED: no `v*` tag exists in this repo yet (CHANGELOG.md's own header:
# "No version of this project has been tagged or released yet"). This workflow
# is prepared ahead of the first tag so cutting `v0.1.0` doesn't also require
# writing a release pipeline from scratch under time pressure.
on:
push:
tags: ["v*"]
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
# Re-verify at the tagged commit — the exact same gate a contributor runs
# locally via `make verify` (CICD-27: no local/CI/release drift).
verify-at-tag:
name: re-verify at tagged commit (make verify)
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # gitleaks (inside `make verify`) needs full history
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
version: "0.11.28"
enable-cache: true
cache-dependency-glob: uv.lock
# This action has no input to disable its own Node-distribution tool-cache
# (unlike ci.yml's other caches); zizmor itself notes Low confidence for
# this instance — this job only runs the verify gate, it builds/publishes
# nothing, so there's no cached artifact for a poisoned cache to ride into.
- name: Set up Node (for the pa11y/axe a11y and pwa-test targets in `make verify`)
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 # zizmor: ignore[cache-poisoning] no per-action toggle for the Node tool-cache; low-confidence finding
with:
node-version: "20"
- name: Install gitleaks (pinned, matches .pre-commit-config.yaml)
run: |
GL=8.21.2
archive="gitleaks_${GL}_linux_x64.tar.gz"
curl -sSfL -o "/tmp/${archive}" \
"https://github.com/gitleaks/gitleaks/releases/download/v${GL}/${archive}"
echo "5bc41815076e6ed6ef8fbecc9d9b75bcae31f39029ceb55da08086315316e3ba /tmp/${archive}" \
| sha256sum --check --strict
tar -xzf "/tmp/${archive}" -C /usr/local/bin gitleaks
chmod +x /usr/local/bin/gitleaks
- name: Install
run: uv sync --locked --group dev --python 3.12
- name: make verify
run: make verify
build-and-release:
name: build sdist/wheel · SBOM · provenance · GitHub Release
needs: [verify-at-tag]
runs-on: ubuntu-latest
permissions:
contents: write # create the GitHub Release and upload assets
id-token: write # keyless OIDC identity for build provenance attestation
attestations: write # publish the attestation to the repo's attestation store
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
# REL-14: the tag must match the package version — no drifting-version releases.
- name: Tag matches pyproject.toml version
run: |
tag_version="${GITHUB_REF_NAME#v}"
pkg_version="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])')"
echo "tag=$tag_version pyproject=$pkg_version"
if [ "$tag_version" != "$pkg_version" ]; then
echo "::error::tag $GITHUB_REF_NAME does not match pyproject version $pkg_version"
exit 1
fi
# REL-13 / CQ-10: a real wheel + sdist build via the repo's own setuptools backend.
- name: Build sdist + wheel
run: |
python -m pip install --upgrade pip build
python -m build
# SEC-27: CycloneDX SBOM of the exact installed (zero-runtime-dependency)
# package closure, built from a clean venv rather than the build-tool venv.
- name: Generate CycloneDX SBOM
run: |
python -m venv /tmp/sbom-venv
/tmp/sbom-venv/bin/pip install --upgrade pip
/tmp/sbom-venv/bin/pip install dist/*.whl
python -m pip install --upgrade cyclonedx-bom
cyclonedx-py environment /tmp/sbom-venv --output-format json --output-file dist/sbom.cdx.json
# SEC-29 (keyless variant): OIDC-backed GitHub attestation binding this
# workflow run to the built artifacts, verifiable with `gh attestation
# verify` — no signing key is stored anywhere.
- name: Attest build provenance for the built artifacts (keyless OIDC)
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: "dist/*.whl,dist/*.tar.gz,dist/sbom.cdx.json"
# REL-10: the tag must have a matching CHANGELOG section, extracted
# verbatim into the GitHub Release body — a missing section fails the release.
- name: Extract this version's CHANGELOG section
run: |
version="${GITHUB_REF_NAME#v}"
awk -v ver="$version" '
index($0, "## [" ver "]") == 1 { found=1; print; next }
found && /^## \[/ { exit }
found { print }
' CHANGELOG.md > release-notes.md
if [ ! -s release-notes.md ]; then
echo "::error::CHANGELOG.md has no '## [$version]' section (REL-10) — add one before tagging" >&2
exit 1
fi
# `gh` ships preinstalled on GitHub-hosted runners — prefer it over a
# third-party action for the one built-in-covered step.
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--notes-file release-notes.md \
--verify-tag \
dist/*.whl dist/*.tar.gz dist/sbom.cdx.json