Skip to content

v7.14.1 - #242

Merged
Paebbels merged 1 commit into
mainfrom
dev
Aug 1, 2026
Merged

v7.14.1#242
Paebbels merged 1 commit into
mainfrom
dev

Conversation

@Paebbels

@Paebbels Paebbels commented Jul 31, 2026

Copy link
Copy Markdown
Member

New Features

  • None. This is a patch release fixing defects found while verifying v7.14.0 against consumers.

Changes

  • PrepareJob.yml associates the Pull Request exactly instead of taking the first search hit. gh pr list --search <sha> lists every merged Pull Request that contains that commit, so it can return more than one — an older release Pull Request built from an ancestor matches just as well — and the code then took .[0] of an unordered list.

    The second parent (father) of a merge commit is the head commit of the merged branch, so the candidates are now reduced to those whose headRefOid equals it:

    gh pr list --base "" --search "${FATHER_SHA}" --state merged --json "title,number,headRefOid,mergedBy,mergedAt"| jq --arg sha "${FATHER_SHA}" '[.[] | select(.headRefOid == $sha)] | sort_by(.mergedAt) | reverse'

    If a Pull Request was closed and recreated from the same branch — rare, but possible — both share a head commit, and the most recently merged one is used, with a warning naming both. Everything stays derived from the commit graph.

    Verified against the real v0.38.0 release merge of VHDL/pyVHDLModel:

    commit  0e703ffa339050179408405698f5ffc78b9c7259   (on main)
    parents 244c24f (main), 61bd8eb
    PR #133 headRefOid = 61bd8eb                       -> exact, single match
    
  • No inputs, outputs or defaults were added, renamed or removed, so @r7 consumers need no adjustment.

