From 449871b3c7e45d9cffd79e9650c1ac6958ef2760 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 19:41:48 +0000 Subject: [PATCH] ship-app: the commit step pushes HEAD to the branch the run was given and only there; the CI dispatch and the behind-check follow that branch 6 October 2026: from a release worktree, `git push origin master` pushed the shared checkout's unchanged local master ref and the tool reported "pushed to origin/master" from its own arithmetic; the Windows build was then looked for on master. Master merges are main's. Co-Authored-By: Claude Fable 5.1 --- tools/ship-app.mjs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/ship-app.mjs b/tools/ship-app.mjs index cf7ffe509..3a061d8d9 100644 --- a/tools/ship-app.mjs +++ b/tools/ship-app.mjs @@ -279,8 +279,9 @@ async function preflight() { const otherDirty = dirty.filter(p => !versionPaths.has(p)); if (otherDirty.length) problems.push(`this tree has ${otherDirty.length} modified tracked file(s) besides the version files; commit or stash them first:\n ${otherDirty.slice(0, 8).join('\n ')}`); if (!DRY) { const f = git(['fetch', 'origin', 'master', '--quiet']); if (f.code !== 0) problems.push(`git fetch origin failed: ${f.out}`); } - const behind = git(['rev-list', '--count', 'HEAD..origin/master']).out; - if (behind !== '0') problems.push(`this tree is ${behind} commit(s) behind origin/master; git pull first`); + const upstream = `origin/${flags.branch || 'master'}`; + const behind = git(['rev-parse', '--verify', '-q', upstream]).code === 0 ? git(['rev-list', '--count', `HEAD..${upstream}`]).out : '0'; + if (behind !== '0') problems.push(`this tree is ${behind} commit(s) behind ${upstream}; git pull first`); const headSha = git(['rev-parse', 'HEAD']).out; // the fork if (!existsSync(join(NODE_DIR, '.git'))) problems.push(`--node ${NODE_DIR} is not a git worktree`); @@ -382,21 +383,25 @@ async function commit() { const changed = git(['status', '--porcelain', '--', ...paths]).out.split('\n').filter(Boolean); const msg = `Igneum Miner ${VERSION}: ${NOTES}`; if (changed.length) { - if (DRY) return done('commit', 'would', `git commit ${paths.length} files as "${msg}" and push origin master`); + if (DRY) return done('commit', 'would', `git commit ${paths.length} files as "${msg}" and push origin ${flags.branch || 'master'}`); const a = git(['add', '--', ...paths]); if (a.code !== 0) throw new Error(`git add failed: ${a.out}`); const cm = git(['commit', '-m', msg]); if (cm.code !== 0) throw new Error(`git commit failed: ${cm.out}`); - } else if (DRY) { done('commit', 'would', 'nothing to commit (the files are committed); push if origin/master lacks HEAD'); return; } + } else if (DRY) { done('commit', 'would', `nothing to commit (the files are committed); push if origin/${flags.branch || 'master'} lacks HEAD`); return; } const sha = git(['rev-parse', 'HEAD']).out; const subject = git(['log', '-1', '--format=%s']).out; if (!subject.startsWith(`Igneum Miner ${VERSION}`)) say(` note: HEAD is "${subject.slice(0, 80)}", not the version commit; the Windows build runs on whatever master is`); - const pushed = git(['merge-base', '--is-ancestor', sha, 'origin/master']).code === 0; + // the push goes to the branch this run was given and only there (6 October 2026: `git push origin master` from a release + // worktree pushed the shared checkout's local master ref, said "pushed to origin/master" from its own arithmetic, and the + // Windows build was then looked for on master; master merges are main's) + const target = flags.branch || 'master'; + const pushed = git(['rev-parse', '--verify', '-q', `origin/${target}`]).code === 0 && git(['merge-base', '--is-ancestor', sha, `origin/${target}`]).code === 0; if (!pushed) { const sw = runSync('gh', ['auth', 'switch', '--user', GH_USER]); if (sw.code !== 0) throw new Error(`gh auth switch failed: ${sw.out}`); - const p = await run('git', ['push', 'origin', 'master']); - if (p.code !== 0) throw new Error(`git push origin master exited ${p.code}; retry: gh auth switch --user ${GH_USER} && git push origin master`); + const p = await run('git', ['push', 'origin', `HEAD:refs/heads/${target}`]); + if (p.code !== 0) throw new Error(`git push origin HEAD:${target} exited ${p.code}; retry: gh auth switch --user ${GH_USER} && git push origin HEAD:refs/heads/${target}`); } state.sha = sha; saveState(); - done('commit', pushed && !changed.length ? 'already' : 'ok', `${sha.slice(0, 12)} ${pushed ? 'was on' : 'pushed to'} origin/master`); + done('commit', pushed && !changed.length ? 'already' : 'ok', `${sha.slice(0, 12)} ${pushed ? 'was on' : 'pushed to'} origin/${target}`); } async function ci() { @@ -412,8 +417,8 @@ async function ci() { say(` no ${WORKFLOW} run for ${sha.slice(0, 12)} yet; waiting up to 3 minutes for the push to start one`); for (let i = 0; i < 12 && !pick; i++) { await sleep(15000); runs = await list(); pick = runs[0]; } if (!pick) { - say(` dispatching: gh workflow run ${WORKFLOW} --ref master`); - const d = await gh(['workflow', 'run', WORKFLOW, '--repo', REPO, '--ref', 'master']); if (d.code !== 0) throw new Error(`gh workflow run failed: ${d.out.trim()}`); + say(` dispatching: gh workflow run ${WORKFLOW} --ref ${flags.branch || 'master'}`); + const d = await gh(['workflow', 'run', WORKFLOW, '--repo', REPO, '--ref', flags.branch || 'master']); if (d.code !== 0) throw new Error(`gh workflow run failed: ${d.out.trim()}`); for (let i = 0; i < 12 && !pick; i++) { await sleep(15000); runs = await list(); pick = runs[0]; } if (!pick) throw new Error(`no run appeared for ${sha.slice(0, 12)}; check https://github.com/${REPO}/actions and retry: ${retryCmd('ci')}`); }