package-registry-manager 0.22.9 → 0.22.11
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/README.md +20 -2
- package/package.json +4 -4
- package/src/auth-urls.mjs +19 -3
- package/src/browser.mjs +14 -9
- package/src/cli-main.mjs +540 -0
- package/src/cli.mjs +15 -534
- package/src/default-scope.mjs +53 -0
- package/src/discovery.mjs +9 -1
- package/src/flows.mjs +1 -1
- package/src/node-version.mjs +14 -0
- package/src/npm-policy.mjs +4 -4
- package/src/npm-similarity.mjs +153 -0
- package/src/organization-scan.mjs +131 -56
- package/src/organization-setup.mjs +51 -13
- package/src/prerequisites.mjs +11 -9
- package/src/publisher-form.mjs +102 -0
- package/src/python.mjs +38 -2
- package/src/registry-state.mjs +75 -44
- package/src/setup-batch.mjs +8 -0
- package/src/setup.mjs +41 -42
- package/src/sign-in-import.mjs +137 -22
package/README.md
CHANGED
|
@@ -33,7 +33,25 @@ package-registry-manager setup --org link-foundation --all --execute --browser-i
|
|
|
33
33
|
Scans read matched manifests/workflows through gh-manager. Account setup shares
|
|
34
34
|
one browser, groups npm approvals, and uses CI evidence to preserve healthy tokens
|
|
35
35
|
or verify replacements before revocation. `--secret-name '{REGISTRY}_TOKEN_{REPO}'`
|
|
36
|
-
selects custom credential names.
|
|
37
|
-
|
|
36
|
+
selects custom credential names.
|
|
37
|
+
|
|
38
|
+
Account scans print progress to stderr (`[37/169] owner/repository`) and stream
|
|
39
|
+
text inspection results as each repository finishes. JSON inspection remains one
|
|
40
|
+
report on stdout. Repository, manifest, registry lookup, and release-log failures are
|
|
41
|
+
included in each repository's `error` and structured `errors` fields; valid
|
|
42
|
+
packages and later repositories are retained. The command exits nonzero after
|
|
43
|
+
printing all results, and `setup --org ORG --all` still plans the usable packages.
|
|
44
|
+
Release health checks only the latest default-branch push or manual run of each
|
|
45
|
+
detected publishing workflow; it downloads logs only when that run failed.
|
|
46
|
+
Expired logs retain the failed run's URL and conclusion alongside the error.
|
|
47
|
+
Account `plan` and `setup` JSON reports also include a `plans` array.
|
|
48
|
+
|
|
49
|
+
Without `--repository`, online commands prefer the current repository's
|
|
50
|
+
organization, then a sole organization membership, then the signed-in GitHub
|
|
51
|
+
user. Multiple memberships fall back to the user; select an organization with
|
|
52
|
+
`--org`. If GitHub account discovery is unavailable, the current directory is
|
|
53
|
+
inspected. Explicit `--repository` (including `--repository .`), `--ref`, and
|
|
54
|
+
local `--offline` commands keep local scope. Both CLIs' GitHub dependency needs
|
|
55
|
+
Node.js 22.12 or newer and npm; JavaScript checks the runtime before loading it.
|
|
38
56
|
|
|
39
57
|
See the [bootstrap, wrapper and credential guide](../docs/registry-setup.md) for branch/PR setup, dual npm names, registry policies and integration limits.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "package-registry-manager",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.11",
|
|
4
4
|
"description": "Inspect repositories and guide secure package-registry setup",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"provenance": true
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
|
-
"syntax": "node --check src/cli.mjs && node --check src/direct-execution.mjs && node --check src/index.mjs && node --check src/browser.mjs && node --check src/browser-options.mjs && node --check src/browser-catalogue.mjs && node --check src/automation.mjs && node --check src/webdriver-automation.mjs && node --check src/profile.mjs && node --check src/setup.mjs && node --check src/auth-urls.mjs && node --check src/containers.mjs && node --check src/flows.mjs && node --check src/prerequisites.mjs && node --check src/registry-state.mjs && node --check src/workflows.mjs && node --check src/publishers.mjs && node --check src/skips.mjs && node --check src/tokens.mjs && node --check src/approvals.mjs && node --check src/default-browser.mjs && node --check src/pages.mjs && node --check src/crates-api.mjs && node --check src/sign-in-import.mjs && node --check scripts/publish-to-npm.mjs && node --check scripts/setup-npm.mjs && node --check scripts/sanitize-npm-userconfig.mjs && node --check src/python.mjs && node --check src/setup-batch.mjs && node --check src/workflow-proposal.mjs && node --check src/repository-identity.mjs && node --check src/repository-repair.mjs && node --check src/manifest-proposal.mjs",
|
|
31
|
+
"syntax": "node --check src/cli.mjs && node --check src/cli-main.mjs && node --check src/node-version.mjs && node --check src/default-scope.mjs && node --check src/direct-execution.mjs && node --check src/index.mjs && node --check src/browser.mjs && node --check src/browser-options.mjs && node --check src/browser-catalogue.mjs && node --check src/automation.mjs && node --check src/webdriver-automation.mjs && node --check src/profile.mjs && node --check src/setup.mjs && node --check src/auth-urls.mjs && node --check src/containers.mjs && node --check src/flows.mjs && node --check src/prerequisites.mjs && node --check src/registry-state.mjs && node --check src/workflows.mjs && node --check src/publishers.mjs && node --check src/skips.mjs && node --check src/tokens.mjs && node --check src/approvals.mjs && node --check src/default-browser.mjs && node --check src/pages.mjs && node --check src/crates-api.mjs && node --check src/sign-in-import.mjs && node --check scripts/publish-to-npm.mjs && node --check scripts/setup-npm.mjs && node --check scripts/sanitize-npm-userconfig.mjs && node --check src/python.mjs && node --check src/setup-batch.mjs && node --check src/workflow-proposal.mjs && node --check src/repository-identity.mjs && node --check src/repository-repair.mjs && node --check src/manifest-proposal.mjs",
|
|
32
32
|
"lint": "eslint src test scripts --max-warnings 0",
|
|
33
33
|
"lint:fix": "eslint src test scripts --fix --max-warnings 0",
|
|
34
34
|
"format": "prettier --write .",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@link-foundation/gh-manager": "https://codeload.github.com/link-foundation/gh-manager/tar.gz/29808e088ac8fd8374361920bbebab07a4d63ac6",
|
|
44
|
-
"browser-commander": "^0.
|
|
45
|
-
"command-stream": "^2.0
|
|
44
|
+
"browser-commander": "^0.31.2",
|
|
45
|
+
"command-stream": "^2.4.0",
|
|
46
46
|
"playwright": "^1.63.0",
|
|
47
47
|
"selenium-webdriver": "^4.50.0"
|
|
48
48
|
},
|
package/src/auth-urls.mjs
CHANGED
|
@@ -111,6 +111,7 @@ export function runInteractive(command, options) {
|
|
|
111
111
|
shell: false,
|
|
112
112
|
});
|
|
113
113
|
let legacyLogin = false;
|
|
114
|
+
let openings = Promise.resolve();
|
|
114
115
|
const stop = options.stopOnLegacyLogin
|
|
115
116
|
? () => {
|
|
116
117
|
legacyLogin = true;
|
|
@@ -119,7 +120,11 @@ export function runInteractive(command, options) {
|
|
|
119
120
|
: undefined;
|
|
120
121
|
const scan =
|
|
121
122
|
options.onUrl || stop
|
|
122
|
-
? authUrlScanner(
|
|
123
|
+
? authUrlScanner((url, kind) => {
|
|
124
|
+
openings = openings.then(() => options.onUrl?.(url, kind));
|
|
125
|
+
// Observe rejection until the command closes and propagates it.
|
|
126
|
+
openings.catch(() => {});
|
|
127
|
+
}, stop)
|
|
123
128
|
: null;
|
|
124
129
|
let stdout = "";
|
|
125
130
|
child.stdout.setEncoding("utf8");
|
|
@@ -141,9 +146,20 @@ export function runInteractive(command, options) {
|
|
|
141
146
|
});
|
|
142
147
|
}
|
|
143
148
|
child.on("error", reject);
|
|
144
|
-
child.on("close", (code) => {
|
|
149
|
+
child.on("close", async (code) => {
|
|
145
150
|
scan?.("\n");
|
|
146
|
-
|
|
151
|
+
try {
|
|
152
|
+
await openings;
|
|
153
|
+
resolve({
|
|
154
|
+
code: code ?? 1,
|
|
155
|
+
stdout,
|
|
156
|
+
stderr: errors,
|
|
157
|
+
legacyLogin,
|
|
158
|
+
approvalExpired,
|
|
159
|
+
});
|
|
160
|
+
} catch (error) {
|
|
161
|
+
reject(error);
|
|
162
|
+
}
|
|
147
163
|
});
|
|
148
164
|
});
|
|
149
165
|
}
|
package/src/browser.mjs
CHANGED
|
@@ -74,7 +74,13 @@ export function npmPrefillScript(prefill, submit = false) {
|
|
|
74
74
|
const config = ${JSON.stringify(prefill)};
|
|
75
75
|
const shouldSubmit = ${JSON.stringify(submit)};
|
|
76
76
|
const normalized = value => (value || '').replace(/\\s+/g, ' ').trim().toLowerCase();
|
|
77
|
-
const
|
|
77
|
+
const provider = Array.from(document.querySelectorAll('button, label, [role="radio"]'))
|
|
78
|
+
.find(element => normalized(element.textContent) === 'github');
|
|
79
|
+
if (provider) provider.click();
|
|
80
|
+
const githubForm = document.querySelector('#pending-github-publisher-form, #github-publisher-form');
|
|
81
|
+
const controls = Array.from((githubForm || document).querySelectorAll('input, select, textarea'))
|
|
82
|
+
.filter(control => !control.disabled && control.type !== 'hidden'
|
|
83
|
+
&& (githubForm || control.getClientRects().length > 0));
|
|
78
84
|
const setValue = (control, value) => {
|
|
79
85
|
const prototype = control instanceof HTMLSelectElement
|
|
80
86
|
? HTMLSelectElement.prototype
|
|
@@ -88,7 +94,7 @@ export function npmPrefillScript(prefill, submit = false) {
|
|
|
88
94
|
};
|
|
89
95
|
const textFor = control => {
|
|
90
96
|
const explicit = control.id
|
|
91
|
-
? document.querySelector(\`label[for="\${CSS.escape(control.id)}"]\`)?.textContent
|
|
97
|
+
? (control.closest('form') || document).querySelector(\`label[for="\${CSS.escape(control.id)}"]\`)?.textContent
|
|
92
98
|
: '';
|
|
93
99
|
return normalized([explicit, control.getAttribute('aria-label'), control.name,
|
|
94
100
|
control.placeholder, control.closest('label')?.textContent].filter(Boolean).join(' '));
|
|
@@ -103,19 +109,18 @@ export function npmPrefillScript(prefill, submit = false) {
|
|
|
103
109
|
const filled = [];
|
|
104
110
|
const used = new Set();
|
|
105
111
|
for (const [labels, value] of values) {
|
|
106
|
-
if (!value) continue;
|
|
112
|
+
if (!value && labels[0] !== 'environment') continue;
|
|
107
113
|
const control = controls.find(candidate => !used.has(candidate)
|
|
108
114
|
&& labels.some(label => textFor(candidate).includes(label)));
|
|
109
115
|
if (control) { setValue(control, value); used.add(control); filled.push(labels[0]); }
|
|
110
116
|
}
|
|
111
|
-
const provider = Array.from(document.querySelectorAll('button, label, [role="radio"]'))
|
|
112
|
-
.find(element => normalized(element.textContent).includes('github'));
|
|
113
|
-
if (provider && filled.length === 0) provider.click();
|
|
114
117
|
let submitted = false;
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
const required = ['organization', 'repository', 'workflow', ...(githubForm?.id.startsWith('pending-') ? ['project'] : [])];
|
|
119
|
+
const form = githubForm || controls.find(control => /repository|repo/.test(textFor(control)))?.closest('form');
|
|
120
|
+
if (shouldSubmit && required.every(field => filled.includes(field))) {
|
|
121
|
+
const button = Array.from((form || document).querySelectorAll('button, input[type="submit"]'))
|
|
117
122
|
.find(candidate => /add|save|configure|submit/.test(normalized(candidate.textContent || candidate.value))
|
|
118
|
-
&& !candidate.disabled);
|
|
123
|
+
&& !candidate.disabled && !candidate.classList.contains('button--disabled'));
|
|
119
124
|
if (button) { button.click(); submitted = true; }
|
|
120
125
|
}
|
|
121
126
|
return { filled, providerSelected: Boolean(provider), submitted };
|