@@ -50,12 +50,12 @@ Editing ``__version__`` by hand without also moving :file:`CITATION.cff`'s
5050``tests/project/test_bump_version.py ``'s
5151``RepositoryCitationTests.test_the_citation_file_names_the_packaged_version ``
5252(``:494-514 ``) asserts the two agree, and ``create-release.yml ``'s
53- ``unit-tests `` job (``:467-481 ``) calls ``unit-tests.yml `` with
53+ ``unit-tests `` job (``:579-595 ``) calls ``unit-tests.yml `` with
5454``gate-only: true ``, which runs the **full ** suite rather than the tiered
5555subset an ordinary push runs (its ``gate `` job, ``unit-tests.yml:1776-1846 ``).
5656That gate runs whenever a release will -- a moved ``__version__ `` is exactly
5757what makes ``version_check ``'s evidence read "not yet published" -- and every
58- publishing job requires it to have succeeded (``:500,685,850,1085 ``), so a
58+ publishing job requires it to have succeeded (``:619,806,972,1208 ``), so a
5959citation left behind fails the gate well before any approval is requested.
6060Either run the script, or move both fields by hand in the same commit.
6161
@@ -66,7 +66,7 @@ process: the ``changelog`` job (``unit-tests.yml:1624-1643``) fails outright if
6666``CHANGELOG.md `` has drifted from its source entry under
6767:file: `docs/source/changelog/ `, and the release-body step warns, without
6868failing, if that entry's heading still reads "unreleased"
69- (``create-release.yml:554-555 ``). Both enforce what the changelog convention
69+ (``create-release.yml:675-676 ``). Both enforce what the changelog convention
7070already asks for.
7171
7272Two Ways to Start a Release
@@ -79,12 +79,12 @@ neither is a workaround for the other:
7979``push: tags: ['v*'] ``
8080 Pushing a tag matching ``v* `` yourself. This chooses **which commit ** to
8181 release, not which version: ``version_check ``'s checkout
82- (``:216-220 ``) pins ``ref: ${{ github.sha }} ``, which on this trigger is
82+ (``:298-302 ``) pins ``ref: ${{ github.sha }} ``, which on this trigger is
8383 the commit the pushed tag points at, and reads ``pcapkit.__version__ `` out
84- of *that * tree (``:245 ``). Every downstream tag and release name is built
84+ of *that * tree (``:327 ``). Every downstream tag and release name is built
8585 from that output -- ``v${{ needs.version_check.outputs.PCAPKIT_VERSION }} ``
86- is ``github ``'s ``tag_name `` at ``:596 `` and the release ``pypi `` and
87- ``conda `` upload to at ``:992 `` and ``:1338 ``, always from
86+ is ``github ``'s ``tag_name `` at ``:717 `` and the release ``pypi `` and
87+ ``conda `` upload to at ``:1115 `` and ``:1462 ``, always from
8888 ``PCAPKIT_VERSION ``, never from ``github.ref_name `` -- so the version
8989 actually released is whatever ``__version__ `` says on the tagged commit,
9090 not the name of the tag that was pushed. The two agree only if the tag
@@ -124,6 +124,13 @@ conclude ``success`` is keyed on its own ``github.run_id`` instead
124124(`#1705 <https://github.com/JarryShaw/PyPCAPKit/issues/1705 >`__). It releases
125125nothing, so it neither waits behind a release nor displaces a run waiting
126126there; only a newer run that may release, reading ``main ``'s newer tip, can.
127+ A Vendor Update that concluded ``success `` with ``vendor-update `` skipped --
128+ its Unit Tests verdict was for another commit -- releases nothing either since
129+ `#1748 <https://github.com/JarryShaw/PyPCAPKit/issues/1748 >`__: the
130+ ``vendor_update `` job reads that run's jobs (``:230-264 ``), and
131+ ``version_check `` skips. The group cannot see that, so such a run still joins
132+ the ref's group; if it displaces a pending run, that release waits for the
133+ next Vendor Update on ``main ``.
127134
128135One Commit per Release
129136----------------------
@@ -137,19 +144,26 @@ days later, and tagged ``main``'s tip ``2c0008c3c`` as both ``v1.5.0b9`` and
137144the default branch, and ``tag `` pulled ``main `` before tagging.
138145
139146* On ``workflow_run ``, where ``github `` creates the ``v* `` tag, it passes
140- ``target_commitish `` ``github.sha `` (``:609 ``); on a ``v* `` push the tag
147+ ``target_commitish `` ``github.sha `` (``:730 ``); on a ``v* `` push the tag
141148 already exists and it passes none. Either way it then checks that the tag
142149 names that commit.
143- * ``tag `` cuts ``conda-<version>+0 `` at that commit (``:722-749 ``) before it
150+ * ``tag `` cuts ``conda-<version>+0 `` at that commit (``:844-871 ``) before it
144151 reads ``main `` at all; the :file: `conda/build ` reset is a separate commit on
145- top of ``main `` (``:771-824 ``), described under `Precautions `_.
152+ top of ``main `` (``:893-946 ``), described under `Precautions `_.
146153* ``pypi `` and ``conda `` check out that commit and, before building, check
147154 that every tag they publish under names it, as ``tag `` does for the ``v* ``
148- tag. A run created for a *later * commit of the same version therefore fails
149- with an ``::error `` instead of publishing a second tree under that version;
150- a partial release is finished by re-running the run that tagged it.
155+ tag. A run created for a *later * commit of the same version therefore never
156+ publishes a second tree under that version. ``version_check `` resolves the
157+ ``v* `` tag the same way first (``:534-552 ``), and off a ``v* `` ref a tag
158+ naming another commit skips the gate and all four publishers
159+ (`#1748 <https://github.com/JarryShaw/PyPCAPKit/issues/1748 >`__):
160+ ``Release status `` posts a ``::notice `` if that release is complete, or a
161+ ``::warning `` naming both commits and what is missing (``:1607-1617 ``), and
162+ the run stays green. A ``v* `` push of such a version still fails with the
163+ check's ``::error ``. A partial release is finished by re-running the run that
164+ tagged it.
151165* ``pypi `` and ``conda `` attach their files with ``gh release upload ``
152- (``:985-1022 ``, ``:1333-1368 ``), not ``action-gh-release ``, which calls Update
166+ (``:1108-1145 ``, ``:1457-1492 ``), not ``action-gh-release ``, which calls Update
153167 a release before every upload (3.0.2's ``src/github.ts:631-683 ``). A file
154168 the release already has is left alone
155169 (`#1640 <https://github.com/JarryShaw/PyPCAPKit/issues/1640 >`__): the action
@@ -243,11 +257,11 @@ The owner's choice on `#1634
243257the release with a GitHub App installation token, which Create a release
244258accepts for a target that changes a workflow file when it has the "Workflows"
245259repository permission (write). "Mint the release App's token"
246- (``create-release.yml:569-577 ``) runs
260+ (``create-release.yml:690-698 ``) runs
247261``actions/create-github-app-token@v3 `` with ``permission-contents: write `` and
248262``permission-workflows: write `` and no ``owner `` or ``repositories ``, so the
249263token is "scoped to only the current repository" and revoked in the action's
250- ``post `` step (v3.3.0's README). Only Create Release spends it (``:613 ``).
264+ ``post `` step (v3.3.0's README). Only Create Release spends it (``:734 ``).
251265While ``vars.RELEASE_APP_CLIENT_ID `` is unset, which reads as "an empty
252266string", the step skips and Create Release spends ``GITHUB_TOKEN ``, so the
253267workflow keeps working, refusals included, until the App exists. A PAT would
@@ -275,15 +289,15 @@ One-time setup:
275289Unlike ``GITHUB_TOKEN ``'s, the App's tag starts a tag-push run. It would rerun
276290the release test gate, ask for a second approval and race the first run's
277291uploads from another concurrency group, so ``version_check `` skips a ``push ``
278- whose ``github.actor_id `` is ``vars.RELEASE_APP_BOT_ID `` (``:210-212 ``), and
292+ whose ``github.actor_id `` is ``vars.RELEASE_APP_BOT_ID `` (``:290-294 ``), and
279293``release_status `` reports it with ``::notice title=Nothing to release ``
280- (``:1440-1442 ``). A tag pushed by a person runs as before. Whether a tag made
294+ (``:1569-1571 ``). A tag pushed by a person runs as before. Whether a tag made
281295through the Releases API fires ``push ``, and with the bot as actor, is
282296unmeasured; if not, the guard never matches and the cost is one approval to
283297reject.
284298
285299A refused Create Release (404, or 403 "Resource not accessible by
286- integration") is explained by "Explain a refused release tag" (``:646-658 ``)
300+ integration") is explained by "Explain a refused release tag" (``:767-779 ``)
287301according to the token spent: with ``GITHUB_TOKEN `` it lists the setup above;
288302with the App's, it points at the App's permissions and installation. For a
289303final release, first delete any draft ``v<version> `` the refused run left:
@@ -432,8 +446,8 @@ Only ``github-release`` carries a required reviewer; ``conda-tag``,
432446removed on `#887 <https://github.com/JarryShaw/PyPCAPKit/issues/887 >`__.
433447What still makes one approval mean *the whole release * is the ``needs: ``
434448graph: ``tag `` and ``pypi `` both depend on ``github ``
435- (``.github/workflows/create-release.yml:685,850 ``), and ``conda `` depends on
436- ``tag `` and ``github `` (``:1085 ``) -- so nothing downstream of ``github `` can
449+ (``.github/workflows/create-release.yml:806,972 ``), and ``conda `` depends on
450+ ``tag `` and ``github `` (``:1208 ``) -- so nothing downstream of ``github `` can
437451start before it is approved, and rejecting it leaves nothing tagged and
438452nothing published. Before this change ``tag `` depended on ``version_check ``
439453alone, so removing its reviewer without moving this dependency would have let
@@ -457,8 +471,8 @@ Precautions
457471 *their own * artefact is missing rather than whether the ``v* `` tag exists, so an
458472 incomplete release runs the jobs that did not finish instead of skipping them.
459473 A half-finished release self-heals on re-running the run that tagged it
460- -- see `Recovery `_ below; a run created for a later commit refuses instead
461- (`One Commit per Release `_).
474+ -- see `Recovery `_ below; a run created for a later commit releases nothing
475+ instead, with a warning that names what is missing (`One Commit per Release `_).
462476 ``release_status `` is the other half: it runs unconditionally and reports,
463477 with a ``::notice ``, a ``::warning `` or a failing ``::error ``, why a run
464478 released nothing or that it released something, so a stranded release is
@@ -480,7 +494,7 @@ back, and neither is needed, since a plain re-run self-heals; see
480494
481495**``environment: pypi`` stays even though its reviewer is gone. ** ``pypi ``
482496publishes through PyPI's OIDC trusted publishing (``environment: pypi `` at
483- ``:845 ``, ``id-token: write `` at ``:849 ``), and PyPI's trusted-publisher
497+ ``:967 ``, ``id-token: write `` at ``:971 ``), and PyPI's trusted-publisher
484498configuration can be scoped to a GitHub Actions environment name. If this
485499project's publisher on PyPI is scoped that way, removing the ``pypi `` name
486500-- not just its reviewer -- would break the upload with a claim mismatch;
@@ -491,7 +505,7 @@ the name regardless, since there is no upside to removing it.
491505**``conda-tag`` writes to ``main``, so a release is not read-only on the
492506branch. ** After cutting ``conda-<version>+0 `` at the run's commit, the
493507``tag `` job pushes a commit setting :file: `conda/build ` to ``0 `` on top of
494- ``main `` (``.github/workflows/create-release.yml:771-824 ``) -- a plain
508+ ``main `` (``.github/workflows/create-release.yml:893-946 ``) -- a plain
495509fast-forward push, never a rewrite -- so the next Conda Update bump of that
496510version is ``+1 ``. There is none when the run's commit is not on ``main ``, nor
497511when ``main ``'s tip already says ``0 `` (the usual case, since
0 commit comments