From 3308df1c16b0dcb7f7b04d4ecb84ccd9e2bf0eb9 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Thu, 24 Sep 2026 09:53:59 +0000 Subject: [PATCH] Fix targeting and the re-run push, found by the first real submit Publishing chocolatey for real turned up three things the earlier runs could not have shown, because no run had ever reached the submit path. Asking for one channel ran all of them. The Linux job stripped chocolatey out of the list with sed, so `-p chocolatey` left the list empty, no `-p` flags were passed, and submit-packages.mjs falls back to ALL on an empty target list. A dispatch for chocolatey alone therefore also pushed homebrew and scoop. They were idempotent and reported "already current", so nothing was damaged, but the next such dispatch would not be so lucky. That sed was also why distribution/chocolatey/* was the one pair of manifests never refreshed in git: only the Windows job templated them, and the Windows job has no commit step. The Linux job now templates every channel, chocolatey included, and the chocolatey submitter skips itself when choco is not on PATH -- Windows still does the packing and pushing. It probes by running the command rather than which/where, which differ between the Linux runner and the Windows one's git-bash. And --force-with-lease was rejected with "stale info" on the re-run. The release checkout is a shallow clone of a single ref, so refs/remotes/origin/ does not exist and there is nothing for the lease to form against. Fetch the branch first and pass the expected commit explicitly, and it does what it was meant to: overwrite our own earlier attempt, refuse if someone else moved it. Verified: `-p chocolatey` on Linux now templates the manifest and prints that Windows will push it, instead of exploding on a missing binary. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/submit-packages.yml | 10 ++++++++-- scripts/open-distribution-pr.sh | 12 +++++++++++- scripts/submit-packages.mjs | 24 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/submit-packages.yml b/.github/workflows/submit-packages.yml index 6e888a8..b3f710b 100644 --- a/.github/workflows/submit-packages.yml +++ b/.github/workflows/submit-packages.yml @@ -56,6 +56,12 @@ jobs: V_IN: ${{ inputs.version }} run: echo "version=${V_IN#v}" >> "$GITHUB_OUTPUT" + # Chocolatey is NOT stripped here. It used to be, which meant + # distribution/chocolatey/* was templated only on the Windows job, which + # has no commit step — so those two files were the one pair that never got + # refreshed in git. This job templates every channel (and commits them); + # the chocolatey *submit* is what belongs to Windows, and the submitter + # skips itself when choco is not on PATH. - name: Resolve package managers id: pms env: @@ -63,8 +69,8 @@ jobs: run: | PMS="$PMS_IN" [ -z "$PMS" ] && PMS="all" - if [ "$PMS" = "all" ]; then PMS="homebrew,scoop,winget,aur,apt,rpm,gentoo,nix,snap,flatpak,appimage,freebsd"; fi - echo "list=$(echo "$PMS" | sed 's/chocolatey,*//g')" >> "$GITHUB_OUTPUT" + if [ "$PMS" = "all" ]; then PMS="homebrew,scoop,winget,aur,apt,rpm,gentoo,nix,chocolatey,snap,flatpak,appimage,freebsd"; fi + echo "list=$PMS" >> "$GITHUB_OUTPUT" - name: Refresh + submit manifests env: diff --git a/scripts/open-distribution-pr.sh b/scripts/open-distribution-pr.sh index e99f3e5..cda77c0 100755 --- a/scripts/open-distribution-pr.sh +++ b/scripts/open-distribution-pr.sh @@ -24,12 +24,22 @@ git config user.email "41898282+github-actions[bot]@users.noreply.github.com" BRANCH="chore/distribution-${VERSION}" # A re-run of the same release must not fail on an existing branch. +# +# --force-with-lease needs a remote-tracking ref to form its lease against. The +# release checkout is a fresh shallow clone of one ref, so refs/remotes/origin/ +# does not exist and the push is rejected with "stale info" — which is +# exactly how the first chocolatey re-run died. Fetch the branch first so the +# lease has a basis, and it behaves as intended: overwrite our own earlier +# attempt, refuse if someone else moved it. if git ls-remote --exit-code --heads origin "${BRANCH}" >/dev/null 2>&1; then echo "branch ${BRANCH} already exists on origin; force-updating it" + git fetch --depth=1 origin "+refs/heads/${BRANCH}:refs/remotes/origin/${BRANCH}" + EXPECT="$(git rev-parse "refs/remotes/origin/${BRANCH}")" git checkout -B "${BRANCH}" git add distribution git commit -m "chore(distribution): refresh manifests for v${VERSION}" - git push --force-with-lease origin "${BRANCH}" + # The lease takes the expected commit, not a ref path. + git push --force-with-lease="${BRANCH}:${EXPECT}" origin "${BRANCH}" else git checkout -b "${BRANCH}" git add distribution diff --git a/scripts/submit-packages.mjs b/scripts/submit-packages.mjs index 158d61e..ff1071f 100644 --- a/scripts/submit-packages.mjs +++ b/scripts/submit-packages.mjs @@ -255,6 +255,21 @@ function tmp(prefix) { return mkdtempSync(join(tmpdir(), `tron-${prefix}-`)); } +/** + * Is a command available on this runner? + * + * Runs the command itself rather than `which`/`where`, which differ between the + * Linux runner and the Windows one's git-bash. + */ +function hasCommand(cmd) { + try { + execFileSync(cmd, ["--version"], { stdio: "pipe" }); + return true; + } catch { + return false; + } +} + /** * Write one file into a repo we own and push it. * @@ -371,6 +386,15 @@ const SUBMITTERS = { }, chocolatey: () => { + // The Linux job templates this manifest so it gets committed with the rest; + // only the Windows job can actually pack and push it. Without this guard the + // Linux run dies on a missing `choco`. + if (!hasCommand("choco")) { + console.log( + " chocolatey: no choco on this runner, manifest refreshed — the Windows job pushes it", + ); + return; + } const key = process.env.CHOCOLATEY_API_KEY; if (!key) return skip("chocolatey", "CHOCOLATEY_API_KEY"); const dir = join(ROOT, "distribution/chocolatey");