@decohere/ci-tools 0.0.1-dev.124 → 0.0.1-dev.126
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/bench/bench.mjs +2 -2
- package/src/bench/history.mjs +3 -3
- package/src/bench/nightly.mjs +1 -1
- package/src/bench/regression-issue.mjs +1 -1
- package/src/github/npm-bootstrap.mjs +4 -4
- package/src/github/oidc-bootstrap-nudge.mjs +2 -2
- package/src/lib/github-issue.mjs +1 -1
- package/src/pages/bench-page.mjs +2 -2
- package/tests/github/npm-bootstrap.test.mjs +4 -4
- package/tests/github/oidc-bootstrap-nudge.test.mjs +4 -5
- package/tests/lib/github-issue.test.mjs +1 -1
package/package.json
CHANGED
package/src/bench/bench.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* bench.mjs — run the benchmark suites and compare against the last saved run
|
|
4
|
+
* bench.mjs — run the benchmark suites and compare against the last saved run.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
7
|
* pnpm bench — run every suite and compare, do not save
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./history.mjs";
|
|
42
42
|
|
|
43
43
|
const WORKSPACE_ROOT = process.cwd();
|
|
44
|
-
// BENCH_HISTORY_FILE lets the nightly job save each comparison round to its own file
|
|
44
|
+
// BENCH_HISTORY_FILE lets the nightly job save each comparison round to its own file.
|
|
45
45
|
const HISTORY_FILE =
|
|
46
46
|
process.env.BENCH_HISTORY_FILE ??
|
|
47
47
|
join(WORKSPACE_ROOT, "projects/ci-tools/dist/ci/bench/bench-history.json");
|
package/src/bench/history.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Benchmark history: the results of each `pnpm bench` run, kept per machine so runs are only
|
|
3
|
-
* compared like for like
|
|
3
|
+
* compared like for like. Pure functions over plain data; bench.mjs does the I/O.
|
|
4
4
|
*
|
|
5
5
|
* Shape (version 2):
|
|
6
6
|
* { version: 2, contexts: { [contextId]: { context, runs: [{ date, sha, results }] } } }
|
|
@@ -118,7 +118,7 @@ export function previousRun(history, id) {
|
|
|
118
118
|
return history.contexts[id]?.runs[0];
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
/** Machine types with no run for this long are dropped: CI runner types come and go
|
|
121
|
+
/** Machine types with no run for this long are dropped: CI runner types come and go. */
|
|
122
122
|
export const STALE_AFTER_DAYS = 30;
|
|
123
123
|
|
|
124
124
|
/** The history without machine types whose newest run is older than `days` before `now`. */
|
|
@@ -205,7 +205,7 @@ export function formatComparison(rows) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
|
-
* When a benchmark counts as slower
|
|
208
|
+
* When a benchmark counts as slower: the nightly job benchmarks tonight's commit (head)
|
|
209
209
|
* and the one the previous nightly measured (base) on the same runner, alternating head, base,
|
|
210
210
|
* head, base. A benchmark regressed when head's median beats base's by more than `threshold`
|
|
211
211
|
* in every round, so one noisy round files nothing.
|
package/src/bench/nightly.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* nightly.mjs — the nightly benchmark run
|
|
4
|
+
* nightly.mjs — the nightly benchmark run. Benchmarks tonight's commit (head) and the
|
|
5
5
|
* commit the previous nightly measured (base) on this runner, alternating head, base, head,
|
|
6
6
|
* base, so the comparison never mixes CPU models. Then:
|
|
7
7
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The GitHub issue for a benchmark that got slower
|
|
2
|
+
* The GitHub issue for a benchmark that got slower: one open issue per benchmark,
|
|
3
3
|
* found again by its exact title and updated in place while the regression lasts.
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* First-publish a new package name (
|
|
2
|
+
* First-publish a new package name (public) and give it its Trusted Publisher,
|
|
3
3
|
* so `publish.yml` can release it over OIDC from then on.
|
|
4
4
|
*
|
|
5
5
|
* pnpm npm:bootstrap [--otp <code>] [--dry-run] [--channel dev] [<package-name>...]
|
|
@@ -31,15 +31,15 @@ export function needsPrereleaseTag(version) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* npm arguments for a name-only first publish.
|
|
35
|
-
* so
|
|
34
|
+
* npm arguments for a name-only first publish. Scoped names default to restricted,
|
|
35
|
+
* so `--access public`. `./` stops npm reading the path as a GitHub `owner/repo`.
|
|
36
36
|
*
|
|
37
37
|
* @param {{ dir: string, version?: string }} pkg
|
|
38
38
|
* @param {string} channel
|
|
39
39
|
*/
|
|
40
40
|
export function publishArgs(pkg, channel) {
|
|
41
41
|
const tag = needsPrereleaseTag(pkg.version) ? ["--tag", channel] : [];
|
|
42
|
-
return ["publish", `./projects/${pkg.dir}`, ...tag];
|
|
42
|
+
return ["publish", `./projects/${pkg.dir}`, "--access", "public", ...tag];
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/** @param {string} name */
|
|
@@ -33,7 +33,7 @@ export function firstPublishCommands(packages, channel = "dev") {
|
|
|
33
33
|
}
|
|
34
34
|
return packages.map((pkg) => {
|
|
35
35
|
const tag = needsPrereleaseTag(pkg.version) ? ` --tag ${channel}` : "";
|
|
36
|
-
return `npm publish ./projects/${pkg.dir}${tag}`;
|
|
36
|
+
return `npm publish ./projects/${pkg.dir} --access public${tag}`;
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -95,7 +95,7 @@ export function buildDescription(options) {
|
|
|
95
95
|
"",
|
|
96
96
|
"That does steps 1 and 2 below, skipping what is already done. To do them by hand instead:",
|
|
97
97
|
"",
|
|
98
|
-
"1. First-publish each name **
|
|
98
|
+
"1. First-publish each name **public** (`--access public`: scoped names default to restricted). From a trusted machine, `npm login` to the org, then from the **repo root**. Use `./` so npm does not treat the path as a GitHub `owner/repo`. `--tag` is required for prerelease versions (`x.y.z-dev.N`). Missing `bin`/`es6` warnings are OK for this name-only bootstrap; CI `forge publish` ships the built tarball later:",
|
|
99
99
|
"",
|
|
100
100
|
"```bash",
|
|
101
101
|
...firstPublishCommands(packages, channel),
|
package/src/lib/github-issue.mjs
CHANGED
|
@@ -47,7 +47,7 @@ export function upsertIssue(options, run = gh) {
|
|
|
47
47
|
"--limit",
|
|
48
48
|
"200",
|
|
49
49
|
"--search",
|
|
50
|
-
// Quoted: GitHub's search can't match a title like `security(ci): …` unquoted
|
|
50
|
+
// Quoted: GitHub's search can't match a title like `security(ci): …` unquoted.
|
|
51
51
|
// The exact-title match in pickIssue still decides.
|
|
52
52
|
`"${title.replaceAll('"', "")}" in:title`,
|
|
53
53
|
"--json",
|
package/src/pages/bench-page.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The benchmark page on Pages
|
|
2
|
+
* The benchmark page on Pages: a trend chart per benchmark and a table of the latest
|
|
3
3
|
* results, from the version 2 history (../bench/history.mjs). Static HTML and inline SVG, so the
|
|
4
4
|
* page needs no script and no third-party chart library.
|
|
5
5
|
*/
|
|
@@ -51,7 +51,7 @@ function machineName(context) {
|
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Contexts with a run within STALE_AFTER_DAYS of the newest run anywhere, most recently run first:
|
|
54
|
-
* CI runner types come and go, and one that stopped appearing would otherwise keep a line
|
|
54
|
+
* CI runner types come and go, and one that stopped appearing would otherwise keep a line.
|
|
55
55
|
*/
|
|
56
56
|
function activeContexts(history) {
|
|
57
57
|
const newest = Math.max(
|
|
@@ -58,7 +58,7 @@ afterEach(() => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
describe("npm-bootstrap", () => {
|
|
61
|
-
it("first-publishes unpublished names
|
|
61
|
+
it("first-publishes unpublished names public, then sets the Trusted Publisher", async () => {
|
|
62
62
|
seedWorkspace();
|
|
63
63
|
const registry = fakeNpm({ published: ["@decohere/scribe"] });
|
|
64
64
|
|
|
@@ -67,7 +67,7 @@ describe("npm-bootstrap", () => {
|
|
|
67
67
|
expect(code).toBe(0);
|
|
68
68
|
expect(registry.calls).toEqual([
|
|
69
69
|
"whoami",
|
|
70
|
-
"publish ./projects/scribe/scribe-console --tag dev [otp 123456]",
|
|
70
|
+
"publish ./projects/scribe/scribe-console --access public --tag dev [otp 123456]",
|
|
71
71
|
"trust list @decohere/scribe-console --json [otp 123456]",
|
|
72
72
|
"trust github @decohere/scribe-console --file publish.yml --repo typesmiths/decohere --env npm-publish --allow-publish --yes [otp 123456]",
|
|
73
73
|
]);
|
|
@@ -86,7 +86,7 @@ describe("npm-bootstrap", () => {
|
|
|
86
86
|
expect(registry.calls).toEqual(["whoami", "trust list @decohere/scribe-console --json"]);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
/**
|
|
89
|
+
/** `npm trust` rejects `--otp`: the code goes through the environment. */
|
|
90
90
|
it("never passes the code as an argument, and lets npm ask when none is given", async () => {
|
|
91
91
|
seedWorkspace();
|
|
92
92
|
const withCode = fakeNpm({ published: ["@decohere/scribe"] });
|
|
@@ -107,7 +107,7 @@ describe("npm-bootstrap", () => {
|
|
|
107
107
|
expect(code).toBe(0);
|
|
108
108
|
expect(registry.calls).toEqual(["whoami"]);
|
|
109
109
|
expect(lines).toContain(
|
|
110
|
-
"[dry run] npm publish ./projects/scribe/scribe-console --tag dev",
|
|
110
|
+
"[dry run] npm publish ./projects/scribe/scribe-console --access public --tag dev",
|
|
111
111
|
);
|
|
112
112
|
});
|
|
113
113
|
|
|
@@ -47,16 +47,15 @@ describe("oidc-bootstrap-nudge", () => {
|
|
|
47
47
|
expect(needsPrereleaseTag("0.0.1-dev.18")).toBe(true);
|
|
48
48
|
expect(needsPrereleaseTag("1.2.3")).toBe(false);
|
|
49
49
|
expect(firstPublishCommands([pkg], "dev")).toEqual([
|
|
50
|
-
"npm publish ./projects/scaffold --tag dev",
|
|
50
|
+
"npm publish ./projects/scaffold --access public --tag dev",
|
|
51
51
|
]);
|
|
52
52
|
expect(firstPublishCommands([{ ...pkg, version: "1.0.0" }], "dev")).toEqual([
|
|
53
|
-
"npm publish ./projects/scaffold",
|
|
53
|
+
"npm publish ./projects/scaffold --access public",
|
|
54
54
|
]);
|
|
55
|
-
expect(body).toContain("npm publish ./projects/scaffold --tag dev");
|
|
55
|
+
expect(body).toContain("npm publish ./projects/scaffold --access public --tag dev");
|
|
56
56
|
expect(body).toContain("pnpm npm:bootstrap --otp <code> @decohere/scaffold");
|
|
57
57
|
expect(body).not.toMatch(/# @decohere\/scaffold/);
|
|
58
|
-
expect(body).toContain("
|
|
59
|
-
expect(firstPublishCommands([pkg], "dev").join("\n")).not.toContain("--access public");
|
|
58
|
+
expect(body).toContain("First-publish each name **public**");
|
|
60
59
|
expect(body).toContain("Workflow filename: `publish.yml`");
|
|
61
60
|
expect(body).toContain("Environment: `npm-publish`");
|
|
62
61
|
expect(body).toContain("gh run rerun --failed");
|
|
@@ -28,7 +28,7 @@ describe("github-issue", () => {
|
|
|
28
28
|
expect(pickIssue([], TITLE)).toBeNull();
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// GitHub's search can't match `security(ci): …` unquoted, so the lookup found nothing
|
|
32
32
|
// and a new issue was opened on every run.
|
|
33
33
|
it("searches for the title as a quoted phrase", () => {
|
|
34
34
|
const { run, calls } = fakeGh([]);
|