Skip to content

Commit 60601c9

Browse files
authored
[codex] Document production PyPI decision gate
Document the PR5 production PyPI decision gate as deferred and conditional. No production PyPI workflow or upload path is added.
1 parent 89a911b commit 60601c9

6 files changed

Lines changed: 930 additions & 776 deletions

File tree

tools/sbom-diff-and-risk/README.md

Lines changed: 382 additions & 379 deletions
Large diffs are not rendered by default.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Production PyPI publishing decision
2+
3+
This page records the PR 5 production PyPI gate for `sbom-diff-and-risk`.
4+
5+
## PR 5 decision
6+
7+
Production PyPI publishing is **deferred, but conditionally allowed after the prerequisites below are complete**. In short: production PyPI is currently deferred.
8+
9+
PR 5 does not add an enabled production publishing workflow and does not publish to production PyPI. The successful TestPyPI Trusted Publishing dry-run proves that the package metadata can render on TestPyPI and that the TestPyPI OIDC path can work, but it is not automatic proof that production PyPI publishing is ready.
10+
11+
The production gate is intentionally conservative because:
12+
13+
- the production PyPI project does not currently exist under the intended name
14+
- the package metadata still declares version `0.4.1`
15+
- the first production upload should be a deliberate release version, not an old dry-run version
16+
- the production PyPI pending publisher or trusted publisher has not been configured
17+
- the production GitHub environment has not yet been confirmed
18+
19+
## Package name and external state
20+
21+
The production package name should be `sbom-diff-and-risk`.
22+
23+
As checked on April 26, 2026:
24+
25+
- `https://pypi.org/pypi/sbom-diff-and-risk/json` returned `404`
26+
- `https://test.pypi.org/pypi/sbom-diff-and-risk/json` returned `200`
27+
- TestPyPI reports `sbom-diff-and-risk` version `0.4.1`
28+
29+
This means the intended production project name is not currently visible on production PyPI, while the TestPyPI dry-run project exists. Treat the production name as available for this decision, but re-check immediately before configuration because PyPI can reserve, prohibit, or receive new projects at any time. The first production upload should use a production PyPI pending publisher unless the project is created by a maintainer before the publishing workflow is enabled.
30+
31+
## First production version
32+
33+
Do not publish `0.4.1` to production PyPI casually.
34+
35+
The first production PyPI version should be `0.5.0` only if v0.5 is approved as the first production package release. Otherwise, defer to a later GitHub release tag.
36+
37+
For the first production upload:
38+
39+
- the GitHub tag should be `v<version>`
40+
- `tools/sbom-diff-and-risk/pyproject.toml` should declare the matching `<version>`
41+
- the GitHub release and release assets should be available for the same tag
42+
- the production PyPI workflow should run from the matching tag ref
43+
- the production PyPI upload should use the checked distributions from that workflow run
44+
45+
## Production publisher identity
46+
47+
Configure the production PyPI publisher to match this identity exactly:
48+
49+
| Field | Value |
50+
| --- | --- |
51+
| PyPI project name | `sbom-diff-and-risk` |
52+
| GitHub owner | `stacknil` |
53+
| GitHub repository | `scientific-computing-toolkit` |
54+
| Future workflow file path | `.github/workflows/sbom-diff-and-risk-pypi.yml` |
55+
| Trusted Publisher workflow name field | `sbom-diff-and-risk-pypi.yml` |
56+
| GitHub environment | `pypi` |
57+
58+
If production PyPI still has no project for this name, configure a pending publisher for a new project. If the project exists by the time production publishing is implemented, add the trusted publisher to the existing project instead.
59+
60+
Do not create or document a PyPI API token for this workflow. Production upload should use Trusted Publishing / OIDC only.
61+
62+
PyPI-side setup should use these paths:
63+
64+
- for a new production project, create a pending publisher on production PyPI for project `sbom-diff-and-risk` with the owner, repository, workflow, and environment values above
65+
- for an existing production project, open that project on production PyPI and add a trusted publisher with the same owner, repository, workflow, and environment values
66+
- leave the environment field as `pypi`; if the PyPI publisher omits the environment, it will not match the future publish job identity
67+
- do not add a PyPI API token, PyPI password, or GitHub publishing secret as a fallback
68+
69+
## Prerequisites before enabling production publishing
70+
71+
Before adding `.github/workflows/sbom-diff-and-risk-pypi.yml`, maintainers should complete all of these checks:
72+
73+
- confirm the intended production package name still resolves as expected on production PyPI
74+
- choose the first production version, likely `0.5.0` or a later release tag
75+
- update `pyproject.toml` to that version
76+
- create or verify the matching GitHub tag and release assets
77+
- create the GitHub environment named `pypi`
78+
- configure required reviewers or equivalent repository controls on the `pypi` environment
79+
- create the PyPI pending publisher or existing-project trusted publisher with the exact identity above
80+
- run the future workflow in no-publish mode first and confirm the publish job is skipped
81+
- verify the checked distributions with `python -m twine check dist/*`
82+
83+
## Future workflow shape
84+
85+
PR 5 intentionally documents the future workflow shape without enabling it.
86+
87+
The future production workflow should:
88+
89+
- use `workflow_dispatch` only for the initial production publishing process
90+
- require an explicit boolean input such as `publish_to_pypi`
91+
- require a confirmation string such as `publish sbom-diff-and-risk to production PyPI`
92+
- require an expected version input and assert that it matches `pyproject.toml`
93+
- require the run ref to be a version tag such as `refs/tags/v0.5.0`
94+
- build the wheel and source distribution once
95+
- run `python -m twine check dist/*`
96+
- upload the checked distributions as a workflow artifact
97+
- publish only from a separate gated job that downloads that artifact
98+
- use the GitHub environment `pypi` on the publish job
99+
- grant `id-token: write` only to the publish job
100+
- avoid production upload on ordinary push or pull request events
101+
102+
The publish step should use `pypa/gh-action-pypi-publish@release/v1` without a `repository-url` override so it targets production PyPI.
103+
104+
## Provenance boundaries
105+
106+
Production PyPI Trusted Publishing provenance, GitHub workflow artifact attestations, and GitHub Release asset verification answer related but different questions.
107+
108+
PyPI Trusted Publishing provenance answers:
109+
110+
- was this distribution uploaded to this PyPI project through the configured GitHub publisher identity?
111+
- did the upload use the expected owner, repository, workflow file, and environment?
112+
113+
GitHub workflow artifact attestations answer:
114+
115+
- were these local wheel or source distribution bytes built by `.github/workflows/sbom-diff-and-risk-ci.yml`?
116+
- do the downloaded files match the attested workflow subjects?
117+
118+
GitHub Release verification answers:
119+
120+
- does the GitHub Release record have a valid release attestation?
121+
- does a downloaded release asset match an attested asset from an immutable release?
122+
123+
Do not treat one provenance surface as a replacement for the others. A PyPI package can have valid Trusted Publishing provenance without proving that it is byte-for-byte identical to a GitHub Release asset. Consumers who need cross-surface verification should compare hashes between a PyPI download and the corresponding GitHub Release asset, then use the GitHub verification flows documented in `self-provenance.md` and `release-provenance.md`.
124+
125+
## Consumer guidance after a future production release
126+
127+
After production publishing is enabled in a later PR, consumers should:
128+
129+
- install only the intended project name, `sbom-diff-and-risk`
130+
- check that the PyPI version matches the expected GitHub release tag
131+
- inspect PyPI's Trusted Publishing provenance for the expected publisher identity
132+
- use GitHub artifact attestation verification for workflow-built files when downloading from GitHub
133+
- use GitHub Release verification for immutable release assets when relying on GitHub Releases
134+
- continue to treat TestPyPI as a dry-run environment only
135+
136+
## PR 5 local verification
137+
138+
PR 5 should remain a documentation and gate-design change. Local verification is still required to prove the existing package surface did not regress:
139+
140+
```powershell
141+
python -m build
142+
python -m twine check dist/*
143+
python -m pytest
144+
git diff --check
145+
```

0 commit comments

Comments
 (0)