forked from ChelseaKR/sprout
-
Notifications
You must be signed in to change notification settings - Fork 0
75 lines (70 loc) · 3.26 KB
/
Copy pathrelease.yml
File metadata and controls
75 lines (70 loc) · 3.26 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
name: release
on:
push:
tags: ["v*"]
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
fetch-depth: 0 # full history + tag objects, needed to verify the tag signature below
- name: Verify the pushed tag is a signed, annotated tag (REL-08)
# `git tag -v` needs the signer's public key (GPG) or gitsign's Sigstore/OIDC trust
# config already available on the runner — neither is provisioned by this workflow
# today, so this step will need that key/config added before the first real release
# (tracked; see the 2026-07-05 remediation execution log). It still fails closed: an
# unsigned or unverifiable tag stops the release here rather than silently publishing.
run: git tag -v "$GITHUB_REF_NAME"
# No caching here either: this whole workflow triggers on `push: tags`, i.e. a
# release event, so a cache poisoned by an earlier, less-trusted run could be
# consumed here even though this job itself holds no write credentials (zizmor
# `cache-poisoning`, high severity — found 2026-07-05, applies workflow-wide on a
# tag-push trigger, not just to the job holding OIDC/attestation permissions).
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: false
- name: Re-run the full gate set at the tagged commit
run: uv sync --frozen --extra serve && uv run sprout ingest && make verify
build-and-publish:
needs: verify
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write # PyPI Trusted Publishing (OIDC) — no stored token
attestations: write
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
# No caching in the OIDC signing/publish job: this job holds id-token: write +
# attestations: write, and a poisoned/stale cache is the standard's canonical
# cache-poisoning exposure for a provenance job (SEC-30, CICD-24). The `verify`
# job above has no credentials and may cache freely.
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: false
- name: Build sdist + wheel
run: uv build
- name: Install the built package so the SBOM reflects real, non-empty deps
run: uv sync --frozen --no-dev
- name: Generate SBOM (CycloneDX)
run: uvx cyclonedx-py environment --output-format json --outfile sbom.cdx.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom
path: sbom.cdx.json
- name: Attest build provenance (SLSA)
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: "dist/*"
- name: Publish to PyPI (Trusted Publishing)
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdf1 # v1.12.4