Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/source/contributing/releasing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ the default branch, and ``tag`` pulled ``main`` before tagging.
``::warning`` naming both commits and what is missing, and the run stays
green. A ``v*`` push of such a version still fails with the
check's ``::error``. A partial release is finished by re-running the run that
tagged it.
tagged it, or, for Anaconda files that run's own ``conda`` legs cannot
build, by Conda Update's ``publish`` dispatch (see `Recovery`_).
* ``pypi`` and ``conda`` attach their files with ``gh release upload``, in
their "Upload package to GitHub Release" steps, not ``action-gh-release``,
which calls Update a release before every upload (3.0.2's ``src/github.ts:631-683``). A file
Expand Down Expand Up @@ -557,6 +558,14 @@ platform/Python distribution before uploading and skips only that leg's
upload if it is already there. Neither replaces a file the GitHub Release
already has (`#1640 <https://github.com/JarryShaw/PyPCAPKit/issues/1640>`__).

A re-run repeats the tagged commit's own workflow, so it cannot upload
Anaconda files that commit's ``conda`` legs cannot build: 1.5.0b14's
``osx-64`` legs were broken at its tag (:issue:`2140`). While ``main``'s version
is still the tagged one, dispatching Conda Update with ``publish`` on ``main``
builds ``main`` and uploads every platform under a bumped build
(:issue:`2060`, :pr:`2150`), and the warning a later commit's run posts for an
unfinished release names that remedy wherever Anaconda files are missing.

**A re-run does not need to be verified by hand against the PyPI and Anaconda
listings, because** ``release_status`` **does it.** That job runs on every
``Create Release`` attempt regardless of what else skipped, and reconciles
Expand Down
36 changes: 35 additions & 1 deletion tests/project/test_release_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -3570,7 +3570,41 @@ def test_a_version_tagged_elsewhere_names_both_commits_and_the_remedy(self) -> N
f'::warning title=v1.5.0b12 is unfinished (#1634)::v1.5.0b12 names {TAGGED_COMMIT}, not this '
f"run's commit {RUN_COMMIT}, and still lacks some of its PyPI files, some of its Anaconda files. "
f"Only that commit's run may finish it (#1634), so this run released nothing: re-run the Create "
f'Release run created for {TAGGED_COMMIT}, or release the next version.',
f'Release run created for {TAGGED_COMMIT}, or release the next version. Its Anaconda files are the '
"exception: while main's version is still 1.5.0b12, dispatch Conda Update with publish on main, "
'which uploads every platform under a bumped build (#2060); the re-run finishes them only if that '
"run's own conda legs can still succeed.",
])

def test_missing_anaconda_files_name_the_conda_update_dispatch(self) -> None:
"""#2140: 1.5.0b14's shape -- only Anaconda files lacking, which the tag's own legs could not build."""
overrides = dict(next(row[1] for row in self.VECTORS
if row[0] == 'tag_on_another_commit_release_unfinished'))
overrides.update({'PCAPKIT_VERSION': '1.5.0b14'})
result = self._run(overrides)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout.splitlines(), [
f'::warning title=v1.5.0b14 is unfinished (#1634)::v1.5.0b14 names {TAGGED_COMMIT}, not this '
f"run's commit {RUN_COMMIT}, and still lacks some of its Anaconda files. Only that commit's run may "
f'finish it (#1634), so this run released nothing: re-run the Create Release run created for '
f'{TAGGED_COMMIT}, or release the next version. Its Anaconda files are the exception: while '
"main's version is still 1.5.0b14, dispatch Conda Update with publish on main, which uploads "
"every platform under a bumped build (#2060); the re-run finishes them only if that run's own "
'conda legs can still succeed.',
])

def test_complete_anaconda_files_keep_the_re_run_remedy_alone(self) -> None:
"""#2140: with Anaconda complete, the PyPI files' remedy is still only the re-run."""
overrides = dict(next(row[1] for row in self.VECTORS
if row[0] == 'tag_on_another_commit_release_unfinished'))
overrides.update({'PCAPKIT_PYPI_COMPLETE': 'false', 'PCAPKIT_CONDA_COMPLETE': 'true'})
result = self._run(overrides)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout.splitlines(), [
f'::warning title=v1.5.0 is unfinished (#1634)::v1.5.0 names {TAGGED_COMMIT}, not this '
f"run's commit {RUN_COMMIT}, and still lacks some of its PyPI files. Only that commit's run may "
f'finish it (#1634), so this run released nothing: re-run the Create Release run created for '
f'{TAGGED_COMMIT}, or release the next version.',
])

