package-registry-manager 0.21.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/flows.mjs +3 -1
- package/src/setup.mjs +39 -6
package/package.json
CHANGED
package/src/flows.mjs
CHANGED
|
@@ -226,13 +226,15 @@ export function npmFlow(packageInfo, context) {
|
|
|
226
226
|
const name = packageInfo.name;
|
|
227
227
|
const registry = registryEndpoint("npm");
|
|
228
228
|
const trustNpm = context.trustNpm ?? DEFAULT_TRUST_NPM;
|
|
229
|
+
// npm trust list needs a 2FA approval; with --json npm holds the approval
|
|
230
|
+
// URL back until it exits, so the human output is read instead (#24).
|
|
229
231
|
const trustList = command("npx", [
|
|
230
232
|
"-y",
|
|
231
233
|
trustNpm,
|
|
232
234
|
"trust",
|
|
233
235
|
"list",
|
|
234
236
|
name,
|
|
235
|
-
"--
|
|
237
|
+
"--browser=false",
|
|
236
238
|
]);
|
|
237
239
|
const steps = [
|
|
238
240
|
step(
|
package/src/setup.mjs
CHANGED
|
@@ -43,6 +43,10 @@ const INTERACTIVE_CHECKS = new Set(["check-trust", "verify-trusted-publisher"]);
|
|
|
43
43
|
const PAGES_CHANGES = new Set(["enable-pages", "use-pages-workflow"]);
|
|
44
44
|
/** Checks whose failure is an answer, so their output is not echoed. */
|
|
45
45
|
const QUIET_CHECKS = new Set(["check-sign-in", "check-pages"]);
|
|
46
|
+
/** A trusted publisher in `npm trust list` output, human-readable or JSON. */
|
|
47
|
+
const LISTED_PUBLISHER = /^\s*(?:id|type|file):\s*\S|"(?:id|type|file)"\s*:/m;
|
|
48
|
+
/** What `npm trust github` prints once the registry stored the publisher. */
|
|
49
|
+
const TRUST_CREATED = /Trust configuration created successfully/i;
|
|
46
50
|
/** npm's answer when a workflow publishes without an attached trusted publisher. */
|
|
47
51
|
const PUBLISH_REJECTED = /\bE404\b|404 Not Found|invalid-publisher/i;
|
|
48
52
|
/** Where `--browser` opens URLs that need no automation. */
|
|
@@ -107,7 +111,6 @@ class SetupSession {
|
|
|
107
111
|
this.conditions.add("trust-missing");
|
|
108
112
|
}
|
|
109
113
|
this.values = {};
|
|
110
|
-
this.deferred = [];
|
|
111
114
|
this.automation = null;
|
|
112
115
|
this.temporary = null;
|
|
113
116
|
this.shim = null;
|
|
@@ -116,7 +119,7 @@ class SetupSession {
|
|
|
116
119
|
async run() {
|
|
117
120
|
for (const step of this.plan.steps) {
|
|
118
121
|
if (CLEANUP_CONDITIONS.has(step.when)) {
|
|
119
|
-
|
|
122
|
+
// cleanup() runs these, even after a failed step.
|
|
120
123
|
} else if (!step.when || this.conditions.has(step.when)) {
|
|
121
124
|
this.log(`==> ${step.title}`);
|
|
122
125
|
await this.runStep(step);
|
|
@@ -126,8 +129,12 @@ class SetupSession {
|
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Runs every cleanup step of the plan whose condition holds, including
|
|
134
|
+
* those after a step that failed (#24).
|
|
135
|
+
*/
|
|
129
136
|
async cleanup() {
|
|
130
|
-
for (const step of this.
|
|
137
|
+
for (const step of cleanupSteps(this.plan)) {
|
|
131
138
|
if (step.id === "sign-out" && this.keepsSession(step)) {
|
|
132
139
|
console.log(
|
|
133
140
|
"Keeping the npm session (--keep-session): its token stays in npm's user configuration until you run npm logout, and the next run reuses it while npm whoami succeeds.",
|
|
@@ -226,8 +233,7 @@ class SetupSession {
|
|
|
226
233
|
return;
|
|
227
234
|
case "check-trust":
|
|
228
235
|
case "verify-trusted-publisher": {
|
|
229
|
-
const trusted =
|
|
230
|
-
result.code === 0 && /"(?:id|type|file)"\s*:/.test(output);
|
|
236
|
+
const trusted = result.code === 0 && listsTrustedPublisher(output);
|
|
231
237
|
toggle(this.conditions, "trust-missing", !trusted);
|
|
232
238
|
if (step.id === "verify-trusted-publisher" && !trusted) {
|
|
233
239
|
throw new Error(
|
|
@@ -483,7 +489,9 @@ class SetupSession {
|
|
|
483
489
|
`${step.command.program} exited with status ${result.code}`,
|
|
484
490
|
);
|
|
485
491
|
}
|
|
486
|
-
if (step.id === "
|
|
492
|
+
if (step.id === "attach-trusted-publisher") {
|
|
493
|
+
this.confirmTrustCreated(result.stdout);
|
|
494
|
+
} else if (step.id === "sign-in") {
|
|
487
495
|
this.conditions.add("tool-signed-in");
|
|
488
496
|
} else if (step.id === "prepare-worktree") {
|
|
489
497
|
this.conditions.add("worktree-created");
|
|
@@ -497,6 +505,17 @@ class SetupSession {
|
|
|
497
505
|
}
|
|
498
506
|
}
|
|
499
507
|
|
|
508
|
+
/**
|
|
509
|
+
* npm prints the stored configuration once `npm trust github` succeeds, so
|
|
510
|
+
* that answer verifies it without a second 2FA-gated `npm trust list`.
|
|
511
|
+
*/
|
|
512
|
+
confirmTrustCreated(output) {
|
|
513
|
+
if (TRUST_CREATED.test(stripAnsi(output))) {
|
|
514
|
+
console.log(" npm stored the trusted publisher.");
|
|
515
|
+
this.conditions.delete("trust-missing");
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
500
519
|
recordPack(output) {
|
|
501
520
|
const packed = packedEntry(output);
|
|
502
521
|
for (const file of packed.files ?? []) {
|
|
@@ -730,6 +749,20 @@ class SetupSession {
|
|
|
730
749
|
}
|
|
731
750
|
}
|
|
732
751
|
|
|
752
|
+
/** The plan's cleanup steps, which run after every other step, even a failed one. */
|
|
753
|
+
export function cleanupSteps(plan) {
|
|
754
|
+
return plan.steps.filter((step) => CLEANUP_CONDITIONS.has(step.when));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/** Whether `npm trust list` output names a trusted publisher. */
|
|
758
|
+
export function listsTrustedPublisher(output) {
|
|
759
|
+
return LISTED_PUBLISHER.test(stripAnsi(output));
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function stripAnsi(text) {
|
|
763
|
+
return String(text ?? "").replaceAll(ANSI, "");
|
|
764
|
+
}
|
|
765
|
+
|
|
733
766
|
/**
|
|
734
767
|
* npm's warnings from `npm pack`, such as fields it auto-corrected or removed
|
|
735
768
|
* from the packed package.json, without npm's advice to run its fixer, which
|