Bug Fixes

  • PrepareJob.yml: Prepare failed for every merge commit on the development branch. The step Find merged PullRequest from second parent searches a merged Pull Request whose base is the release branch, but it was guarded by is_merge_commit alone. A merge commit pushed to the development branch originates from a Pull Request based on the development branch, so the search can never match and the step exits 1 — taking the whole Prepare job, and with it the run, down.

    Reproduced against the two most recent dev merges of VHDL/pyVHDLModel:

    merge commit on dev second parent result of the search
    d82822e (v6.5.0 #166) 1c69670 []step fails
    61bd8eb ([Snyk] Security upgrade python from 3.12-slim-bookworm to 3.14.0-slim-bookworm #165) a5a1db5 [{"number":133,"state":"MERGED","title":"v0.38.0"}] → step passes

    Both search results are correct, by the way — a5a1db5 really is one of [Snyk] Security upgrade python from 3.12-slim-bookworm to 3.13.5-slim-bookworm #133's commits, since [Snyk] Security upgrade python from 3.12-slim-bookworm to 3.13.5-slim-bookworm #133's head 61bd8eb is its descendant. The search was simply being asked a release-branch question on a dev push. The second row is what makes this more than cosmetic: an ordinary dev push was reported as the (later reverted) v0.38.0 release.

    The guard is now is_release_commit, which Classify already computes as is_merge_commit restricted to the main and version branches, and which TriggerTaggedRelease keys off as well. This is the answer to the # TODO: why not is_release_commit? that sat directly above the step.

    Why it stayed hidden: Pull Requests to a development branch used to be squash-merged, which produces no second parent, so is_merge_commit was false and the step was skipped. It surfaces as soon as a Pull Request is merged with a real merge commit.

    Downstream effect: on a development-branch merge, Prepare.outputs.version is now empty, as it already was for regular commits. VersionCheck is guarded by needs.Prepare.outputs.version != '' and is therefore correctly skipped there — it only ever ran on such pushes by way of the match above. On the release path nothing changes.

  • PrepareJob.yml: a search without a hit was not detected. gh pr list --json … returns an empty JSON array, not an empty string, so [[ "${PULL_REQUESTS}" == "" ]] never triggered. A no-match fell through to jq .[0].title → the literal null, and only the later regexp check reported it — as a confusing complaint about a title named null. No match is now an error that lists the candidates the search did return.

  • CleanupArtifacts.yml: the second delete step deleted the first set again. The step guarded itself with steps.compute2 but passed the names resolved by steps.compute:

          if: inputs.condition2 && inputs.artifact-json-ids2 != '' && steps.compute2.outputs.artifacts != ''
          with:
            name: |
              ${{ join(fromJSON(steps.compute.outputs.artifacts).*, '   # <- compute, not compute2

    So it re-deleted the artifacts the first step had already deleted — silently, because of continue-on-error: true — while every artifact named by artifact-json-ids2 survived.

    Present since the workflow was introduced in 465d2a9, but harmless until v7.14.0 made CompletePipeline.yml rely on the second set to delete the package artifact on non-release runs. Without this fix, that artifact was never cleaned up at all.

Documentation

  • doc/JobTemplate/Setup/PrepareJob.rst — the Behavior topic now states that step 4 runs for release commits only, and how the pull-request is identified (headRefOid equal to the second parent, newest wins on a tie).
  • Still outstanding from v7.14.0 and deliberately not attempted here: CleanupArtifacts.yml has no documentation page — doc/JobTemplate/Cleanup/ArtifactCleanup.rst documents the deprecated ArtifactCleanUp.yml — and the instantiation examples across 22 files still reference @r6. That needs a rework rather than a patch.

Unit Tests

  • The CleanupArtifacts.yml fix is verified on a real run. Verification of Job Templates on dev @ 1e03b93 (run 30670208319) logs

    Artifact 'myPackage-Packages' (ID: 8808477452) deleted
    

    from the second Artifact to delete: block. On the previous run (30667778312), with identical inputs, that line was absent — the package artifact was left behind.

  • The FindPullRequest step was executed offline against seven scenarios, with git and gh mocked, asserting the emitted pr_* outputs and the exit code:

    scenario result
    one exact headRefOid match pr_number=133, pr_version=v0.38.0
    containing-but-not-head PR plus the exact match (the real case above) the exact match wins
    two PRs sharing a head commit (recreated PR) newest by mergedAt wins, warning names both
    same, with the input array in the opposite order identical result — order-independent
    only a containing PR, no head match error, exit 1, candidates listed
    search returns [] error, exit 1, "no candidates at all"
    gh call itself fails error, exit 1
  • The PrepareJob.yml change is also exercised by merging this Pull Request itself: it produces a merge commit on main, which is exactly the case the step must handle.

  • Both changed workflows parse as YAML, the step's script passes bash -n, and the changed .rst produces no docutils errors beyond the pre-existing Sphinx-only roles.


Related Issues and Pull-Requests

  • Follow-up to v7.14.0 #240 (v7.14.0), which introduced the condition/condition2 inputs whose second set the CleanupArtifacts.yml fix repairs.
  • Reported from VHDL/pyVHDLModel run 30632085881, where 52 jobs were green and the run was red solely because of the Prepare failure — blocking a clean signal on VHDL/pyVHDLModel#167 (v0.38.0).

Note

GitHub's Default to PR title for merge commit messages setting needs no support here: the version is derived from the Pull Request title through the API, never from the commit message, so a trailing (#123) never reaches release_tag_pattern. Deriving the Pull Request from the commit message was tried and rejected — that message is free text, and a subject ending in (#123) could name an issue or an unrelated Pull Request and tag a wrong release.

Note

is_prerelease_commit (PrepareJob.yml:287) is still assigned but never initialised and never written to GITHUB_OUTPUT. Left untouched — it looks like an unfinished feature rather than a defect.

@codacy-production

codacy-production Bot commented Jul 31, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

🟢 Coverage 100.00% diff coverage · +0.00% coverage variation

Metric Results
Coverage variation +0.00% coverage variation
Diff coverage 100.00% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (9864288) 45 41 91.11%
Head commit (179b07f) 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 (#242) 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.

@Paebbels Paebbels changed the title v7.14.1 v7.15.0 Jul 31, 2026
@Paebbels Paebbels added the Enhancement New feature or request label Jul 31, 2026
@Paebbels Paebbels changed the title v7.15.0 v7.14.1 Aug 1, 2026
@Paebbels Paebbels removed the Enhancement New feature or request label Aug 1, 2026
PrepareJob.yml
--------------

'FindPullRequest' looked up a merged Pull Request whose base is the release branch, but it ran for
every merge commit. A merge commit pushed to the development branch comes from a Pull Request based
on the development branch, so the search returned an empty list and the step - and with it the whole
'Prepare' job - failed.

Guard the step with 'is_release_commit', which 'Classify' already computes as 'is_merge_commit'
restricted to the main and version branches, and which 'TriggerTaggedRelease' keys off too. This
answers the TODO that sat right above the step.

The search itself is now exact. It lists every Pull Request *containing* the second parent, which
can be more than one - an older release Pull Request built from an ancestor also matches - and the
code then took the first entry in an unordered list. The second parent (father) of a merge commit is
the head commit of the merged branch, so the candidates are reduced to those whose 'headRefOid'
equals it. If a Pull Request was closed and recreated from the same branch, both share a head commit
and the most recently merged one is used, with a warning naming both. No match is now an error that
lists the candidates instead of falling through to the literal 'null': 'gh pr list --json' returns
an empty JSON array, not an empty string, so the previous guard never triggered.

Everything stays derived from the commit graph. Deriving the Pull Request from the merge commit's
message instead was tried and rejected: that message is free text - editable in the merge dialog,
arbitrary for a local merge - so a subject ending in '(#123)' could select an issue number or an
unrelated Pull Request and tag a wrong release. The v0.38.0 release merge of pyVHDLModel shows both
sides of it: its subject is plain 'v0.38.0' with no number to parse, while its second parent
'61bd8eb' equals the 'headRefOid' of Pull Request #133 exactly.

CleanupArtifacts.yml
--------------------

The second delete step guarded itself with 'steps.compute2', but passed the names computed by
'steps.compute'. So it re-deleted the first set - already deleted by the first step, and masked by
'continue-on-error' - while the artifacts named by 'artifact-json-ids2' survived.

Present since the workflow was introduced, but only visible now that 'CompletePipeline' relies on
the second set to delete the package artifact on non-release runs.

Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
@Paebbels
Paebbels merged commit f6f6430 into main Aug 1, 2026
158 of 162 checks passed
@Paebbels Paebbels mentioned this pull request Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants