-
Notifications
You must be signed in to change notification settings - Fork 0
162 lines (147 loc) · 7.35 KB
/
Copy pathrelease.yml
File metadata and controls
162 lines (147 loc) · 7.35 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
161
162
# =============================================================================
# Release & publish workflow (conclave v1.0 — distribution + release-eng)
#
# !!! INERT UNTIL CONFIGURED — SAFE TO MERGE !!!
#
# This workflow does NOTHING until BOTH of the following are true:
# (a) a GitHub *Release* is published (a pushed git tag ALONE does not trigger
# it — the trigger is `release: published`, the explicit human gesture), AND
# (b) the `conclave-cli` PyPI project + its OIDC Trusted Publisher are configured
# by the owner (see RELEASING.md "One-time PyPI setup").
#
# Until (a) AND (b) hold, merging this file changes nothing at runtime: no tag is
# cut here, no version is bumped here, nothing is published here. Cutting v1.0.0 is
# then a single tag + GitHub Release away (the full runbook is in RELEASING.md).
#
# What it does WHEN a Release is published:
# build — builds sdist + wheel with `python -m build`, uploads them as
# workflow artifacts so publish + sign consume the exact same bytes.
# pypi-publish — publishes those artifacts to PyPI via OIDC Trusted Publishing
# (NO API token, NO stored secret), with PEP 740 attestations.
# Fails CLOSED if the Trusted Publisher is not yet configured —
# it never falls back to anything insecure.
# sign — signs the sdist + wheel with Sigstore keyless (ambient OIDC ->
# Fulcio) and attaches the `.sigstore` bundles to the GitHub
# Release assets.
#
# Distribution-name note: the PyPI distribution name is `conclave-cli` (the name
# `conclave` is taken by an unrelated project). The command + import package stay
# `conclave`. The Trusted Publisher must therefore name PROJECT `conclave-cli`.
#
# Pin discipline: every `uses:` is pinned to a full 40-char commit SHA with a
# `# vX.Y.Z` comment. conclave's other workflows (test.yml, gitleaks.yml) pin to
# mutable major tags; this publish workflow holds elevated OIDC permissions, so it
# is hardened one level further with full commit-SHA pins.
# =============================================================================
name: Release
on:
# Primary, safe trigger: only fires once a GitHub Release is *published*.
# A pushed tag by itself does NOT publish a Release and therefore does NOT
# trigger this workflow.
release:
types: [published]
# Least-privilege at the top level; each job widens scope locally only as needed.
permissions:
contents: read
jobs:
# --------------------------------------------------------------------------
# Job 1: build sdist + wheel and publish them as workflow artifacts so the
# publish and sign jobs consume the exact same bytes (no rebuild drift).
# --------------------------------------------------------------------------
build:
name: Build sdist + wheel
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python 3.12
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
cache: pip
- name: Install build frontend
run: python -m pip install --upgrade "build==1.2.2.post1"
- name: Build sdist + wheel
run: python -m build --sdist --wheel --outdir dist/
- name: Show built artifacts
run: ls -l dist/
- name: Upload dist artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dist
path: dist/
if-no-files-found: error
# --------------------------------------------------------------------------
# Job 2: publish to PyPI via OIDC Trusted Publishing.
#
# No API token, no stored secret: pypa/gh-action-pypi-publish mints a short-lived
# OIDC token from this job's `id-token: write` and exchanges it for a PyPI upload
# token. PyPI must have a Trusted Publisher (pending or active) for `conclave-cli`
# pointing at owner=ernestprovo23, repo=conclave, workflow=release.yml — see
# RELEASING.md. Until that exists, this job fails CLOSED (publish denied); it
# never falls back to anything insecure.
#
# PEP 740 attestations are generated + attached by default (the action's
# `attestations: true` default) since OIDC Trusted Publishing is in use.
# --------------------------------------------------------------------------
pypi-publish:
name: Publish to PyPI (OIDC Trusted Publishing)
needs: build
runs-on: ubuntu-latest
# id-token: write is scoped to THIS job only (never granted at workflow top level).
permissions:
id-token: write # REQUIRED for OIDC Trusted Publishing — mints the token
contents: read
steps:
- name: Download dist artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist/
# Production PyPI via Trusted Publishing (OIDC). No `password:` — the action
# uses ambient OIDC. PEP 740 attestations are on by default.
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
packages-dir: dist/
# No `password:` — OIDC Trusted Publishing is used (no stored secret).
# `attestations` defaults to true under Trusted Publishing -> PEP 740.
# --------------------------------------------------------------------------
# Job 3: sign the release artifacts with Sigstore keyless.
#
# The job's ambient OIDC mints a short-lived Fulcio cert (issuer
# https://token.actions.githubusercontent.com), signs each dist file, and
# attaches the resulting `.sigstore` bundle(s) to the GitHub Release assets
# (release-signing-artifacts, the action's default on a release event).
#
# We self-verify (`verify: true`) against THIS workflow's own identity so a
# broken run can never publish a bad bundle.
# --------------------------------------------------------------------------
sign:
name: Sign release artifacts (Sigstore keyless)
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write # REQUIRED for ambient OIDC -> Fulcio
contents: write # REQUIRED to attach .sigstore bundles to the Release assets
steps:
- name: Download dist artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist/
- name: Sign sdist + wheel and attach bundles to the Release
uses: sigstore/gh-action-sigstore-python@5b79a39c381910c090341a2c9b0bf022c8b387e1 # v3.4.0
with:
inputs: ./dist/*.tar.gz ./dist/*.whl
# Self-check: verify what we just signed against THIS workflow's own
# identity so a broken run never publishes a bad bundle.
verify: true
verify-cert-identity: "https://github.com/ernestprovo23/conclave/.github/workflows/release.yml@${{ github.ref }}"
verify-oidc-issuer: "https://token.actions.githubusercontent.com"
# release-signing-artifacts defaults to true: on a release event the
# .sigstore bundles are attached to the Release assets automatically.
release-signing-artifacts: true
upload-signing-artifacts: true