Skip to content

Commit 48bec02

Browse files
fix(ci): coordinate the reviewed PyPI publisher security update (#50)
Update publisher v1.14.3 together with the semantic checker and reviewed SHA regression coverage. Preserve all Trusted Publisher, OIDC, approval, and smoke boundaries. Verified upstream action metadata and security advisory, 780 local tests, complete package and standalone gates, and all nine exact-head CI jobs.
1 parent 88608e6 commit 48bec02

6 files changed

Lines changed: 38 additions & 13 deletions

File tree

‎.github/workflows/publish.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ jobs:
383383
working-directory: release-bundle
384384
run: sha256sum --check artifact-sha256.txt
385385
- name: Publish through the configured PyPI Trusted Publisher
386-
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1, node24
386+
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3, node24
387387
with:
388388
packages-dir: release-bundle/dist/
389389
print-hash: true

‎AGENTS.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,12 @@ Post-stable invariants:
134134
state read-only, and stop. Do not use another main push or recovery path
135135
until the exact external state is known and recovery is separately
136136
authorized.
137-
Keep the PyPI publisher v1.14.1 pinned to the reviewed commit whose
137+
Keep the PyPI publisher v1.14.3 pinned to the reviewed commit whose
138138
composite action uses the Node 24 `setup-python` fallback. The workflow
139139
checker must reject any other publisher SHA without changing the top-level
140-
workflow, job, environment, or Trusted Publisher identity.
140+
workflow, job, environment, or Trusted Publisher identity. Publisher upgrades
141+
must update the workflow pin, semantic-checker constants, regression tests,
142+
and current maintenance guidance together after reviewing upstream changes.
141143
10. `README.md` is the distribution long description and must remain accurate
142144
before and after publication. Use `python -m pip install cometapi`,
143145
unversioned project links, and publication-neutral maintenance language.

‎CONTRIBUTING.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ direct wheel build with the locked Twine validator. Change the metadata format
5151
or backend pin only together with verified support in the validation and
5252
publication tools.
5353

54+
Dependabot can update a protected publisher Action SHA before its semantic
55+
contract has been reviewed. Review the upstream action definition and runtime
56+
dependencies, then update the workflow SHA and version comment,
57+
`PYPI_PUBLISH_ACTION_SHA` and `PYPI_PUBLISH_ACTION_VERSION` in
58+
`scripts/check_workflows.py`, regression coverage, and current maintenance
59+
guidance in the same pull request. Run the complete checks above and retain the
60+
exact-SHA rejection tests. Do not remove the guard or relax release conditions,
61+
permissions, or protected-environment requirements to make an update pass.
62+
5463
If a check is unavailable, say so in the pull request rather than describing
5564
it as passing.
5665

‎RELEASING.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,17 @@ whose immutable action metadata selects `node24`. The semantic
173173
checker rejects any other pin so the workflow cannot silently regress to the
174174
deprecated Node 20 runtime.
175175

176-
The direct PyPI publisher v1.14.1 is pinned to the reviewed commit. Its only
177-
action-definition change from the previously reviewed publisher is the
178-
conditional `setup-python` fallback moving from Node 20 to Node 24; the
176+
The direct PyPI publisher v1.14.3 is pinned to
177+
`7245906fb61fa33a13554f9d5fb856fe61758086`. The reviewed
178+
[upstream comparison](https://github.com/pypa/gh-action-pypi-publish/compare/ba38be9e461d3875417946c167d0b5f3d385a247...7245906fb61fa33a13554f9d5fb856fe61758086)
179+
retains the composite action definition and Node 24 `setup-python` fallback.
180+
Its runtime updates include Twine, Sigstore, and certifi plus hashed dependency
181+
constraints. The certifi and Sigstore update addresses
182+
[GHSA-5xjx-3w67-w9x9](https://github.com/pypa/gh-action-pypi-publish/security/advisories/GHSA-5xjx-3w67-w9x9).
183+
The semantic checker requires this exact publisher SHA while preserving the
179184
top-level `publish.yml`, `publish` job, `pypi` environment, and Trusted
180-
Publisher identity remain unchanged. The semantic checker requires this exact
181-
publisher SHA.
185+
Publisher identity. Local CI does not exercise OIDC publication or attestations;
186+
those require the separately authorized release workflow.
182187

183188
The job invokes the pinned action release-only first with
184189
`skip-github-pull-request: true`. That step cannot continue on error and is

‎scripts/check_workflows.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
RELEASE_PLEASE_ACTION_VERSION = "5.0.0"
3434
RELEASE_PLEASE_ACTION_RUNTIME = "node24"
3535
RELEASE_PLEASE_ACTION = f"googleapis/release-please-action@{RELEASE_PLEASE_ACTION_SHA}"
36-
PYPI_PUBLISH_ACTION_SHA = "ba38be9e461d3875417946c167d0b5f3d385a247"
37-
PYPI_PUBLISH_ACTION_VERSION = "1.14.1"
36+
PYPI_PUBLISH_ACTION_SHA = "7245906fb61fa33a13554f9d5fb856fe61758086"
37+
PYPI_PUBLISH_ACTION_VERSION = "1.14.3"
3838
PYPI_PUBLISH_ACTION_RUNTIME = "node24"
3939
PYPI_PUBLISH_ACTION = f"pypa/gh-action-pypi-publish@{PYPI_PUBLISH_ACTION_SHA}"
4040
RELEASE_PLEASE_BRIDGE_VERSION = "0.1.0-alpha.1"

‎tests/test_release_workflow.py‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,13 +500,22 @@ def test_pypi_publisher_uses_reviewed_node24_action() -> None:
500500
check_publish_workflow(text, LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8"))
501501

502502

503-
def test_pypi_publisher_rejects_another_full_sha() -> None:
503+
@pytest.mark.parametrize(
504+
"unreviewed_sha",
505+
[
506+
"ba38be9e461d3875417946c167d0b5f3d385a247",
507+
"dc37677b2e1c63e2034f94d8a5b11f265b73ba33",
508+
"cef221092ed1bacb1cc03d23a2d87d1d172e277b",
509+
],
510+
ids=["prior-1.14.1", "prior-1.14.2", "unreviewed"],
511+
)
512+
def test_pypi_publisher_rejects_another_full_sha(unreviewed_sha: str) -> None:
504513
text = PUBLISH_WORKFLOW.read_text(encoding="utf-8").replace(
505514
PYPI_PUBLISH_ACTION,
506-
"pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b",
515+
f"pypa/gh-action-pypi-publish@{unreviewed_sha}",
507516
1,
508517
)
509-
with pytest.raises(RuntimeError, match=r"pypa/gh-action-pypi-publish@ba38be9"):
518+
with pytest.raises(RuntimeError, match=re.escape(PYPI_PUBLISH_ACTION)):
510519
check_publish_workflow(text, LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8"))
511520

512521

0 commit comments

Comments
 (0)