Repository navigation
Add npm staged publishing workflow - #341
Conversation
✅ Deploy Preview for yarn-v6 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Stage commands ignore workspace registry
- Modified registry_auth to accept package ident and use get_registry_for_ident, ensuring stage commands respect publishConfig.registry, scoped settings, and packageRules like publish does.
Or push these changes by commenting:
@cursor push 0bb4d46687
Preview (0bb4d46687)
diff --git a/packages/zpm/src/commands/npm/stage/approve.rs b/packages/zpm/src/commands/npm/stage/approve.rs
--- a/packages/zpm/src/commands/npm/stage/approve.rs
+++ b/packages/zpm/src/commands/npm/stage/approve.rs
@@ -36,8 +36,11 @@
= StreamReport::new(StreamReportConfig::from_config(&project.config));
with_report_result(report, async {
+ let active_workspace
+ = project.active_workspace()?;
+
let (registry, authorization)
- = registry_auth(&project).await?;
+ = registry_auth(&project, active_workspace.manifest.name.as_ref()).await?;
let pretty_stage_id
= DataType::Code.colorize(&self.stage_id.0);
diff --git a/packages/zpm/src/commands/npm/stage/list.rs b/packages/zpm/src/commands/npm/stage/list.rs
--- a/packages/zpm/src/commands/npm/stage/list.rs
+++ b/packages/zpm/src/commands/npm/stage/list.rs
@@ -51,8 +51,11 @@
let project
= Project::new(None).await?;
+ let active_workspace
+ = project.active_workspace()?;
+
let (registry, authorization)
- = registry_auth(&project).await?;
+ = registry_auth(&project, active_workspace.manifest.name.as_ref()).await?;
let mut items = Vec::new();
let mut page = 0;
diff --git a/packages/zpm/src/commands/npm/stage/mod.rs b/packages/zpm/src/commands/npm/stage/mod.rs
--- a/packages/zpm/src/commands/npm/stage/mod.rs
+++ b/packages/zpm/src/commands/npm/stage/mod.rs
@@ -5,6 +5,7 @@
http_npm::{self, AuthorizationMode, GetAuthorizationOptions},
project::Project,
};
+use zpm_primitives::Ident;
pub mod approve;
pub mod list;
@@ -32,16 +33,16 @@
}
}
-async fn registry_auth(project: &Project) -> Result<(String, Option<String>), Error> {
+async fn registry_auth(project: &Project, ident: Option<&Ident>) -> Result<(String, Option<String>), Error> {
let registry
- = http_npm::get_registry(&project.config, None, true)?.to_string();
+ = http_npm::get_registry_for_ident(&project.config, ident, true)?.to_string();
let authorization
= http_npm::get_authorization(&GetAuthorizationOptions {
configuration: &project.config,
http_client: &project.http_client,
registry: ®istry,
- ident: None,
+ ident: ident,
auth_mode: AuthorizationMode::AlwaysAuthenticate,
allow_oidc: false,
}).await?;
diff --git a/packages/zpm/src/commands/npm/stage/reject.rs b/packages/zpm/src/commands/npm/stage/reject.rs
--- a/packages/zpm/src/commands/npm/stage/reject.rs
+++ b/packages/zpm/src/commands/npm/stage/reject.rs
@@ -36,8 +36,11 @@
= StreamReport::new(StreamReportConfig::from_config(&project.config));
with_report_result(report, async {
+ let active_workspace
+ = project.active_workspace()?;
+
let (registry, authorization)
- = registry_auth(&project).await?;
+ = registry_auth(&project, active_workspace.manifest.name.as_ref()).await?;
let pretty_stage_id
= DataType::Code.colorize(&self.stage_id.0);You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit e60a960. Configure here.
⏱️ Benchmark Resultsgatsby install-full-cold
📊 Raw benchmark data (gatsby install-full-cold)Base times: 4.890s, 4.609s, 4.282s, 4.354s, 4.273s, 4.297s, 4.428s, 4.274s, 4.358s, 4.442s, 4.273s, 4.263s, 4.367s, 4.368s, 4.359s, 4.392s, 4.320s, 4.285s, 4.253s, 4.302s, 4.289s, 4.266s, 4.259s, 4.301s, 4.272s, 4.313s, 4.409s, 4.247s, 4.347s, 4.421s Head times: 4.375s, 4.342s, 4.340s, 4.364s, 4.290s, 4.320s, 4.406s, 4.410s, 4.226s, 4.304s, 4.340s, 4.312s, 4.339s, 4.237s, 4.325s, 4.266s, 4.371s, 4.274s, 4.300s, 4.372s, 4.329s, 4.368s, 4.410s, 4.391s, 4.346s, 4.300s, 4.312s, 4.423s, 4.407s, 4.356s gatsby install-cache-only
📊 Raw benchmark data (gatsby install-cache-only)Base times: 1.309s, 1.295s, 1.298s, 1.301s, 1.264s, 1.290s, 1.276s, 1.286s, 1.288s, 1.284s, 1.282s, 1.313s, 1.297s, 1.306s, 1.302s, 1.289s, 1.299s, 1.304s, 1.481s, 1.296s, 1.295s, 1.293s, 1.268s, 1.304s, 1.305s, 1.309s, 1.309s, 1.316s, 1.334s, 1.327s Head times: 1.320s, 1.325s, 1.308s, 1.305s, 1.315s, 1.317s, 1.314s, 1.334s, 1.316s, 1.317s, 1.310s, 1.348s, 1.307s, 1.312s, 1.327s, 1.338s, 1.289s, 1.320s, 1.310s, 1.310s, 1.319s, 1.282s, 1.311s, 1.314s, 1.306s, 1.292s, 1.307s, 1.310s, 1.300s, 1.293s gatsby install-cache-and-lock (warm, with lockfile)
📊 Raw benchmark data (gatsby install-cache-and-lock (warm, with lockfile))Base times: 0.371s, 0.365s, 0.361s, 0.363s, 0.356s, 0.368s, 0.358s, 0.360s, 0.362s, 0.361s, 0.355s, 0.362s, 0.366s, 0.366s, 0.361s, 0.364s, 0.360s, 0.359s, 0.359s, 0.359s, 0.359s, 0.367s, 0.365s, 0.360s, 0.367s, 0.363s, 0.366s, 0.367s, 0.361s, 0.363s Head times: 0.358s, 0.360s, 0.356s, 0.359s, 0.363s, 0.356s, 0.360s, 0.354s, 0.357s, 0.354s, 0.360s, 0.359s, 0.355s, 0.355s, 0.362s, 0.355s, 0.357s, 0.360s, 0.361s, 0.357s, 0.356s, 0.359s, 0.353s, 0.363s, 0.357s, 0.364s, 0.359s, 0.363s, 0.367s, 0.403s |


yarn npm publish --stagednow uploads packages for later approval and returns their stage IDs, with support for dry runs and JSON output.Ports Berry’s staging workflow, including
npm stage list,approve, andreject, paginated listing, UUID validation, and OTP handling for approval and rejection. All four commands share the active workspace’s publish registry selection, honoringpublishConfig.registry, scoped settings, matching package rules, and the corresponding credentials.yarn npm stage approve <id> <id> …approves multiple versions on that registry in order. All IDs are validated before sending requests; a failed approval stops the command, while earlier successful approvals remain published.Includes Berry’s acceptance tests and additional coverage for scoped packages, registry and credential precedence in nested workspaces, pagination, multiple approvals, invalid input, and partial failures.
Validation:
cargo build -rand the publish/staging integration suites: 42 passed; one CI-only provenance test skipped.yarn tsc --buildpassed.Note
Medium Risk
Touches npm publish and authenticated registry HTTP paths; mistaken approve publishes real versions, though behavior mirrors existing publish auth and OTP flows.
Overview
Adds npm staged publishing:
yarn npm publish --stageduploads to the registry staging API (POST /-/stage/package…) instead of publishing immediately, returns a stage ID (and updated JSON fieldsstaged,published,stageId), and does not send OTP during staging.Introduces
yarn npm stage list,approve, andrejectto list paginated staged versions, approve one or more UUIDs in order (with OTP on approve/reject), or delete a staged upload. Stage commands shareget_publish_registryand workspace publish-registry/auth resolution with staged publish.http_npmgainsget_publish_registry,delete(with OTP retry), and publish uses the shared registry helper.InvalidNpmStageIdvalidates UUID-shaped stage IDs before any network calls on approve.Acceptance harness mocks stage registry routes; a large
stage.test.tssuite covers dry-run/JSON, OTP behavior, multi-approve partial failure, registry precedence, and pagination.Reviewed by Cursor Bugbot for commit f1a5a30. Bugbot is set up for automated code reviews on this repo. Configure here.