Skip to content

fix(release): unblock dcode-ai publish when a platform is rate limited#46

Merged
CreatorGhost merged 2 commits into
devfrom
npm-publish-resilience
Jul 15, 2026
Merged

fix(release): unblock dcode-ai publish when a platform is rate limited#46
CreatorGhost merged 2 commits into
devfrom
npm-publish-resilience

Conversation

@CreatorGhost

@CreatorGhost CreatorGhost commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Issue

npm i -g dcode-ai 404s: the dcode-ai wrapper was never published. Every publish-npm run fails on the 184MB dcode-ai-windows-x64 binary with npm E429 (publish rate limit — as user undefined is npm's rate-limit wording, not an auth failure; 5 of 7 platform packages publish fine with the token).

Root cause: publish.ts is sequential + fail-fast, and the user-facing wrapper publishes last. One throttled platform throws and aborts the run before the wrapper is ever published, so nothing is installable.

Registry state confirms it: dcode-ai-{darwin-arm64,darwin-x64,linux-x64,windows-arm64}@1.0.1 are live; only dcode-ai-windows-x64 and the dcode-ai wrapper are missing.

Type of change

  • Bug fix (release tooling)

What changed

  • publish() no longer throws; it returns success/failure and collects failures.
  • Every platform that can publish does; the tiny wrapper always publishes regardless of a throttled platform.
  • All platforms are listed as optionalDependencies at the target version. npm resolves only the current platform's optional dep at install time, so listing a still-rate-limited platform is harmless and self-heals when a re-run publishes it.
  • Sturdier E429 handling: honors Retry-After when present, 8 attempts, capped exponential backoff.
  • Real (non-E429) errors are logged in full; the run exits non-zero when any package is left behind so leftovers are visible. Re-running fills only the missing ones via the existing already-published skip.

Verification

  • bun typecheck — 30/30 pass.
  • Prettier clean.
  • Idempotency and the optional-dep fallback match the existing esbuild-style wrapper design documented at the top of publish.ts.

Notes

  • No unit-test seam exists for a live-npm publish script; validation is the publish workflow itself. A dispatch (dry-run then real) is the next step after merge.
  • Intentional tradeoff: if a platform stays rate limited, the run still exits non-zero to flag it — but dcode-ai is installable in the meantime, and a re-run backfills the platform.

Summary by CodeRabbit

  • New Features

    • Improved package publishing resilience with automatic retries and rate-limit handling.
    • Added support for safely re-running publishing to process only packages that previously failed.
    • Added clearer reporting for incomplete and successful publishing runs.
  • Bug Fixes

    • Publishing failures are now handled without unexpected exceptions.
    • Dry runs complete with appropriate status reporting, while failed releases return a failure status.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@CreatorGhost, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 299d0395-2e75-43f0-8742-faf543c2a1e1

📥 Commits

Reviewing files that changed from the base of the PR and between 1ec1d0a and 06145e7.

📒 Files selected for processing (1)
  • packages/opencode/script/publish.ts
📝 Walkthrough

Walkthrough

The npm publish helper now retries rate-limited publishes without throwing, while the script tracks failed platform and wrapper packages, preserves dependency versions, and reports whether a re-run is required.

Changes

npm publish resilience

Layer / File(s) Summary
Retrying npm publishes
packages/opencode/script/publish.ts
The publish helper uses bounded E429 retries, honors retry-after output, applies fallback delays, and returns a boolean result.
Partial failure tracking and exit handling
packages/opencode/script/publish.ts
Platform and wrapper failures are collected, optional dependency versions are recorded before publishing, and final output reflects dry-run, failure, or complete success states.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • CreatorGhost/TheCode#44: Both changes update the npm publish helper with bounded retry and E429 backoff behavior.

Suggested reviewers: thdxr

Sequence Diagram(s)

sequenceDiagram
  participant PublishScript
  participant npm
  participant npmRegistry
  PublishScript->>npm: Publish platform or wrapper package
  npm->>npmRegistry: Submit package
  npmRegistry-->>npm: Return success or E429
  npm-->>PublishScript: Return result and retry-after output
  PublishScript->>npm: Retry failed rate-limited package
  PublishScript-->>PublishScript: Record failures and determine exit status
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: making dcode-ai publish resilient to rate limiting.
Description check ✅ Passed Mostly matches the template with clear issue, changes, and verification sections; only the checklist and screenshots sections are omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch npm-publish-resilience

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/opencode/script/publish.ts`:
- Around line 156-163: Update the dry-run handling around the failures check so
non-empty failures are reported and cause a non-zero exit before printing “dry
run complete.” Preserve the existing success message only when failures is
empty, and ensure both dry-run and publish modes use the failure path
consistently.
- Line 89: Update the fallback delay calculation near parseRetryAfter so it uses
capped exponential backoff instead of attempt * 90_000. Preserve the parsed
Retry-After value when available and cap only the calculated fallback at 300,000
milliseconds.
- Around line 71-74: Update publish so the alreadyPublished(name) registry
preflight handles rejected promises by logging the failure and returning false,
rather than allowing the rejection to escape. Preserve the existing
skip-and-true behavior when the package is already published, and ensure the
failure collector can continue to the wrapper path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71b6fc88-7b12-4dfa-9fee-af337a8eed3a

📥 Commits

Reviewing files that changed from the base of the PR and between 2244207 and 1ec1d0a.

📒 Files selected for processing (1)
  • packages/opencode/script/publish.ts

Comment thread packages/opencode/script/publish.ts
Comment thread packages/opencode/script/publish.ts Outdated
Comment thread packages/opencode/script/publish.ts Outdated
Address review: publish dcode-ai wrapper before per-platform binaries so a
rate limit/timeout never leaves it unpublished; stop alreadyPublished from
throwing; treat 'cannot publish over' as success; capped exponential backoff
with a Retry-After:0 guard; broaden 429 detection; fail dry-run on any failure.
@CreatorGhost

Copy link
Copy Markdown
Owner Author

Addressed all review findings (CodeRabbit + our independent reviewer) in 06145e7:

  • Publish the dcode-ai wrapper first so a per-platform rate limit or CI timeout can never leave it unpublished (the original un-installable failure).
  • alreadyPublished no longer throws on a network blip (degrades to attempt-publish); cannot publish over is treated as success.
  • Capped exponential backoff with a Retry-After: 0 guard; broadened 429 detection.
  • Dry-run now fails loudly on any package failure instead of exiting 0.

The red unit (linux) check is the pre-existing models.dev/recorded-fixture baseline; this PR only touches script/publish.ts (a release script not imported by tests).

@CreatorGhost CreatorGhost merged commit 48f6cd2 into dev Jul 15, 2026
5 of 7 checks passed
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