g1t/scripts/ops/artifacts-namespaces.test.mjs

95 lines4,809 bytesCodeBlame
1// The namespace report, from configuration and table rows as the repos
2// database holds them.
3
4import assert from "node:assert/strict";
5import { readFileSync } from "node:fs";
6import { test } from "node:test";
7import { fileURLToPath } from "node:url";
8
9import { parseJsonc } from "../deploy/stack.mjs";
10import { LIMIT_PER_MINUTE, configured, namespaceOf, standings, table } from "./artifacts-namespaces.mjs";
11
12const sharded = {
13 artifacts: [
14 { binding: "ARTIFACTS", namespace: "g1t" },
15 { binding: "ARTIFACTS_1", namespace: "g1t-us-1" },
16 { binding: "ARTIFACTS_EU", namespace: "g1t-eu" },
17 ],
18 vars: {
19 ARTIFACTS_NAMESPACES: JSON.stringify({ ARTIFACTS: "g1t", ARTIFACTS_1: "g1t-us-1", ARTIFACTS_EU: "g1t-eu", ARTIFACTS_2: "g1t-us-2" }),
20 ARTIFACTS_NEW_REPOS: "g1t,g1t-us-1,g1t-us-2",
21 ARTIFACTS_EU_NAMESPACE: "g1t-eu",
22 ARTIFACTS_NAMESPACE_LIMITS: JSON.stringify({ "g1t": { max_repos: 100 } }),
23 },
24};
25
26test("today's configuration is one namespace that takes nothing new by name", () => {
27 const today = parseJsonc(readFileSync(fileURLToPath(new URL("../../services/repos/wrangler.jsonc", import.meta.url)), "utf8"));
28 const config = configured(today);
29 assert.equal(config.length, 1);
30 assert.deepEqual(
31 { namespace: config[0].namespace, bound: config[0].bound, default: config[0].default, takes: config[0].takes_new_repos, eu: config[0].eu },
32 { namespace: "g1t", bound: true, default: true, takes: false, eu: false },
33 );
34});
35
36test("each namespace's binding, jurisdiction and part in placing are read from the configuration", () => {
37 const config = configured(sharded);
38 const by = Object.fromEntries(config.map((one) => [one.namespace, one]));
39 // A binding never says its namespace's jurisdiction; Cloudflare does.
40 assert.equal(by["g1t-eu"].jurisdiction, null);
41 assert.ok(by["g1t-eu"].eu && !by["g1t-eu"].takes_new_repos);
42 assert.ok(by["g1t-us-1"].bound && by["g1t-us-1"].takes_new_repos);
43 // Named, but no binding for it: not bound.
44 assert.equal(by["g1t-us-2"].bound, false);
45 assert.equal(by.g1t.max_repos, 100);
46 assert.equal(namespaceOf("acme--rocket"), "g1t");
47 assert.equal(namespaceOf("g1t-us-1/acme--rocket"), "g1t-us-1");
48 assert.equal(namespaceOf(null, "main"), "main");
49});
50
51test("standings add up holdings and health, and warn about what needs doing", () => {
52 const held = [
53 { ns: "", repos: 90, forks: 10, stored_bytes: 2e9 },
54 { ns: "g1t", repos: 10, forks: 0, stored_bytes: 1e9 },
55 { ns: "g1t-us-1", repos: 3, forks: 1, stored_bytes: 5e8 },
56 ];
57 const health = [
58 { window: "day", store: "g1t", peak: LIMIT_PER_MINUTE * 0.8, calls: 900_000, errors: 4, rate_limited: 2, rejected: 0 },
59 { window: "hour", store: "g1t", peak: 100, calls: 5_000, errors: 0, rate_limited: 2, rejected: 0 },
60 { window: "hour", store: "g1t-us-1@fallback", peak: 3, calls: 40, errors: 0, rate_limited: 0, rejected: 0 },
61 ];
62 const rows = standings(configured(sharded), held, health, [{ namespace: "g1t", count: 7 }, { namespace: "g1t-eu", count: 1 }]);
63 const by = Object.fromEntries(rows.map((row) => [row.namespace, row]));
64 assert.equal(by.g1t.repos, 100);
65 assert.equal(by.g1t.stored_bytes, 3e9);
66 assert.equal(by.g1t.cloudflare_events, 7);
67 assert.ok(by.g1t.warnings.some((w) => /80% of the limit/.test(w)));
68 assert.ok(by.g1t.warnings.some((w) => /max_repos/.test(w)));
69 assert.ok(by.g1t.warnings.some((w) => /rate limited/.test(w)));
70 assert.ok(by["g1t-us-1"].warnings.some((w) => /fallback/.test(w)));
71 assert.ok(by["g1t-us-2"].warnings.some((w) => /not bound/.test(w)));
72 assert.deepEqual(by["g1t-eu"].warnings, []);
73 const text = table(rows);
74 assert.match(text, /^namespace/);
75 assert.match(text, /g1t \*/);
76 assert.match(text, /g1t-us-2 .*\(not bound\)/);
77});
78
79test("what Cloudflare has is checked against what is bound", () => {
80 const made = [
81 { namespace: "g1t", jurisdiction: null },
82 { namespace: "g1t-us-1", jurisdiction: null },
83 { namespace: "g1t-eu", jurisdiction: null },
84 ];
85 const rows = standings(configured(sharded), [], [], [], made);
86 const by = Object.fromEntries(rows.map((row) => [row.namespace, row]));
87 // Made without the EU jurisdiction: it cannot be changed, so it is said.
88 assert.ok(by["g1t-eu"].warnings.some((w) => /jurisdiction is unrestricted/.test(w)));
89 assert.equal(by.g1t.jurisdiction, "any");
90 // Named and bound nowhere, and not made: both said.
91 assert.ok(by["g1t-us-2"].warnings.some((w) => /no namespace of this name/.test(w)));
92 const right = standings(configured(sharded), [], [], [], made.map((one) => (one.namespace === "g1t-eu" ? { ...one, jurisdiction: "eu" } : one)));
93 assert.deepEqual(right.find((row) => row.namespace === "g1t-eu").warnings, []);
94 assert.equal(right.find((row) => row.namespace === "g1t-eu").jurisdiction, "eu");
95});