From 4c39a2c63ac990aa719a31570040bde384bd9f3e Mon Sep 17 00:00:00 2001 From: Allan Thraen Date: Thu, 1 Oct 2026 13:00:38 +0200 Subject: [PATCH] =?UTF-8?q?docs(release):=20winget=20fails=20differently?= =?UTF-8?q?=20now=20=E2=80=94=20record=20the=20v0.9.0=20evidence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The winget section described one failure shape and two causes, both of which are now fixed. v0.9.0 failed a third way and the old text would have sent the next person after a stale fork that wasn't stale, or a token scope that was already correct. What actually happened (2026-09-30): the workflow's sync step SUCCEEDED, and submit then failed with "Ref cannot be created." — no user named, no mention of permissions, which is a different string from the documented one. The fork was behind upstream by exactly the 5 commits winget-pkgs landed in the 34 seconds between the sync (18:51:46) and the submit error (18:52:23). komac resolves upstream HEAD at submit time and branches from it, so a commit that arrives inside that gap is one the fork does not have yet. A hand merge-upstream (clean fast-forward to 0/0) plus an immediate re-dispatch succeeded with no other change. Recorded: - The new error text, next to the old one, and a table keyed on BOTH the error string and whether the sync step passed — that pair separates all three causes in one glance, which is the thing that was missing. - That the sync step not being continue-on-error is what made this diagnosable: its passing is what ruled out the two historical causes. - The compare-direction gotcha. `compare/master...microsoft:winget-pkgs:master` puts the fork in base position, so `ahead_by` is upstream's lead over the fork. Read the natural way round it reports "5 ahead" for a fork that is 5 behind, and sends you looking for a divergence that does not exist. I misread it once before catching it. - The personal-fork question, re-tested rather than re-asserted: it was 19,108 commits behind and untouched since 2026-08-19, yet v0.7.0 and v0.8.0 both published fine in that window, so komac is not using it. Marked settled. - A note on the post-tag checklist that winget has now needed manual help on three consecutive releases, each for a different reason, while Chocolatey has been reliable throughout. The underlying fix for all of it is unchanged and still not done: have CI create the Release with a PAT instead of GITHUB_TOKEN. That removes the manual dispatch and the sync-to-submit gap together. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01NDsEfog5kVkT5NmX1Ya5be --- CLAUDE.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 78dd2eb..05afdc7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -792,7 +792,9 @@ gh workflow run chocolatey.yml -f tag=vX.Y.Z # 3. watch them — they fail independently of CI and nothing else will tell you ``` -To make it genuinely automatic, CI / Release would have to create the Release with a PAT rather than `GITHUB_TOKEN`. +**Budget for winget needing a second dispatch.** It has required manual intervention on three consecutive releases (v0.6.0, v0.7.0, v0.9.0) — a different cause each time, which is why it keeps getting rediagnosed from scratch. Chocolatey has been reliable. See "winget: the `CreateRef` error names the wrong culprit" for how to tell this release's cause from the last one's; the short version is **read the error text and check whether the sync step passed before touching anything**. + +To make it genuinely automatic, CI / Release would have to create the Release with a PAT rather than `GITHUB_TOKEN`. That is also what would close the sync→submit race, since the mirrors would no longer be dispatched as a separate step minutes later — worth doing before v1.0. **Chocolatey moderation: cleared 08 Sep 2026.** The v0.5.0 submission — the package's first — sat in the human review queue from May, which is why the listing stayed on 0.5.0 through two @@ -850,12 +852,33 @@ When it fails you will see: 1. **The fork is stale.** komac creates its branch in `umage-ai/winget-pkgs`; upstream lands dozens of commits a day, so a fork untouched since the last release is always too far behind for GitHub to accept a new branch. 2. **`WINGET_TOKEN` is missing the `workflow` scope**, so the automatic sync that would have fixed (1) *cannot* run — `merge-upstream` returns HTTP 422 because upstream winget-pkgs contains `.github/workflows/*.yml` and syncing means writing them. The fork stays stale and you land back at (1). +**As of v0.9.0 both of those are fixed, and a third cause has taken over — read the error text before assuming either.** The failure now looks like this instead, with **no** mention of permissions or of a user: + +``` +0: Ref cannot be created. +1: failed to create branch UmageAI.CodeShellManager-- +``` + +That shape is a **race, not staleness**. Measured on the v0.9.0 release (2026-09-30): the workflow's sync step *succeeded* at 18:51:46, the submit failed at 18:52:23, and at the moment of failure the fork was behind upstream by exactly **5 commits** — everything winget-pkgs had landed in those 34 seconds. komac resolves the upstream HEAD at submit time and branches from it, so a commit that arrived inside the gap is one the fork does not have yet and the ref cannot be created. Re-running `merge-upstream` by hand (clean fast-forward to 0/0) and dispatching immediately succeeded with no other change. + +So **diagnose by the error text and the sync step's own conclusion, in that order**: + +| What you see | Cause | Fix | +|---|---|---| +| `…does not have the correct permissions to execute CreateRef`, **sync step failed** | token missing `workflow` | fix the scope | +| same message, **sync step succeeded**, fork far behind | stale fork the sync could not close | `merge-upstream`, re-dispatch | +| `Ref cannot be created.`, **sync step succeeded**, fork behind by a handful | the sync→submit race | `merge-upstream`, re-dispatch **immediately** | + +**Check the direction when you compare forks.** `gh api repos/umage-ai/winget-pkgs/compare/master...microsoft:winget-pkgs:master` takes the fork as *base* and upstream as *head*, so `ahead_by` is how far **upstream is ahead of the fork** and `behind_by` is the fork's own extra commits. Reading it the natural way round turns "5 behind upstream" into "5 ahead of it" and sends you looking for a divergence that isn't there. + +Expect this to recur: the window is as wide as the gap between the sync step and the submit step, against a repository that commits dozens of times a day. Closing it properly means syncing inside the submit step rather than ahead of it — or removing the manual dispatch entirely (see the `GITHUB_TOKEN` note above), which removes the gap with it. + Two traps that cost real time across v0.6.0 and v0.7.0: -- **Sync the fork under the org, `umage-ai/winget-pkgs`** — komac uses the fork owned by the same account as this repo. A maintainer's *personal* fork (`AThraen/winget-pkgs`) may also exist and is a red herring; syncing it changes nothing. +- **Sync the fork under the org, `umage-ai/winget-pkgs`** — komac uses the fork owned by the same account as this repo. A maintainer's *personal* fork (`AThraen/winget-pkgs`) may also exist and is a red herring; syncing it changes nothing. Re-tested at v0.9.0, because the original error names `AThraen` and the personal fork is an obvious suspect: it sat **19,108 commits behind** upstream, untouched since 2026-08-19 — and v0.7.0 and v0.8.0 both published successfully in September while it was already that stale. komac is not using it. Don't re-open this one. - **`public_repo` alone is not enough — the token also needs `workflow`.** This was recorded backwards here through v0.6.0 ("`public_repo` is sufficient"), which is why the same failure was rediagnosed three releases running. It is still true that widening to *full* `repo` is wrong and does not help: that grants CI write access to every private repo the owner can reach. `public_repo` + `workflow`, nothing more. -`winget.yml` syncs the org fork automatically before submitting, and that step is deliberately **not** `continue-on-error` — it used to be, which is exactly how a failing sync stayed invisible and only the misleading `CreateRef` error was ever seen. If the sync fails, fix the token scope; to unblock a release in the meantime, sync by hand and re-dispatch: +`winget.yml` syncs the org fork automatically before submitting, and that step is deliberately **not** `continue-on-error` — it used to be, which is exactly how a failing sync stayed invisible and only the misleading `CreateRef` error was ever seen. That change earned its keep at v0.9.0: the sync step passing is what ruled out both historical causes in one glance. If the sync fails, fix the token scope; to unblock a release in the meantime, sync by hand and re-dispatch: ```bash gh api -X POST repos/umage-ai/winget-pkgs/merge-upstream -f branch=master