From 32d20fc97d47bb82d498d61feadf8839d0c57ecf Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Thu, 1 Oct 2026 00:22:30 -0400 Subject: [PATCH] docs(contributing): correct pep.rst's release gating description (#956) The page claimed all four publishing jobs are gated on `startsWith(github.ref_name, 'v') || PCAPKIT_TAG_EXISTS == 'false'`, and that an ordinary commit makes "all four jobs skip" for that reason. Only `github` gates on `PCAPKIT_TAG_EXISTS` (create-release.yml:343). The other three gate on their own target: - `tag` on `PCAPKIT_CONDA_TAG_EXISTS` (:447) - `pypi` on `PCAPKIT_PYPI_COMPLETE` (:525) - `conda` on `PCAPKIT_CONDA_COMPLETE` (:625) Three things the page left out, all load-bearing: - each of those three also requires `version_check` to have strictly succeeded, because `!cancelled()` suppresses the `success()` Actions prepends over the whole `needs:` list; - `github` -- and for `conda` also `tag` -- must have succeeded or skipped, which is what stops a legitimate skip cascading; - naming those two states rather than writing `!= 'failure'` is what makes a cancelled dependency skip the job below it cleanly instead of running it against an artefact never produced (:121-128, pinned by test_release_gates.py:624). The shared shape is kept, since it is the true common fact: gate on the `v*` ref, or on evidence the target still needs publishing. The three per-job conditions are named by what they check rather than by their literal expressions, so the page does not re-acquire a boolean that can drift. tests/project/test_release_gates.py pins this shape and passes unchanged: 34 tests, 23 subtests, re-derived as 34 under plain unittest. --- docs/source/contributing/pep.rst | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/source/contributing/pep.rst b/docs/source/contributing/pep.rst index 5b747eae0..7b86823e9 100644 --- a/docs/source/contributing/pep.rst +++ b/docs/source/contributing/pep.rst @@ -859,11 +859,26 @@ lists only ``push`` on ``v*`` tags and a ``workflow_run``. The chain is: -> "Create Release" (workflow_run, on Vendor Update completing) Every publishing job — ``github``, ``tag``, ``pypi``, ``conda`` — is gated on -``startsWith(github.ref_name, 'v') || PCAPKIT_TAG_EXISTS == 'false'``. That gate -is why ordinary commits do not publish: ``Create Release`` runs on each one, but -the tag for the current version already exists, so all four jobs skip. Changing -the version string is what makes ``PCAPKIT_TAG_EXISTS`` false, and the next push -then tags and publishes. So: +``startsWith(github.ref_name, 'v')`` or on evidence that its own target still +needs publishing. Only ``github`` gates on ``PCAPKIT_TAG_EXISTS``, because the +tag that output answers for is the one ``github`` is about to create. ``tag``, +``pypi`` and ``conda`` each gate on their own target instead -- whether the +matching Conda tag exists, whether PyPI's file count for the version has +reached the expected total, whether Anaconda's upload is complete. Each of +those three additionally requires ``version_check`` to have succeeded, and +``github`` -- and, for ``conda``, ``tag`` -- to have succeeded *or skipped*. +Those conditions open with ``!cancelled()``, which suppresses the ``success()`` +Actions would otherwise prepend; accepting ``skipped`` is then what stops an +upstream job's legitimate skip cascading into skipping a job whose own evidence +says it still has work to do. Naming the two states rather than writing "not +failed" is deliberate: a *cancelled* dependency then skips the job below it +cleanly, instead of letting it run against an artefact that was never +produced. + +That is why an ordinary commit does not publish: the version string has not +moved, so each job's own check finds its target already there and all four +skip. Changing the version string is what flips every one of those checks, and +the next push then tags and publishes. So: .. list-table:: :header-rows: 1