Skip to content

Submit the right version to winget, and pin the rest of the actions - #264

Merged
fstubner merged 1 commit into
mainfrom
fix/release-workflow-winget-and-pinning
Aug 28, 2026
Merged

fstubner merged 1 commit into
mainfrom
fix/release-workflow-winget-and-pinning

Conversation

@fstubner

Copy link
Copy Markdown
Owner

Closes the one item my assessment left in Unconfirmed, which turned out
to be two bugs rather than none, plus the pinning inconsistency.

Both winget jobs would submit the wrong PackageVersion

publish.yml passed version: ${{ env.TAG }} — that is v0.3.1. The action
strips the v only when the input is empty. From its own action.yml:

If ('' -eq '${{ inputs.version }}') {
  Write-Output "version=$($ReleaseInfo.tag_name -replace '^v')" >> $env:GITHUB_OUTPUT
} Else {
  Write-Output "version=${{ inputs.version }}" >> $env:GITHUB_OUTPUT
}

Passing it explicitly opted out of the stripping. The catalog entry would
have been v0.3.1 next to the existing 0.3.0; winget sorts versions
naturally, so those do not compare as an upgrade, and it would have been
permanent in a moderated public catalog. A Resolve PackageVersion step now
derives ${TAG#v} and both jobs use it.

…and would fail on the documented re-run path

release-tag was left at its default, github.event.release.tag_name || github.ref_name. On release: published that is right. On
workflow_dispatch the first is null and the second is the branch the run
was dispatched from, so the action asks the API for a release tagged main
and fails — on precisely the recovery path this workflow's own header
advertises:

workflow_dispatch with a tag input (re-run a specific job after fixing a
transient failure)

Both jobs now pass release-tag: ${{ env.TAG }}.

Neither bug had a chance to show up yet: the winget GUI job has never run to
completion (it needs microsoft/winget-pkgs to accept an initial submission
first, PR #368471), and the committed 0.3.0 manifests under
packaging/winget/ were hand-written, not produced by this job.

Action pinning

publish.yml, release.yml and release-drafter.yml were fully SHA-pinned.
ci.yml, site.yml, site-preview.yml, pages.yml, audit.yml and
gui-render.yml pinned their third-party actions and left the first-party
actions/* on mutable tags — so the policy read as deliberate in three files
and absent in six. Now uniform: 28 uses pinned across six workflows, each
with the resolved version in a trailing comment so Dependabot can still see
what it is.

Verification

All nine workflow files parse as YAML. actionlint is not installed here, so
this is a parse check plus review, not a lint. The winget jobs themselves
cannot be exercised outside a real publish — the version derivation is the
part I could check, and ${TAG#v} gives 0.3.1 for both v0.3.1 and a
bare 0.3.1.

Both winget jobs would have submitted `PackageVersion: v0.3.1` beside the
existing `0.3.0` in the catalog. The action strips the tag's `v` only when
the `version` input is empty -- from its own action.yml:

    If ('' -eq '${{ inputs.version }}') { tag_name -replace '^v' }
    Else                                { inputs.version }

Passing `${{ env.TAG }}` opted out of that. Winget sorts versions naturally,
so `v0.3.1` and `0.3.0` do not compare as an upgrade. A step now derives the
stripped form and both jobs use it.

The same two jobs also left `release-tag` at its default, which is
`github.event.release.tag_name || github.ref_name`. On a `workflow_dispatch`
the first is null and the second is the branch the run was dispatched from,
so the action would ask the API for a release tagged `main` -- on exactly the
re-run path this workflow's header offers for recovering a failed publish.
Both jobs now name the tag.

Neither was reachable before now: the winget GUI job has never run to
completion (it needs microsoft/winget-pkgs to accept an initial submission
first), and the committed 0.3.0 manifests were written by hand.

Separately, the first-party `actions/*` steps are now SHA-pinned like every
third-party action already was. publish.yml, release.yml and
release-drafter.yml were fully pinned; ci.yml, site.yml, site-preview.yml,
pages.yml, audit.yml and gui-render.yml were not, which left the policy
looking deliberate in three files and absent in six. 28 uses across six
workflows, each carrying the resolved version in a trailing comment.

All nine workflow files parse.
@github-actions

Copy link
Copy Markdown
Contributor

Site preview: https://pr-264.netscli-site-preview.pages.dev

Built from 5edbf25 with NETSCLI_PREVIEW=1 — noindex, and analytics disabled so it does not report into netscli.com's numbers.

Production is unaffected: netscli.com is served from GitHub Pages via pages.yml, which is manual-only.

@fstubner
fstubner merged commit eecff91 into main Aug 28, 2026
16 checks passed
@fstubner
fstubner deleted the fix/release-workflow-winget-and-pinning branch August 28, 2026 16:08
fstubner added a commit that referenced this pull request Aug 28, 2026
…274)

#264 stopped the winget jobs passing the tag through as `PackageVersion`.
This adds the assertion that should have caught it, and records the state of
the catalog it left behind.

The `Resolve PackageVersion` step now requires MAJOR.MINOR.PATCH and fails
the job otherwise. `${TAG#v}` was already producing the right answer, so this
is not belt-and-braces on the arithmetic -- it is the check that was missing
entirely. winget-pkgs accepted `v0.2.2` through `v0.2.6` without complaint,
so nothing downstream will catch a recurrence, and a merged manifest is
permanent. The regex accepts every tag this repo has used plus a prerelease
form, and rejects `v0.2.6`, `main` and `latest` -- the last two being what a
`workflow_dispatch` re-run would have produced before #264.

I also got the impact wrong when I first reported this, and the correction
matters because it changes what needs doing. I said the mixed version set
would affect `winget upgrade` ordering. It does not: winget normalises a
leading `v` when comparing. Checked against the client rather than reasoned
about --

    > winget list --id fstubner.netscli
    netscli  fstubner.netscli  0.2.0  v0.2.6  winget

-- it offers v0.2.6 as an upgrade from an installed 0.2.0, and
`--version 0.2.6` resolves `v0.2.6` while `--version 0.2.9` finds nothing, so
the filter is real and the prefix is normalised.

What is actually wrong is display: the catalog shows a version this project
never issued, and the two packages sit inconsistently beside each other in
`winget search` -- `v0.2.6` against the GUI's `0.2.6`. The next
correctly-versioned release fixes that, since search and install use the
latest version.

docs/PUBLISHING.md records the catalog contents, the measurements above, and
the one remaining decision: removing the five directories from
microsoft/winget-pkgs is a PR against a third-party repo that breaks anyone
pinned to those versions with `--version`, so it is deliberately not
automated and doing nothing is a defensible answer. It also says not to reach
for the action's `max-versions-to-keep` to prune them, because that deletes
public catalog entries as a side effect of an ordinary release.

All nine workflow files parse.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant