Conversation
Both verification pipelines fail on every tag at *⤴ Publish Python wheel package to PyPI* - `_Checking_SimplePackage_Pipeline.yml` and `_Checking_NamespacePackage_Pipeline.yml`, on v7.14.1 and again on v7.15.0. `myPackage` and `myFramework.Extension` are fixtures that exist to exercise the job templates; nobody publishes them. The failure only appears on tags, which is exactly the run someone checks before cutting a release. `PublishOnPyPI.yml` gains a `dry_run` input. When enabled, the two `twine upload` steps are replaced by a single `twine check dist/*.whl dist/*.tar.gz`. Everything before them is unchanged, so the artifact download, the Python setup and the dependency install are still exercised, and the package metadata is validated rather than merely built. `CompletePipeline.yml` forwards it as `pypi_dry_run`, defaulting to `'false'` so no consumer changes behaviour. Skipping the job entirely - an input that drops `PublishOnPyPI` from the pipeline - was the alternative. It would leave the job template unverified, which is what the verification pipelines exist to prevent, so a dry run that still reaches the packages was preferred. Setting `pypi_dry_run: 'true'` in the two verification pipelines is deliberately *not* part of this commit. They call `CompletePipeline.yml@dev`, so an input that exists only on this branch makes GitHub reject the workflow file before a runner is assigned - "This run likely failed because of a workflow file issue". The switch is flipped in a follow-up once this input is on `dev`. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…lates. Both were written as local reusable workflows in 'pyTooling/SynchronizeForks' and have run there through two releases; they are generic and belong here. 'UpdateVersionBranch' proposes the update of a major-version branch as a pull-request, titled like 'Updating r8 from v8.1.0'. A major without a branch is created from the highest existing lower major rather than from the main branch - a branch cut from the main branch is already identical to it, so there would be nothing to open a pull-request about. References to the repository itself are rewritten to name the version branch; where a rewrite is needed it becomes a commit on an update branch, and the pull-request is opened from there. 'CheckMarketplaceMetadata' validates an action's metadata file against the GitHub Marketplace rules on every push, instead of discovering a violation in the publish form. Publishing itself has no API and stays manual. The 'workflow_dispatch' trigger both carried in their original repository is dropped: no job template here has one. Neither is wired into this repository's own checking workflows. 'UpdateVersionBranch' creates branches and pull-requests, and 'CheckMarketplaceMetadata' would fail here by design, because this repository has no 'action.yml' at its root. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Taking the template into 'pyTooling/download-artifact' and 'pyTooling/upload-artifact' showed the assumption was too narrow: both tag releases as 'v1.x.y' while publishing 'v4' ... 'v8' branches, so the branch number is not the released version's major and deriving it would target 'v1'. The optional 'major' parameter states it. Empty, the behaviour is unchanged. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
* The check is written in Python via 'shell: python' instead of a shell script with an embedded Python fragment. The step reads YAML and validates five rules, which is what Python is for; the metadata is parsed with 'ruamel.yaml', installed after 'actions/setup-python', and a new 'python_version' parameter selects the interpreter. * 'ubuntu_image' is the first input parameter in both templates and in both documentation pages, matching the other job templates. * The instantiation example names its job 'CheckMarketplace' rather than 'Marketplace', so the instance says which template it is. * One empty line before 'outputs:' in 'UpdateVersionBranch.yml', and its environment block is aligned again - 'MAIN_BRANCH' had pushed the column. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
`CompletePipeline.yml` guards `PublishToGitHubPages` on the ref, because the `github-pages` environment rejects a deployment from a feature branch before a runner is assigned - one second, no steps, no log - so every feature-branch pipeline showed a red job unrelated to its changes. The guard was written as an allowlist of the two refs that had been observed to deploy: the default branch and `dev`. On a tag push `github.ref_name` is the tag, so the job is **skipped** - silently, on the release run, which is the run whose documentation matters most. Tags are admitted by the environment. pyVHDLModel's v0.39.0 pipeline, still on `@r7`, deployed Pages from `ref_name = v0.39.0` (https://github.com/VHDL/pyVHDLModel/actions/runs/30951229155, job `PublishToGitHubPages` success). `github.ref_type == 'tag'` is added to the condition. Feature branches are still blocked, which is what the guard was for. `documentation_steps` defaults to `'html pages'`, so all eleven repositories calling `CompletePipeline.yml` publish Pages and all eleven would have lost their release-run documentation on moving to `@r8`. None has moved yet. `doc/Development.rst` gains the rule this came from: a condition gating a job on the ref is a blocklist of the refs that cannot work, never an allowlist of the refs that have been seen to work - an allowlist built from one observed rejection drops every ref that was never tried, and drops it by skipping, which no pipeline reports. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
PrepareJob evaluates the new 'publish_pages_on' input into the 'publish_pages' output; CompletePipeline forwards the input and gates 'PublishToGitHubPages' on that output instead of a hard-coded list of refs. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…ions'. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…lib'. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…tplotlib' as well. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…sed or doesn't match the code.
'VersionCheck' gates 'TriggerTaggedRelease', 'ReleasePage' and 'PublishOnPyPI' and fails instead of being skipped;
it compares with the new 'package_version' output of 'Parameters.yml'. The new 'CheckReleaseVersion.yml' asks PyPI
for an existing release ('check_pypi_duplicate'), and 'TagReleaseCommit.yml' refuses an existing tag or release page.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'CheckReleaseVersion.yml' runs 'VersionCheck' (compare with 'PythonVersion', no 'packaging') and 'RegistryCheck' (new input 'pypi_url', default 'https://pypi.org'; no 'r' prefix handling). 'CompletePipeline.yml' calls it once instead of a local job, staying at 20 distinct reusable workflows. Inputs are inlined instead of passed through 'env:', and 'TagReleaseCommit.yml' exports 'GH_TOKEN' like 'PrepareJob.yml' and 'PublishReleaseNotes.yml'. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…her than PyPI. 'PublishOnPyPI.yml' gains 'pypi_upload_url' (default 'https://upload.pypi.org/legacy/'), passed to 'twine upload --repository-url'. 'CompletePipeline.yml' gains 'pypi_url', forwarded to 'CheckReleaseVersion.yml', and 'pypi_upload_url', forwarded to 'PublishOnPyPI.yml' - a registry's upload URL isn't its base URL. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
It only named the file in error messages. An empty 'package_version' now fails the check with one message, and 'Parameters.yml' already warns about a missing version file. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…ed or doesn't match the code (#261)
…m through 'env:'.
The three steps read '${{ inputs.* }}', '${{ github.repository }}' and the previous steps' outputs directly, and export
'GH_TOKEN' in the script like 'PrepareJob.yml' and 'PublishReleaseNotes.yml'. A shell variable remains only where the
value is changed: the version without its prefix and the escaped repository name.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
🟢 Coverage 100.00% diff coverage · +0.00% coverage variation
Metric Results Coverage variation ✅ +0.00% coverage variation Diff coverage ✅ 100.00% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (8e631fc) 45 41 91.11% Head commit (4b1ca13) 45 (+0) 41 (+0) 91.11% (+0.00%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#264) 1 1 100.00% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
'Pipeline.yml' classifies the ref, calls the five verification workflows, tags a release commit when all of them succeeded, and on the tag run publishes the release page and opens the pull-request moving the version branch. The verification workflows exchange their 'push' trigger for 'workflow_call', and the release jobs leave '_Checking_JobTemplates.yml'. The fixture pipelines and the template test publish nothing: 'pypi_dry_run' and 'dry_run' are 'true'. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…over all jobs. 'Pipeline.yml' called the five verification workflows, which collected about 170 jobs into a single run - unreadable when one of them fails. They keep their own 'push' trigger and their own runs; the new 'Release.yml' waits for their runs of the release commit, tags it, and on the tag run publishes the release page and opens the version-branch pull-request. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'Prepare' -> 'Verifications' could not be exercised before the workflow sits
on 'main': the push trigger is 'main' only, and 'workflow_dispatch' needs the
file on the default branch ('dev'), where it isn't either. The PR branch is
added to the push trigger as a scaffold, to be removed before merging.
The release jobs need no new condition to stay out of the way - 'Classify' in
'PrepareJob.yml' sets 'is_release_commit' for a merge commit on the main
branch only. 'TriggerTaggedRelease' compares the ref a second time regardless,
because creating a tag is the one irreversible step.
'Verifications' waited out its 120 minute timeout when a workflow had no run
for the commit at all: the API reports 'null', which never equals 'completed',
so the 'NO RUN' error below the loop was unreachable. The wait for a run to
appear is now bounded by 'noRunTimeout'.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'Verifications' queried one workflow at a time and blocked on it, so a workflow that finished later in the list stayed unseen until its turn came, and every interval cost one request for the whole wait. 'actions/runs?head_sha=' reports every run of the commit, so one request per pass now covers all five workflows. Runs are listed newest first, so the first line for a workflow is its current run and a superseded re-run is ignored - 'per_page=1' had read whichever run was newest. A workflow that concluded is removed from the wait and neither queried nor printed again. The interval is 15 s (was 60 s), and the loop has its own timeout, both overridable per run through the new 'poll_interval' and 'poll_timeout' dispatch inputs. The job's 'timeout-minutes' stays the outer bound; the loop's default of 6600 s reports the workflows still pending before that hits. Local harness '_scratchpad/release-checks/test-poll.py' (stubbed 'gh'): all five green in one pass, a failure named and refused, a missing run reported as 'NO RUN' without consuming the timeout, a shrinking wait list reporting each workflow exactly once over three passes, and a refusal when the timeout expires while runs are still in progress. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'Release.yml' had 'claude/actions-pipeline' in its push trigger so the gate could run before the workflow was on 'main'. It is on 'main' now, and the branch is gone, so the trigger is 'main' alone again. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Every consumer's main workflow is 'Pipeline.yml' with 'name: Pipeline', and the workflows this repository checks itself with are prefixed '_Checking_'. This one is the repository's pipeline, so it takes that name. 'Prepare' and 'Verifications' are useful on any branch: they report in one job whether the five verification workflows of a commit succeeded, which is otherwise five runs to read. The push trigger is no longer limited to 'main'. The release jobs need no new condition - 'is_release_commit' is only true for a merge commit on the main branch, 'is_release_tag' only at a tag, and 'TriggerTaggedRelease' compares the ref a second time. A branch run skips all three, as observed on 'claude/actions-pipeline'. 'TagReleaseCommit.yml' defaults its 'workflow' input to 'Pipeline.yml', so the explicit input is gone with the rename. Branch runs now cancel their predecessor: a branch only needs the roll-up of its newest commit, and 'Verifications' occupies a runner until the checks it waits for finish. 'main' and tags keep the old behaviour. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
The PDF build died in the first table of the document with
./myPackage.tex:1260: TeX capacity exceeded, sorry [input stack size=10000].
<inserted text> \the \everycr
l.1260 \end{tabulary}
Sphinx' default 'latex_table_style' is ['booktabs', 'colorrows']. For
'colorrows' it sets colortbl's '\CT@everycr' to the token list '\the\everycr',
while colortbl sets '\everycr' to '\the\CT@everycr': each expands into the
other until TeX's input stack is full. colortbl is 2026/05/01 v1.0l.
The 56 "undefined reference" warnings in that job were a consequence - lualatex
returned 1, latexmk stopped, and nothing resolved the references on a second
pass.
Checked with MiKTeX 26.5 installed locally, the same version the image uses:
the document builds to 275 pages with no capacity error. Tables lose their
alternating row colors and keep the booktabs rules.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
The default release-notes footer credited 'pyTooling/Actions::Release.yml'. That file was renamed to 'Pipeline.yml', but naming it there would be wrong either way: the footer appears on a **consumer's** release page, and what wrote it is the 'PublishReleaseNotes.yml' job template, not this repository's own pipeline. The documentation copy of the default is updated with it. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New Features
CheckReleaseVersion.yml- a new job template refusing a release before it is tagged (Refuse a release before it's tagged, if its version is already released or doesn't match the code #261). ItsVersionCheckjob compares the version from the pull-request title or tag with the__version__in the Python code, andRegistryCheckasks a package registry whether that version is already released. Both run early in the pipeline, so a missing version bump or a duplicate release shows within the first minutes.CompletePipeline.ymlcalls it asVersionCheckand gatesTriggerTaggedRelease,ReleasePageandPublishOnPyPIon its result.CompletePipeline.yml:version_file(default'__init__.py'),check_pypi_duplicate(default'true'),pypi_url(default'https://pypi.org') andpypi_upload_url(default'https://upload.pypi.org/legacy/').UpdateVersionBranch.yml- proposes the update of a major-version branch as a pull-request, titled likeUpdating r8 from v8.1.0(Add the 'UpdateVersionBranch' and 'CheckMarketplaceMetadata' job templates #260). A new major branches off the highest existing lower major, and self-references (<owner>/<repo>[/<path>]@<ref>, workflow-status badges) are rewritten on anupdate/<branch>branch, so no consumable branch is force-pushed. Proven inpyTooling/SynchronizeForksacross v1.0.0 and v1.0.1.CheckMarketplaceMetadata.yml- validates an action's metadata against the GitHub Marketplace rules on every push: file at the repository root, name, description shorter than 125 characters, branding icon and colour, public repository (Add the 'UpdateVersionBranch' and 'CheckMarketplaceMetadata' job templates #260). The Marketplace itself checks this only at publish time, in a web form.PrepareJob.yml: new inputpublish_pages_onand outputpublish_pages(Let the caller choose the refs on which GitHub Pages are published #259) - a newline separated list of or-ed conditions on the pipeline's ref:default-branch,main-branch,development-branch,release-branch,release-tag,nightly-tag,branch=<regexp>andtag=<regexp>.CompletePipeline.ymlforwards it and gatesPublishToGitHubPageson the result, so a repository chooses when GitHub Pages are published. An unknown condition or a broken regular expression fails every pipeline, not only the tag run.PublishOnPyPI.yml: new inputdry_run, forwarded byCompletePipeline.ymlaspypi_dry_run(Add a dry-run mode to PublishOnPyPI #256). The twotwine uploadsteps are replaced by onetwine check, so a pipeline building a package that is never published validates its metadata instead of failing at the upload.PublishOnPyPI.yml: new inputpypi_upload_url, passed totwine upload --repository-url, so packages can go to another registry (Refuse a release before it's tagged, if its version is already released or doesn't match the code #261).Pipeline.yml- this repository releases itself from a workflow of its own (Move the release into a workflow of its own #265). The release logic used to sit inside_Checking_JobTemplates.yml, a test workflow, which is why the v8.0.0 tag had to be created by hand. The five_Checking_*.ymlworkflows keep their ownpushtrigger and their own, separately readable runs;Pipeline.ymlholds no test jobs.Prepareclassifies the commit, andVerificationswaits for the runs of those five workflows for that commit and fails if one of them didn't succeed - one request per poll covers all five, a workflow that concluded is dropped from the wait, and the interval and timeout are thepoll_interval(15 s) andpoll_timeout(6600 s) dispatch inputs.TriggerTaggedReleasethen tags the release commit. A tag created with the pipeline's token raises nopushevent, so the job starts this workflow again throughworkflow_dispatchat the tag; in that runReleasePagepublishes the notes andUpdateVersionBranchopens the pull-request movingr8.mainor a release tag.Changes
CompletePipeline.yml'sVersionCheckcompared the version before, but no job depended on it - a mismatch was a red job while tagging and publishing went on. It now runs wheneverPreparereports a version, fails instead of being skipped when it can't check, and blocks the tag, the release page and the PyPI upload.TagReleaseCommit.ymlrefuses to tag if the tag or a release page for that version already exists (Refuse a release before it's tagged, if its version is already released or doesn't match the code #261). Before, an existing tag failedcreateRefby accident and an existing release page wasn't noticed.Parameters.yml: new outputpackage_version- the__version__ofpackage_version_file(Refuse a release before it's tagged, if its version is already released or doesn't match the code #261).python-matplotlib:p, for a requirement on matplotlib itself and for the extrapyTooling[diagram]. pip can't build matplotlib inside MSYS2. numpy was already mapped.UpdateVersionBranch.ymlreads its inputs directly instead of throughenv:blocks, and exportsGH_TOKENin the script likePrepareJob.ymlandPublishReleaseNotes.yml(Inline the inputs of 'UpdateVersionBranch.yml' instead of 'env:' #263).pyTooling/Actions::PublishReleaseNotes.ymlinstead of::Release.yml. The text appears on every consumer's release page; a repository overridingrelease_notes_footeris unaffected.Bug Fixes
8fc18bc).CompletePipeline.ymlguardsPublishToGitHubPageson the ref, because thegithub-pagesenvironment rejects a deployment from a feature branch before a runner is assigned. The guard was an allowlist of the default branch anddev; on a tag pushgithub.ref_nameis the tag, so the job was skipped - silently, on the release run, whose documentation matters most.github.ref_type == 'tag'is admitted now, feature branches still aren't.PublishReleaseNotes.ymlkeeps a release page's existing text when re-run, instead of replacing it with the preliminary notes (Add a dry-run mode to PublishOnPyPI #256).Documentation
CheckReleaseVersion.rst,UpdateVersionBranch.rstandCheckMarketplaceMetadata.rst, listed in their categories and in the templates overview.CompletePipeline.rstdocumentsversion_file,check_pypi_duplicate,pypi_url,pypi_upload_url,pypi_dry_runandpublish_pages_on; its Behavior names the new checks and what they refuse.PublishOnPyPI.rstdocumentsdry_runandpypi_upload_url;PrepareJob.rstdocumentspublish_pages_onandpublish_pages;Parameters.rstdocumentspackage_version.Development.rstgains the rule behind the Pages fix: a condition gating a job on the ref is a blocklist of refs that cannot work, never an allowlist of refs that have been seen to work.GitHub Pipeline
_Checking_JobTemplates.ymlrunsCheckReleaseVersion.ymlfor an unreleased version ofpyTooling, and_Checking_Parameters.ymlcheckspackage_versionandpackage_version_filefor the simple and the namespace fixture package._Checking_Parameters.ymlcheckspublish_pagesfor a branch, a release tag and a nightly tag._Checking_JobTemplates.ymlforPipeline.yml(Move the release into a workflow of its own #265).PublishOnPyPIthere became a dry-run test that runs on every pipeline instead of only on a release tag, and both fixture pipelines setpypi_dry_run: 'true'.latex_table_style = ["booktabs"]indoc/conf.py. Sphinx' default addscolorrows, which makes colortbl's\CT@everycrand\everycrexpand into each other until TeX's input stack is full - the PDF build died in the first table of the documentation. Tables keep the booktabs rules and lose their alternating row colours.Known Issues
Verificationsoccupies a runner while it waits - up topoll_timeout, with the job's two hourtimeout-minutesbehind it.gh run rerun <id>, nevergh run rerun <id> --failed, and only after the run has finished.CleanupArtifactsis guarded by!cancelled(), so it deletes the intermediate artifacts even when the job consuming them failed; re-running just the failed jobs then stops atUnable to download artifact(s): Artifact not found. This affects every pipeline built fromCompletePipeline.yml, not only this repository.Related Issues and Pull-Requests
Note
Why 8.1.0 and not 9.0.0. No parameter changes its meaning: every change either adds an input with a default that keeps the previous behaviour, or makes a check that was already there refuse a release it should never have allowed (#261).
Two defaults are worth naming.
check_pypi_duplicatedefaults to'true', so a release commit asks PyPI - a package that isn't published there answers 404 and passes. AndVersionChecknow fails where it used to be skipped: a repository keeping__version__somewhere other than the package's root__init__.pyhas to setversion_file. Every repository callingCompletePipeline.ymlkeeps it in the root__init__.py.