def test_the_release_apps_tag_push_is_quiet(self) -> None:
Expand Down
11 changes: 9 additions & 2 deletions tests/project/test_release_status_scripts_1967.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
cases below, and the script on the same, and requires the same status,
standard output and error, ``$GITHUB_OUTPUT``, ``$GITHUB_STEP_SUMMARY`` and
``gh`` calls. The former body is kept here verbatim, and the case table is
checked to reach every branch of it.
checked to reach every branch of it. The one sentence the shell never had,
the Anaconda remedy #2140 added, is dropped from the script's output first;
:mod:`tests.project.test_release_gates` pins it.
* :class:`TestTheVendorUpdateStaysInline` pins ``vendor_update``'s "Read whether
its vendor-update job ran", which #1967 moved to a script and then put back
inline as too plain to need one, to its shell verbatim, with no checkout, and
Expand Down Expand Up @@ -270,6 +272,11 @@
'PCAPKIT_RELEASED_AT': OTHER}
#: A value standing for a variable left unset.
UNSET = None
#: The sentence #2140 appended to the unfinished warning where Anaconda files are
#: missing, which the former shell never printed.
ANACONDA_REMEDY = re.compile(r"(?m) Its Anaconda files are the exception: while main's version is still .*?, "
r"dispatch Conda Update with publish on main, .*? only if that run's own conda legs "
r'can still succeed\.$')

#: ``release_status``'s cases: ``(name, overrides of STATUS_BASE)``.
STATUS_CASES = (
Expand Down Expand Up @@ -524,7 +531,7 @@ def test_the_release_status(self) -> None:
for name, overrides in STATUS_CASES + tuple(sampled_status_cases()):
with self.subTest(case=name):
old, new = self.run_both(FORMER_STATUS, 'release_status.py', self.status_env(overrides))
self.assertEqual(new, old)
self.assertEqual((new[0], ANACONDA_REMEDY.sub('', str(new[1])), *new[2:]), old)

def test_every_status_branch_is_reached(self) -> None:
"""The curated cases alone reach each of :data:`STATUS_BRANCHES`, each case exactly one."""
Expand Down
12 changes: 10 additions & 2 deletions util/release_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
2. ``version_check`` did not succeed: a warning.
3. The release test gate failed or was cancelled: a warning.
4. The version is tagged at another commit and every publisher skipped (#1748):
a notice if that release is complete, else a warning naming what it lacks.
a notice if that release is complete, else a warning naming what it lacks,
and, for Anaconda files, Conda Update's ``publish`` dispatch (#2140).
5. Each publisher reconciled against its own evidence -- succeeded, or skipped
with its evidence saying done: a notice if all reconciled, a warning if one
failed or was cancelled, and otherwise the ``::error``.
Expand Down Expand Up @@ -141,11 +142,18 @@ def report_elsewhere() -> 'None':
'(#1748).')
return
version = var('PCAPKIT_VERSION')
# #2140: the re-run repeats the tagged commit's own conda legs, so it cannot
# upload what they could not build -- 1.5.0b14's osx-64, broken at its tag.
# Conda Update's `publish` dispatch builds main instead (#2060).
anaconda = (f" Its Anaconda files are the exception: while main's version is still {version}, dispatch Conda "
'Update with publish on main, which uploads every platform under a bumped build (#2060); the '
"re-run finishes them only if that run's own conda legs can still succeed."
if var('PCAPKIT_CONDA_COMPLETE') != 'true' else '')
say('warning', f'v{version} is unfinished (#1634)',
f"v{var('PCAPKIT_VERSION')} names {var('PCAPKIT_RELEASED_AT')}, not this run's commit "
f"{var('PCAPKIT_RUN_SHA')}, and still lacks {', '.join(missing)}. Only that commit's run may finish it "
'(#1634), so this run released nothing: re-run the Create Release run created for '
f"{var('PCAPKIT_RELEASED_AT')}, or release the next version.")
f"{var('PCAPKIT_RELEASED_AT')}, or release the next version.{anaconda}")


def jobs() -> 'str':
Expand Down
Loading