@newlandnpt/pep-cli 0.9.0-rc.2 → 0.9.0-rc.4
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 +14 -0
- package/dist/pep.cjs +123 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,20 @@ pep setup --skip-skills # only sign in and configure Maven
|
|
|
77
77
|
pep setup group/sub -p # a different group, into THIS project
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
### Seeing what a run would do
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
pep setup --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Prints the plan and **installs nothing**: which repositories the group holds right now, which of them
|
|
87
|
+
are new, where each would land, and which entries on your list are no longer in the group — together
|
|
88
|
+
with the skill names those occupy, which is what makes one block another. Useful before a first run,
|
|
89
|
+
and when an install fails for a reason you would rather understand than guess at.
|
|
90
|
+
|
|
91
|
+
It never opens a browser: with no valid sign-in it reports `"login": "required"` and exits non-zero.
|
|
92
|
+
It does read the group, so it may refresh your token, exactly as `pep auth status` does.
|
|
93
|
+
|
|
80
94
|
`--issuer`, `--client-id` and `--resource` work here exactly as on `pep auth login`, for pointing a
|
|
81
95
|
run at another deployment:
|
|
82
96
|
|
package/dist/pep.cjs
CHANGED
|
@@ -1176,6 +1176,13 @@ never deleted. \`pep skills remove <repo>\` drops one for good.
|
|
|
1176
1176
|
The group is baked into this build and is not remembered between runs: pass one
|
|
1177
1177
|
to install from a different group, just for this run.
|
|
1178
1178
|
|
|
1179
|
+
--json prints what this run would do \u2014 which repositories the group holds, which
|
|
1180
|
+
of them are new, where each would land, and which entries on your list are no
|
|
1181
|
+
longer in the group (with the skill names they occupy, which is what makes one
|
|
1182
|
+
block another). It installs nothing, writes nothing and never opens a browser.
|
|
1183
|
+
It does need a valid sign-in to read the group, so it may refresh your token,
|
|
1184
|
+
exactly as \`pep auth status\` does.
|
|
1185
|
+
|
|
1179
1186
|
--issuer, --client-id and --resource are passed to step 1, exactly as on
|
|
1180
1187
|
\`pep auth login\`, and are not remembered either. If you are already signed in to
|
|
1181
1188
|
a different deployment, setup signs in again rather than silently using the one
|
|
@@ -1188,13 +1195,15 @@ replaces it \u2014 run \`pep auth login\` to go back.`,
|
|
|
1188
1195
|
"--dir <path> Install skills into this directory instead",
|
|
1189
1196
|
`--issuer <url> PEP server for this run (default: ${DEFAULT_ISSUER})`,
|
|
1190
1197
|
"--client-id <id> Registered OAuth client for this run",
|
|
1198
|
+
"--json Print what this run would do, install nothing",
|
|
1191
1199
|
"--resource <uri> Token audience; repeat for multiple resources"
|
|
1192
1200
|
],
|
|
1193
1201
|
examples: [
|
|
1194
1202
|
"pep setup",
|
|
1195
1203
|
"pep setup --skip-nexus",
|
|
1196
1204
|
`pep setup ${DEFAULT_SKILLS_GROUP} -p`,
|
|
1197
|
-
"pep setup --issuer https://pep-dev.example --client-id <that deployment's id>"
|
|
1205
|
+
"pep setup --issuer https://pep-dev.example --client-id <that deployment's id>",
|
|
1206
|
+
"pep setup --json"
|
|
1198
1207
|
]
|
|
1199
1208
|
}
|
|
1200
1209
|
};
|
|
@@ -1834,6 +1843,17 @@ async function installGroup(dependencies, remote) {
|
|
|
1834
1843
|
if (repos.length === 0) {
|
|
1835
1844
|
dependencies.onProgress(` ${group} lists no repositories \u2014 nothing to install.`);
|
|
1836
1845
|
}
|
|
1846
|
+
const drifted = driftedFromGroup(
|
|
1847
|
+
dependencies.installed.map((one) => one.source),
|
|
1848
|
+
repos,
|
|
1849
|
+
group
|
|
1850
|
+
);
|
|
1851
|
+
if (drifted.length > 0) {
|
|
1852
|
+
dependencies.onProgress(` \u26A0 On your list but no longer in ${group}:`);
|
|
1853
|
+
for (const source of drifted) dependencies.onProgress(` ${source}`);
|
|
1854
|
+
dependencies.onProgress(" Nothing was deleted. If one of them blocks an install below,");
|
|
1855
|
+
dependencies.onProgress(" `pep skills remove <repo>` drops it for good.");
|
|
1856
|
+
}
|
|
1837
1857
|
const installed = [];
|
|
1838
1858
|
const failed = [];
|
|
1839
1859
|
for (const [index, source] of repos.entries()) {
|
|
@@ -1846,13 +1866,7 @@ async function installGroup(dependencies, remote) {
|
|
|
1846
1866
|
dependencies.onProgress(` \u2717 ${source}: ${message}`);
|
|
1847
1867
|
}
|
|
1848
1868
|
}
|
|
1849
|
-
return {
|
|
1850
|
-
status: "installed",
|
|
1851
|
-
group,
|
|
1852
|
-
installed,
|
|
1853
|
-
failed,
|
|
1854
|
-
drifted: driftedFromGroup(dependencies.installedSources, repos, group)
|
|
1855
|
-
};
|
|
1869
|
+
return { status: "installed", group, installed, failed, drifted };
|
|
1856
1870
|
}
|
|
1857
1871
|
async function runSetup(dependencies) {
|
|
1858
1872
|
dependencies.onProgress("\u2460 Signing in to PEP\u2026");
|
|
@@ -1922,9 +1936,74 @@ function setupFailureSummary(report) {
|
|
|
1922
1936
|
if (failed.length === 0) return void 0;
|
|
1923
1937
|
return `Setup finished with problems: ${failed.join(", ")} did not complete.`;
|
|
1924
1938
|
}
|
|
1939
|
+
async function planSetup(dependencies) {
|
|
1940
|
+
const group = dependencies.group;
|
|
1941
|
+
const nexus = dependencies.skipNexus ? "skipped" : "planned";
|
|
1942
|
+
const bySource = new Map(dependencies.installed.map((one) => [one.source, one]));
|
|
1943
|
+
let current;
|
|
1944
|
+
try {
|
|
1945
|
+
current = await dependencies.auth.status();
|
|
1946
|
+
} catch {
|
|
1947
|
+
}
|
|
1948
|
+
if (current === void 0) {
|
|
1949
|
+
return {
|
|
1950
|
+
group,
|
|
1951
|
+
issuer: null,
|
|
1952
|
+
account: null,
|
|
1953
|
+
login: "required",
|
|
1954
|
+
skills: { status: "unavailable", reason: "not signed in \u2014 run `pep auth login` first" },
|
|
1955
|
+
nexus
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
const issuer = current.authorization.issuer;
|
|
1959
|
+
if (dependencies.requestedIssuer !== void 0 && !sameIssuer(issuer, dependencies.requestedIssuer)) {
|
|
1960
|
+
return {
|
|
1961
|
+
group,
|
|
1962
|
+
issuer,
|
|
1963
|
+
account: accountOf(current.user),
|
|
1964
|
+
login: "different-deployment",
|
|
1965
|
+
skills: {
|
|
1966
|
+
status: "unavailable",
|
|
1967
|
+
reason: `signed in to ${issuer}, but --issuer names ${dependencies.requestedIssuer}; a real run would sign in again first`
|
|
1968
|
+
},
|
|
1969
|
+
nexus
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
const plan = {
|
|
1973
|
+
group,
|
|
1974
|
+
issuer,
|
|
1975
|
+
account: accountOf(current.user),
|
|
1976
|
+
login: "reuse",
|
|
1977
|
+
nexus
|
|
1978
|
+
};
|
|
1979
|
+
if (dependencies.skipSkills) {
|
|
1980
|
+
return { ...plan, skills: { status: "skipped", reason: "--skip-skills" } };
|
|
1981
|
+
}
|
|
1982
|
+
let repos;
|
|
1983
|
+
try {
|
|
1984
|
+
repos = await dependencies.listGroupRepos({
|
|
1985
|
+
issuer,
|
|
1986
|
+
accessToken: current.authorization.accessToken
|
|
1987
|
+
});
|
|
1988
|
+
} catch (error) {
|
|
1989
|
+
return { ...plan, skills: { status: "unavailable", reason: messageOf(error) } };
|
|
1990
|
+
}
|
|
1991
|
+
const repositories = repos.map((path) => {
|
|
1992
|
+
const known = bySource.get(path);
|
|
1993
|
+
return known === void 0 ? { path, state: "new", directory: dependencies.directoryFor(path) } : {
|
|
1994
|
+
path,
|
|
1995
|
+
state: "installed",
|
|
1996
|
+
directory: known.directory,
|
|
1997
|
+
...known.commit !== void 0 ? { commit: known.commit } : {}
|
|
1998
|
+
};
|
|
1999
|
+
});
|
|
2000
|
+
const gone = new Set(driftedFromGroup(dependencies.installed.map((one) => one.source), repos, group));
|
|
2001
|
+
const drifted = dependencies.installed.filter((one) => gone.has(one.source));
|
|
2002
|
+
return { ...plan, skills: { status: "planned", repositories, drifted } };
|
|
2003
|
+
}
|
|
1925
2004
|
|
|
1926
2005
|
// src/cli.ts
|
|
1927
|
-
var VERSION = false ? "0.0.0-dev" : "0.9.0-rc.
|
|
2006
|
+
var VERSION = false ? "0.0.0-dev" : "0.9.0-rc.4";
|
|
1928
2007
|
var SKILLS_ADD_DEPRECATION = "\u26A0 `pep skills add` will be removed in a future release.";
|
|
1929
2008
|
function reportUpdate(result) {
|
|
1930
2009
|
const conflicts = () => {
|
|
@@ -2108,12 +2187,14 @@ function reportSetup(report) {
|
|
|
2108
2187
|
console.error(` \u2717 ${source}: ${message}`);
|
|
2109
2188
|
}
|
|
2110
2189
|
if (skills.drifted.length > 0) {
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
console.error(" `pep skills
|
|
2190
|
+
const n = skills.drifted.length;
|
|
2191
|
+
console.error(
|
|
2192
|
+
`
|
|
2193
|
+
\u26A0 ${n} ${n === 1 ? "repository" : "repositories"} on your list ${n === 1 ? "is" : "are"} no longer in ${skills.group} (listed above).`
|
|
2194
|
+
);
|
|
2195
|
+
console.error(" Nothing was deleted. `pep skills update` will report 404 for each of them");
|
|
2196
|
+
console.error(" (which reads exactly like a typo, but is not). `pep skills remove <repo>`");
|
|
2197
|
+
console.error(" drops one for good.");
|
|
2117
2198
|
}
|
|
2118
2199
|
}
|
|
2119
2200
|
if (report.nexus.status === "skipped") {
|
|
@@ -2141,11 +2222,37 @@ async function main() {
|
|
|
2141
2222
|
const skipNexus = flag(args, "--skip-nexus");
|
|
2142
2223
|
const skipSkills = flag(args, "--skip-skills");
|
|
2143
2224
|
const loginOptions = takeLoginOptions(args);
|
|
2225
|
+
const wantsJson = flag(args, "--json");
|
|
2144
2226
|
const { requested, chosenTarget } = parseSkillsArgs("setup", args);
|
|
2145
2227
|
const skillsGroup = requested ?? DEFAULT_SKILLS_GROUP;
|
|
2146
2228
|
const { configStore: configStore2, auth: auth2 } = createCliServices();
|
|
2147
2229
|
const stateStore = fileSkillsStateStore();
|
|
2148
2230
|
const state = await stateStore.read();
|
|
2231
|
+
const installed = Object.entries(state?.packages ?? {}).map(([source, pkg]) => ({
|
|
2232
|
+
source,
|
|
2233
|
+
directory: pkg.directory,
|
|
2234
|
+
skills: Object.keys(pkg.skills).sort(),
|
|
2235
|
+
...pkg.commit !== void 0 ? { commit: pkg.commit } : {}
|
|
2236
|
+
}));
|
|
2237
|
+
if (wantsJson) {
|
|
2238
|
+
const plan = await planSetup({
|
|
2239
|
+
auth: auth2,
|
|
2240
|
+
...issuerOf(loginOptions) !== void 0 ? { requestedIssuer: issuerOf(loginOptions) } : {},
|
|
2241
|
+
group: skillsGroup,
|
|
2242
|
+
skipSkills,
|
|
2243
|
+
skipNexus,
|
|
2244
|
+
listGroupRepos: (remote) => listGroupRepos({ ...remote, group: skillsGroup }),
|
|
2245
|
+
installed,
|
|
2246
|
+
// ⚠ 与真跑**同一条推导**(`targetForSource`):干跑报的落点要是和真跑落的地方
|
|
2247
|
+
// 不一样,那它比没有还坏。
|
|
2248
|
+
directoryFor: (source) => targetForSource(chosenTarget, state?.packages[source]).directory
|
|
2249
|
+
});
|
|
2250
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
2251
|
+
if (plan.skills.status === "unavailable") {
|
|
2252
|
+
throw new Error(`--json could not plan the skills step: ${plan.skills.reason}`);
|
|
2253
|
+
}
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
2149
2256
|
const report = await runSetup({
|
|
2150
2257
|
auth: auth2,
|
|
2151
2258
|
// ⚠ 传 `loginOptions` 而不是 `args`:后者到这里**恒为空**(`parseSkillsArgs` 要么抛、
|
|
@@ -2171,7 +2278,7 @@ async function main() {
|
|
|
2171
2278
|
},
|
|
2172
2279
|
// 漂移比对的另一半。取**这一趟开始前**的账 —— 装完再读的话,本轮刚装上的那些也在
|
|
2173
2280
|
// 里头,而它们当然都还在群里,比出来一样,只是白读一遍。
|
|
2174
|
-
|
|
2281
|
+
installed,
|
|
2175
2282
|
skipNexus,
|
|
2176
2283
|
setupNexus: (remote) => setupNexusCredential(remote),
|
|
2177
2284
|
onProgress: (line) => console.error(line),
|