Skip to content

Commit d9d4ea0

Browse files
anandgupta42claude
andcommitted
fix: add retry logic for npm publish transient 404s
npm returns transient 404 errors when multiple scoped packages under the same org are published concurrently. Add retry logic (3 attempts with exponential backoff) to `publish.ts` instead of switching to sequential publishes, which would be too slow for 13 platform binaries. Also update CHANGELOG.md for v0.5.11 to document the fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f87e9ac commit d9d4ea0

File tree

3 files changed

+22
-24
lines changed

3 files changed

+22
-24
lines changed

.github/meta/commit.txt

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,8 @@
1-
fix: add release smoke tests to prevent broken binary publishes
1+
release: v0.5.11
22

3-
Closes #462
4-
5-
v0.5.10 shipped with `@altimateai/altimate-core` missing from standalone
6-
distributions, crashing on startup. Add three-layer defense:
7-
8-
- **CI smoke test**: run the compiled `linux-x64` binary after build and
9-
before npm publish — catches runtime crashes that compile fine
10-
- **Build-time verification**: validate all `requiredExternals` are in
11-
`package.json` `dependencies` (not just `devDependencies`) so they
12-
ship in the npm wrapper package
13-
- **Local pre-release script**: `bun run pre-release` builds + smoke-tests
14-
the binary before tagging — mandatory step in RELEASING.md
15-
16-
Also adds `smoke-test-binary.test.ts` with 3 tests: version check,
17-
standalone graceful-failure, and `--help` output.
18-
19-
Reviewed by 5 AI models (Claude, GPT 5.2 Codex, Gemini 3.1 Pro,
20-
Kimi K2.5, MiniMax M2.5). Key fixes from review:
21-
- Include workspace `node_modules` in `NODE_PATH` (Gemini)
22-
- Restrict dep check to `dependencies` only (GPT, Gemini, Kimi)
23-
- Hard-fail pre-publish gate when binary not found (Claude, GPT)
24-
- Tighten exit code assertion for signal safety (MiniMax)
3+
Update README changelog to reflect releases v0.5.1 through v0.5.11.
4+
Previous README only listed up to v0.5.0, missing 10 versions of features
5+
including `check` CLI, skill management, session tracing, Codespaces support,
6+
impact analysis, Snowflake Cortex, MCP auto-discovery, and more.
257

268
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- **README changelog gap** — updated README to reflect releases v0.5.1 through v0.5.11; previous README only listed up to v0.5.0
13+
- **npm publish transient 404s** — added retry logic (3 attempts with backoff) to `publish.ts` for concurrent scoped package publishes that hit npm registry race conditions
1314

1415
## [0.5.10] - 2026-03-24
1516

packages/opencode/script/publish.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,22 @@ const tasks = Object.entries(binaries).map(async ([name]) => {
112112
await $`chmod -R 755 .`.cwd(`./dist/${name}`)
113113
}
114114
await $`bun pm pack`.cwd(`./dist/${name}`)
115-
await $`npm publish *.tgz --access public --tag ${Script.channel}`.cwd(`./dist/${name}`)
115+
// Retry up to 3 times — npm returns transient 404s when multiple scoped
116+
// packages under the same org are published concurrently.
117+
for (let attempt = 1; attempt <= 3; attempt++) {
118+
try {
119+
await $`npm publish *.tgz --access public --tag ${Script.channel}`.cwd(`./dist/${name}`)
120+
break
121+
} catch (e: any) {
122+
const isRetryable = String(e?.stderr ?? e).includes("E404") || String(e?.stderr ?? e).includes("ETIMEDOUT")
123+
if (isRetryable && attempt < 3) {
124+
console.warn(`npm publish ${name} attempt ${attempt} failed (retryable), retrying in ${attempt * 5}s...`)
125+
await Bun.sleep(attempt * 5000)
126+
} else {
127+
throw e
128+
}
129+
}
130+
}
116131
})
117132
await Promise.all(tasks)
118133
await $`cd ./dist/${pkg.name} && bun pm pack && npm publish *.tgz --access public --tag ${Script.channel}`

0 commit comments

Comments
 (0)