Skip to content

Add npm release publishing flow#3

Merged
Nek-12 merged 4 commits into
mainfrom
add-npm-release-publishing
Jun 11, 2026
Merged

Add npm release publishing flow#3
Nek-12 merged 4 commits into
mainfrom
add-npm-release-publishing

Conversation

@Nek-12

@Nek-12 Nek-12 commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

  • add local npm release entrypoints for cross-compiled publishing and dry-runs
  • publish a small firefox-cli package plus platform-specific optional native packages
  • add release.yml trusted-publishing flow that publishes npm packages before undrafting the GitHub release
  • clean Bun root .bun-build artifacts safely after compile leaks

Verification

  • bun run format:check
  • bun run typecheck
  • bun test scripts/test/npm-publish.test.ts scripts/test/package-check.test.ts
  • bun run npm:publish:dry-run
  • bun run check

Summary by CodeRabbit

  • New Features

    • Application now available on npm with automatic cross-platform binary support.
  • Documentation

    • Added npm publishing documentation describing installation options and platform support.
  • Tests

    • Added automated tests validating the release workflow and package integrity.
  • Chores

    • Enhanced CI/CD infrastructure with npm publishing and GitHub release automation.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Nek-12, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 14 minutes and 8 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61ddf432-a317-4526-a957-58768eb5d999

📥 Commits

Reviewing files that changed from the base of the PR and between d586cec and 9a96c22.

📒 Files selected for processing (5)
  • .github/workflows/release.yml
  • docs/development.md
  • packages/cli/src/npm-platform-binary-runtime.js
  • scripts/platform-targets.ts
  • scripts/test/npm-publish.test.ts
📝 Walkthrough

Walkthrough

This PR adds a complete npm publishing pipeline for distributing the Firefox CLI as an npm package with per-platform native binary sub-packages. It introduces platform target infrastructure, multi-platform binary building, npm package assembly with validation, publishing orchestration, and GitHub Actions CI/CD automation.

Changes

NPM Publishing Pipeline

Layer / File(s) Summary
Platform Target Infrastructure and Binary Building
scripts/platform-targets.ts, scripts/build-binary.ts, scripts/build-all-binaries.ts, packages/cli/src/npm-platform-binary-runtime.js
Adds SupportedBinaryTarget interface mapping OS/architecture pairs to Bun targets. Refactors build-binary.ts to accept target parameters, output to dist/bin/<platformKey>/<binaryName>, and export buildBinary(target) and cleanupRootBunBuildArtifacts(root) with executable signature validation. Creates build-all-binaries.ts to sequentially build all supported targets. Adds runtime module to resolve platform-specific native packages and verify binary existence via filesystem access.
NPM Package Assembly and Validation
scripts/npm-package.ts, scripts/npm-package-check.ts, scripts/package.ts, scripts/package-check.ts, scripts/test/package-check-test-utils.ts
Adds npm-package.ts to assemble dist/npm layout with firefox-cli package and per-platform @firefox-cli/native-<platform>-<arch> packages, each with platform-specific package.json metadata and binaries. Normalizes bin paths to bin/firefox-cli.js across package.ts and package-check.ts. Creates npm-package-check.ts to validate CLI/native package manifests, optionalDependencies, binary existence, and performs temporary install verification by running the CLI with --version.
NPM Publishing Orchestration
scripts/npm-publish.ts, scripts/test/npm-publish.test.ts, package.json
Introduces NpmPublishPlan interface and resolveNpmPublishPlan() to parse CLI args (--dry-run, --provenance, --require-signed-xpi, --otp, --registry) and compute npm publish arguments and package roots. Adds publishNpmPackage() that orchestrates prerequisite checks, optionally builds binaries and signed extensions, then invokes npm publish in each package directory. Adds package.json scripts for build:binary:all, npm:package, npm:package:verify, and npm:publish:* variants. Includes test suite for publish plan generation.
CI/CD Release Automation
.github/workflows/release.yml, docs/development.md, scripts/check-firefox-architecture-policy.test.mjs
Updates github-release job to use narrowed artifact glob matching only packaged archives and signed .xpi/provenance. Adds npm-publish job to download signed artifacts, set up Bun/Node/npm, and run bun run npm:publish:ci. Adds publish-github-release job to finalize release as non-draft/non-prerelease. Documents npm publishing commands, optionalDependencies platform selection, and GitHub Actions trusted publishing configuration. Includes test validating workflow artifact patterns.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add npm release publishing flow' accurately captures the main objective of the PR, which is to implement npm package publishing capabilities integrated into the release workflow.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-npm-release-publishing

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 and usage tips.

