impel-cli 0.20.63-canary.7 → 0.20.64
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 +1 -1
- package/RELEASE_NOTES.md +27 -0
- package/package.json +1 -1
- package/src/cli.js +1 -2
- package/src/cliProfiles.js +9 -6
- package/src/codexSetup.js +14 -5
- package/src/commands/auth.js +6 -22
- package/src/commands/update.js +2 -4
- package/src/config.js +5 -48
- package/src/extension/index.js +2 -2
- package/src/gateway/index.js +1 -0
- package/src/managedApps.js +5 -18
- package/src/managedProfileVersion.js +3 -1
- package/src/posthog.js +2 -2
- package/src/remote/transfer.js +8 -10
- package/src/runtimeBrand.js +7 -66
- package/src/sessionHooks.js +4 -11
- package/src/updates.js +3 -12
- package/src/windowsGit.js +1 -2
- package/scripts/bake-canary-brand.mjs +0 -92
- package/scripts/canary-version.mjs +0 -173
- package/scripts/npm-dist-tags.mjs +0 -134
- package/scripts/pack-canary.mjs +0 -32
- package/scripts/pack-release.mjs +0 -27
- package/scripts/prepare-canary.mjs +0 -28
- package/scripts/release-gate.mjs +0 -133
- package/scripts/release-metadata.mjs +0 -18
- package/scripts/required-checks.mjs +0 -126
- package/scripts/verify-canary-install.mjs +0 -62
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import { execFileSync } from "node:child_process";
|
|
5
|
-
|
|
6
|
-
function main() {
|
|
7
|
-
if (!process.env.GITHUB_OUTPUT) throw new Error("GITHUB_OUTPUT is not set");
|
|
8
|
-
const { version } = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
9
|
-
const sourceCommit = execFileSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
10
|
-
fs.appendFileSync(process.env.GITHUB_OUTPUT, `version=${version}\nsource_commit=${sourceCommit}\n`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
main();
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error(`release-metadata: ${error?.message || error}`);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// The CI check names a publishable commit must carry (canary release cycle, U4).
|
|
3
|
-
//
|
|
4
|
-
// Both release workflows consume this list through checked-in gate scripts.
|
|
5
|
-
// A renamed CI job that is not renamed here fails the suite, not a release.
|
|
6
|
-
// Every push to `dev` and `main` runs these via `ci.yml`, so they must exist on
|
|
7
|
-
// a publishable SHA; names must match the job names exactly.
|
|
8
|
-
//
|
|
9
|
-
// Usage:
|
|
10
|
-
// node scripts/required-checks.mjs <check-runs.ndjson>
|
|
11
|
-
// Evaluate the Checks API output (one `{name, status, conclusion}` JSON
|
|
12
|
-
// object per line). Prints the markdown summary on stdout and exits 0
|
|
13
|
-
// when every required check is green, 2 while any is still queued,
|
|
14
|
-
// running, or not yet reported (the caller polls), and 1 when a required
|
|
15
|
-
// check, or a present Windows vendor check, has a non-success conclusion.
|
|
16
|
-
// node scripts/required-checks.mjs --list
|
|
17
|
-
// Print the required names, one per line.
|
|
18
|
-
|
|
19
|
-
import fs from "node:fs";
|
|
20
|
-
import path from "node:path";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
|
-
|
|
23
|
-
export const REQUIRED_CHECKS = Object.freeze([
|
|
24
|
-
"Node 18 on ubuntu-latest",
|
|
25
|
-
"Node 18 on macos-latest",
|
|
26
|
-
"Node 18 on windows-latest",
|
|
27
|
-
"Node 24 on ubuntu-latest",
|
|
28
|
-
"Node 24 on macos-latest",
|
|
29
|
-
"Node 24 on windows-latest",
|
|
30
|
-
"Pinned macOS CLI installer contract",
|
|
31
|
-
"Pinned ChatGPT/Codex config contract",
|
|
32
|
-
"Pinned Claude config contract",
|
|
33
|
-
"Windows standard-user Codex config contract",
|
|
34
|
-
]);
|
|
35
|
-
|
|
36
|
-
// The Windows vendor contract workflow is path-filtered, so its jobs may
|
|
37
|
-
// legitimately be absent. Present => must be green. Absent => loud warning
|
|
38
|
-
// telling the operator when a manual dispatch is owed.
|
|
39
|
-
export const CONDITIONAL_CHECKS = Object.freeze([
|
|
40
|
-
"Pinned Claude MSIX install and replacement",
|
|
41
|
-
"Pinned ChatGPT/Codex Store install",
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Judge one commit's check runs. A name with any completed/success run is
|
|
46
|
-
* green (a re-run supersedes an earlier failure); a name with no run yet, or
|
|
47
|
-
* whose runs are all still queued or in progress, is pending; a name whose
|
|
48
|
-
* runs have all completed without a success has failed. Failure outranks
|
|
49
|
-
* pending so a superseded or broken SHA is refused as soon as it is known.
|
|
50
|
-
*/
|
|
51
|
-
export function evaluateCheckRuns(runs, { required = REQUIRED_CHECKS, conditional = CONDITIONAL_CHECKS } = {}) {
|
|
52
|
-
const byName = new Map();
|
|
53
|
-
for (const run of runs) {
|
|
54
|
-
if (!byName.has(run.name)) byName.set(run.name, []);
|
|
55
|
-
byName.get(run.name).push(run);
|
|
56
|
-
}
|
|
57
|
-
const runsFor = (name) => byName.get(name) ?? [];
|
|
58
|
-
const green = (name) => runsFor(name).some((run) => run.status === "completed" && run.conclusion === "success");
|
|
59
|
-
const unfinished = (name) => runsFor(name).some((run) => run.status !== "completed");
|
|
60
|
-
const describe = (name) => {
|
|
61
|
-
const found = runsFor(name);
|
|
62
|
-
if (found.length === 0) return "MISSING";
|
|
63
|
-
return found.map((run) => `${run.status}/${run.conclusion ?? "none"}`).join(", ");
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const failures = [];
|
|
67
|
-
const pending = [];
|
|
68
|
-
const absentConditional = [];
|
|
69
|
-
for (const name of required) {
|
|
70
|
-
if (green(name)) continue;
|
|
71
|
-
if (runsFor(name).length === 0 || unfinished(name)) pending.push(name);
|
|
72
|
-
else failures.push(`required check "${name}": ${describe(name)}`);
|
|
73
|
-
}
|
|
74
|
-
for (const name of conditional) {
|
|
75
|
-
if (runsFor(name).length === 0) absentConditional.push(name);
|
|
76
|
-
else if (green(name)) continue;
|
|
77
|
-
else if (unfinished(name)) pending.push(name);
|
|
78
|
-
else failures.push(`Windows vendor check "${name}": ${describe(name)}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const state = failures.length > 0 ? "failure" : pending.length > 0 ? "pending" : "success";
|
|
82
|
-
const summary = ["## Release gate: checks on the commit", ""];
|
|
83
|
-
summary.push("| Check | Result |", "| --- | --- |");
|
|
84
|
-
for (const name of [...required, ...conditional]) summary.push(`| ${name} | ${describe(name)} |`);
|
|
85
|
-
if (absentConditional.length > 0) {
|
|
86
|
-
summary.push(
|
|
87
|
-
"",
|
|
88
|
-
"> **Warning:** " + absentConditional.map((name) => `\`${name}\``).join(" and ")
|
|
89
|
-
+ " never ran on this commit. If this change touches bundle-affecting files"
|
|
90
|
-
+ " (src/apps.js, src/windowsApps.js, src/desktopTasks.js, src/codesign.js,"
|
|
91
|
-
+ " src/selfInvocation.js, or the Windows contract tests), dispatch the"
|
|
92
|
-
+ " \"Pinned Windows vendor app contract\" workflow against this commit.",
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
if (failures.length > 0) summary.push("", "**Gate failed:**", ...failures.map((failure) => `- ${failure}`));
|
|
96
|
-
if (state === "pending") summary.push("", "**Still waiting on:** " + pending.map((name) => `\`${name}\``).join(", "));
|
|
97
|
-
summary.push("", `Total check runs found on this commit: ${runs.length}`);
|
|
98
|
-
|
|
99
|
-
return { state, failures, pending, absentConditional, summary: summary.join("\n") + "\n" };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function main(argv) {
|
|
103
|
-
if (argv[0] === "--list") {
|
|
104
|
-
process.stdout.write(REQUIRED_CHECKS.join("\n") + "\n");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
if (argv.length !== 1) {
|
|
108
|
-
process.stderr.write("usage: node scripts/required-checks.mjs <check-runs.ndjson> | --list\n");
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
const lines = fs.readFileSync(path.resolve(argv[0]), "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
112
|
-
const runs = lines.map((line) => JSON.parse(line));
|
|
113
|
-
const result = evaluateCheckRuns(runs);
|
|
114
|
-
process.stdout.write(result.summary);
|
|
115
|
-
for (const failure of result.failures) process.stderr.write(`${failure}\n`);
|
|
116
|
-
if (result.state === "failure") process.exit(1);
|
|
117
|
-
if (result.state === "pending") {
|
|
118
|
-
process.stderr.write(`waiting for ${result.pending.map((name) => `"${name}": ${runs.some((run) => run.name === name) ? "pending" : "MISSING"}`).join(", ")}\n`);
|
|
119
|
-
process.exit(2);
|
|
120
|
-
}
|
|
121
|
-
process.stderr.write("All required checks are green on the pushed commit.\n");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
125
|
-
main(process.argv.slice(2));
|
|
126
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { execFileSync } from "node:child_process";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
-
|
|
7
|
-
export function assertCanaryInstall({ version, expectedVersion, brand, origins }) {
|
|
8
|
-
assert.equal(version, `${expectedVersion} (canary)`);
|
|
9
|
-
assert.deepEqual({
|
|
10
|
-
channel: brand.channel,
|
|
11
|
-
gateway: brand.gateway,
|
|
12
|
-
sessions: brand.sessions,
|
|
13
|
-
resolvedSessions: brand.resolvedSessions,
|
|
14
|
-
controlPlane: brand.controlPlane,
|
|
15
|
-
}, {
|
|
16
|
-
channel: "canary",
|
|
17
|
-
gateway: origins.gateway,
|
|
18
|
-
sessions: origins.sessions,
|
|
19
|
-
resolvedSessions: origins.sessions,
|
|
20
|
-
controlPlane: origins.controlPlane,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function main([prefix, expectedVersion]) {
|
|
25
|
-
if (!prefix || !expectedVersion) throw new Error("usage: node scripts/verify-canary-install.mjs <npm-prefix> <version>");
|
|
26
|
-
// Assert the installed package's defaults, never an Actions-level override.
|
|
27
|
-
for (const name of ["IMPEL_GATEWAY_URL", "IMPEL_SESSIONS_URL", "IMPEL_APP_URL", "IMPEL_CLI_RUNTIME_BRAND"]) {
|
|
28
|
-
delete process.env[name];
|
|
29
|
-
}
|
|
30
|
-
const cli = path.join(prefix, "bin", "impel");
|
|
31
|
-
const root = path.join(prefix, "lib", "node_modules", "impel-cli");
|
|
32
|
-
const version = execFileSync(cli, ["--version"], {
|
|
33
|
-
encoding: "utf8",
|
|
34
|
-
env: { ...process.env, IMPEL_SKIP_UPDATE_CHECK: "1", IMPEL_DISABLE_TELEMETRY: "1" },
|
|
35
|
-
}).trim();
|
|
36
|
-
const load = (file) => import(pathToFileURL(path.join(root, "src", file)).href);
|
|
37
|
-
const [config, sessions, runtime] = await Promise.all([
|
|
38
|
-
load("config.js"),
|
|
39
|
-
load("sessionCollector.js"),
|
|
40
|
-
load("runtimeBrand.js"),
|
|
41
|
-
]);
|
|
42
|
-
const { resolveDefaultGateway, resolveDefaultAppUrl } = config;
|
|
43
|
-
const { DEFAULT_SESSIONS_URL, resolveSessionsUrl } = sessions;
|
|
44
|
-
const { CHANNEL_ORIGINS, RUNTIME_BRAND } = runtime;
|
|
45
|
-
assertCanaryInstall({
|
|
46
|
-
version,
|
|
47
|
-
expectedVersion,
|
|
48
|
-
brand: {
|
|
49
|
-
channel: RUNTIME_BRAND.channel,
|
|
50
|
-
gateway: resolveDefaultGateway(),
|
|
51
|
-
sessions: DEFAULT_SESSIONS_URL,
|
|
52
|
-
resolvedSessions: resolveSessionsUrl({}),
|
|
53
|
-
controlPlane: resolveDefaultAppUrl(),
|
|
54
|
-
},
|
|
55
|
-
origins: CHANNEL_ORIGINS.canary,
|
|
56
|
-
});
|
|
57
|
-
console.log(`Installed canary ${version} resolves ${JSON.stringify(CHANNEL_ORIGINS.canary)}.`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
61
|
-
await main(process.argv.slice(2));
|
|
62
|
-
}
|