@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: 2

🧹 Nitpick comments (3)
scripts/platform-targets.ts (1)

19-24: 💤 Low value

Consider caching getPlatformKey(target) to avoid duplicate calls.

Line 21 and line 23 both call getPlatformKey(target). While this is not a performance concern in practice (the array is small and computed once at module load), storing the result would be more efficient.

♻️ Optional refactor
 export const supportedBinaryTargets: readonly SupportedBinaryTarget[] = targetInputs.map((target) => {
+  const platformKey = getPlatformKey(target);
   return {
     ...target,
-    platformKey: getPlatformKey(target),
+    platformKey,
     binaryName: getBinaryName(target),
-    npmPackageName: `@firefox-cli/native-${getPlatformKey(target)}`,
+    npmPackageName: `@firefox-cli/native-${platformKey}`,
   };
 });
🤖 Prompt for 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.

In `@scripts/platform-targets.ts` around lines 19 - 24, The map callback for
supportedBinaryTargets calls getPlatformKey(target) twice; cache the result in a
local variable (e.g., const platformKey = getPlatformKey(target)) inside the map
function and reuse that variable for both platformKey and the npmPackageName
construction, leaving getBinaryName(target) as-is; update the object properties
in the supportedBinaryTargets initializer to reference the cached platformKey.
.github/workflows/release.yml (1)

189-216: ⚖️ Poor tradeoff

Review static analysis warnings for the npm-publish job.

Several static analysis warnings were flagged:

  1. Unpinned action references (lines 201, 202, 205, 212): Actions use version tags rather than commit SHAs. While this is common practice and acceptable for many projects, consider pinning to SHAs if your security policy requires it.

  2. Cache poisoning (lines 202, 205): setup-bun and setup-node enable caching by default. This is generally safe for official actions from trusted organizations (oven-sh, actions), but be aware of the risk if your threat model requires cache isolation.

  3. Credential persistence (line 201): The artipacked warning is likely a false positive since actions/checkout@v6 does not persist credentials to downloaded artifacts.

These are policy decisions rather than code defects. If your project's security requirements mandate commit-SHA pinning and cache isolation, address these warnings; otherwise they can be accepted as known trade-offs.

🤖 Prompt for 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.

In @.github/workflows/release.yml around lines 189 - 216, The pipeline job
npm-publish triggers static-analysis flags about unpinned action versions,
caching, and credential persistence; decide and implement your security policy:
if you require immutability, pin each action in the npm-publish steps
(actions/checkout, oven-sh/setup-bun, actions/setup-node,
actions/download-artifact) to specific commit SHAs instead of tags, and disable
cache options for setup-bun and setup-node (or add explicit cache-isolation
settings) to avoid cache poisoning; if the warnings are acceptable, add a short
justification comment in the workflow near the job explaining why tag versions
and caching are permitted and note that actions/checkout does not persist
credentials to downloaded artifacts.
scripts/npm-publish.ts (1)

80-94: 💤 Low value

Consider extracting readOption to a shared utility.

This function is duplicated between build-binary.ts and npm-publish.ts. While the duplication is not a serious issue, extracting it to a shared module would improve maintainability.

🤖 Prompt for 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.

In `@scripts/npm-publish.ts` around lines 80 - 94, The readOption function is
duplicated; extract it to a shared utility and import it from both scripts.
Create a new module (e.g., export function readOption(args: readonly string[],
name: string): string | undefined) and move the implementation there, then
replace the local readOption definitions in npm-publish.ts and build-binary.ts
with imports of the shared readOption to avoid duplication and keep behavior
identical.
🤖 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 @.github/workflows/release.yml:
- Around line 218-229: The gh release edit step in the publish-github-release
job uses an unquoted template expansion ${ { github.ref_name } } in a shell
command; to fix, ensure the value is properly quoted or passed via an
environment variable: update the gh release edit invocation in the
publish-github-release step to quote the template expansion (e.g., use "${{
github.ref_name }}") or set GITHUB_REF_NAME=${{ github.ref_name }} in env and
reference that variable, keeping GH_TOKEN handling the same so shell injection
is prevented.

In `@packages/cli/src/npm-platform-binary-runtime.js`:
- Around line 22-30: resolvePackagedBinary currently ignores the packageRoot
argument which can cause resolution to happen from the wrong module tree; change
resolution to use a createRequire rooted at path.join(packageRoot,
'package.json') (import createRequire from 'module') and call
rootRequire.resolve instead of the global require.resolve when locating
`${packageName}/package.json`; keep getPlatformKey usage and set packageJsonPath
from rootRequire.resolve, falling back to global require only if packageRoot is
not provided.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 189-216: The pipeline job npm-publish triggers static-analysis
flags about unpinned action versions, caching, and credential persistence;
decide and implement your security policy: if you require immutability, pin each
action in the npm-publish steps (actions/checkout, oven-sh/setup-bun,
actions/setup-node, actions/download-artifact) to specific commit SHAs instead
of tags, and disable cache options for setup-bun and setup-node (or add explicit
cache-isolation settings) to avoid cache poisoning; if the warnings are
acceptable, add a short justification comment in the workflow near the job
explaining why tag versions and caching are permitted and note that
actions/checkout does not persist credentials to downloaded artifacts.

In `@scripts/npm-publish.ts`:
- Around line 80-94: The readOption function is duplicated; extract it to a
shared utility and import it from both scripts. Create a new module (e.g.,
export function readOption(args: readonly string[], name: string): string |
undefined) and move the implementation there, then replace the local readOption
definitions in npm-publish.ts and build-binary.ts with imports of the shared
readOption to avoid duplication and keep behavior identical.

In `@scripts/platform-targets.ts`:
- Around line 19-24: The map callback for supportedBinaryTargets calls
getPlatformKey(target) twice; cache the result in a local variable (e.g., const
platformKey = getPlatformKey(target)) inside the map function and reuse that
variable for both platformKey and the npmPackageName construction, leaving
getBinaryName(target) as-is; update the object properties in the
supportedBinaryTargets initializer to reference the cached platformKey.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f31c8dd6-d768-435a-af8c-edf65321acec

📥 Commits

Reviewing files that changed from the base of the PR and between 36d0d1d and d586cec.

📒 Files selected for processing (15)
  • .github/workflows/release.yml
  • docs/development.md
  • package.json
  • packages/cli/src/npm-platform-binary-runtime.js
  • scripts/build-all-binaries.ts
  • scripts/build-binary.ts
  • scripts/check-firefox-architecture-policy.test.mjs
  • scripts/npm-package-check.ts
  • scripts/npm-package.ts
  • scripts/npm-publish.ts
  • scripts/package-check.ts
  • scripts/package.ts
  • scripts/platform-targets.ts
  • scripts/test/npm-publish.test.ts
  • scripts/test/package-check-test-utils.ts

Comment thread .github/workflows/release.yml
Comment thread packages/cli/src/npm-platform-binary-runtime.js
@Nek-12 Nek-12 merged commit fd4ca9c into main Jun 11, 2026
11 checks passed
@Nek-12 Nek-12 deleted the add-npm-release-publishing branch June 11, 2026 17:34
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