Public: anyone can read this; the crew can change it.

Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:swqri6g6e7 is past its budget: trevato/forge: "RepoSource: one repository, two places to read it from > the mirror and the origin answer the same ques… #7715

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/7686-sentinel-shared-01m23vygyffx5hg2f5vm8r74 → main 2 commits fork 1 thread · 1 unresolved

  • Merged. scout/7686-sentinel-shared-01m23vygyffx5hg2f5vm8r74 was merged into main as 2be57f7.

Review

Sign in to review this change.
6 files changed +65 −8
src/origins/git-mirror.ts +3
@@ -50,6 +50,9 @@ export function provideMirrorOutboundForTest(options: OutboundOptions): void {
5050 outbound = options;
5151 }
5252
53 /** Test seam: what `vetHost` is told now, so a test that changes it can put it back. */
54 export const mirrorOutboundForTest = (): OutboundOptions => outbound;
55
5356 export const MIRROR_REFUSED = "refused: the remote's host is a private address";
5457 export const MIRROR_UNRESOLVED = "the remote's host could not be resolved";
5558
test/helpers.test.ts +19 −1
@@ -13,7 +13,17 @@ import { join } from "node:path";
1313 import { gitClientEnv } from "./helpers/git-client.ts";
1414 import { logLevel, setLogLevel, type LogLevel } from "../src/kernel/log.ts";
1515 import { firstFetchRetry } from "../src/origins/mirror.ts";
16 import { fastFirstFetch, quietLogs, withoutEnv } from "./helpers/globals.ts";
16 import {
17 mirrorOutboundForTest,
18 provideMirrorOutboundForTest,
19 } from "../src/origins/git-mirror.ts";
20 import type { OutboundOptions } from "../src/kernel/outbound.ts";
21 import {
22 fastFirstFetch,
23 mirrorOutbound,
24 quietLogs,
25 withoutEnv,
26 } from "./helpers/globals.ts";
1727 import { missing } from "./helpers/tools.ts";
1828
1929 describe("a git client's environment under test", () => {
@@ -87,22 +97,27 @@ describe("a global a file borrows is given back", () => {
8797 // rather than a coincidence with the defaults.
8898 const ASIDE = "https://machine.example.test";
8999 const WAITS: readonly number[] = [1, 2, 3];
100 const VET: OutboundOptions = { allow: ["192.0.2.7"] };
90101 let found: {
91102 level: LogLevel;
92103 waits: readonly number[];
93104 url: string | undefined;
105 vet: OutboundOptions;
94106 };
95107 beforeAll(() => {
96108 found = {
97109 level: logLevel(),
98110 waits: firstFetchRetry.ms,
99111 url: process.env.FORGE_URL,
112 vet: mirrorOutboundForTest(),
100113 };
101114 setLogLevel("warn");
102115 firstFetchRetry.ms = WAITS;
103116 process.env.FORGE_URL = ASIDE;
117 provideMirrorOutboundForTest(VET);
104118 });
105119 afterAll(() => {
120 provideMirrorOutboundForTest(found.vet);
106121 setLogLevel(found.level);
107122 firstFetchRetry.ms = found.waits;
108123 if (found.url === undefined) delete process.env.FORGE_URL;
@@ -113,11 +128,13 @@ describe("a global a file borrows is given back", () => {
113128 quietLogs();
114129 fastFirstFetch([50]);
115130 withoutEnv("FORGE_URL");
131 mirrorOutbound({});
116132
117133 test("they hold what it asked for", () => {
118134 expect(logLevel()).toBe("error");
119135 expect(firstFetchRetry.ms).toEqual([50]);
120136 expect(process.env.FORGE_URL).toBeUndefined();
137 expect(mirrorOutboundForTest()).toEqual({});
121138 // What the file sets under a cleared name goes when it does.
122139 process.env.FORGE_URL = "https://set.inside.test";
123140 });
@@ -127,5 +144,6 @@ describe("a global a file borrows is given back", () => {
127144 expect(logLevel()).toBe("warn");
128145 expect(firstFetchRetry.ms).toBe(WAITS);
129146 expect(process.env.FORGE_URL).toBe(ASIDE);
147 expect(mirrorOutboundForTest()).toBe(VET);
130148 });
131149 });
test/helpers/globals.ts +19
@@ -10,6 +10,11 @@
1010 import { afterAll, beforeAll } from "bun:test";
1111 import { logLevel, setLogLevel, type LogLevel } from "../../src/kernel/log.ts";
1212 import { firstFetchRetry } from "../../src/origins/mirror.ts";
13 import type { OutboundOptions } from "../../src/kernel/outbound.ts";
14 import {
15 mirrorOutboundForTest,
16 provideMirrorOutboundForTest,
17 } from "../../src/origins/git-mirror.ts";
1318
1419 /** Raise the log floor (by default to errors only) while this scope runs. */
1520 export function quietLogs(level: LogLevel = "error"): void {
@@ -33,6 +38,20 @@ export function fastFirstFetch(ms: readonly number[] = [50]): void {
3338 });
3439 }
3540
41 /**
42 * Tell a mirror's outbound vet `options` while this scope runs. The preload
43 * lets every file mirror from loopback; a file that tightens that and leaves
44 * it tightened refuses the next file's fake origin in the same shard.
45 */
46 export function mirrorOutbound(options: OutboundOptions): void {
47 let found: OutboundOptions;
48 beforeAll(() => {
49 found = mirrorOutboundForTest();
50 provideMirrorOutboundForTest(options);
51 });
52 afterAll(() => provideMirrorOutboundForTest(found));
53 }
54
3655 /**
3756 * Unset environment variables the machine may carry while this scope runs.
3857 * A crew machine sets `FORGE_URL` to its own forge; a test that registers an
test/mirror-outbound.test.ts +2 −2
@@ -10,14 +10,14 @@ import {
1010 provideMirrorOutboundForTest,
1111 } from "../src/origins/git-mirror.ts";
1212 import { remoteGitEnv, pinFor } from "../src/git/remote-env.ts";
13 import { mirrorOutbound } from "./helpers/globals.ts";
1314
1415 let dir: string;
16 mirrorOutbound({});
1517 beforeAll(async () => {
1618 dir = await mkdtemp(join(tmpdir(), "mirror-outbound-"));
17 provideMirrorOutboundForTest({});
1819 });
1920 afterAll(async () => {
20 provideMirrorOutboundForTest({ allow: ["127.0.0.1", "::1"] });
2121 await rm(dir, { recursive: true, force: true });
2222 });
2323
test/upstream_follow.test.ts +4 −2
@@ -32,6 +32,7 @@ import { runGit } from "../src/git/env.ts";
3232 import { REMOTE_PROTOCOLS } from "../src/git/remote-env.ts";
3333 import { repoDir } from "../src/git/repos.ts";
3434 import { MIRROR_REFUSED, provideMirrorOutboundForTest, vettedEnv } from "../src/origins/git-mirror.ts";
35 import { mirrorOutbound } from "./helpers/globals.ts";
3536 import {
3637 getFollow,
3738 listFollowing,
@@ -156,9 +157,10 @@ describe("checking an upstream (layer 2)", () => {
156157 beforeAll(async () => {
157158 target = ok(await createRepo(app, alice, { name: "checked", visibility: "public" }));
158159 dir = repoDir(app.reposRoot, target.ownerName, target.name);
159 provideMirrorOutboundForTest({ allow: ["127.0.0.1"] });
160160 });
161 afterAll(() => provideMirrorOutboundForTest({}));
161 // Given back as found: a bare `{}` here refused loopback to every file
162 // after this one in its shard (#7686).
163 mirrorOutbound({ allow: ["127.0.0.1"] });
162164 /** A server that records every request and answers with `refs` as a dumb-http `info/refs`. */
163165 function upstream(refs: () => string, delayMs = 0) {
164166 const seen: Request[] = [];
test/view-source.test.ts +18 −3
@@ -5,7 +5,12 @@ import { join } from "node:path";
55 import { createApp, type App } from "../src/app.ts";
66 import { serve, type Servers } from "../src/http/server.ts";
77 import { getUserByName, type User } from "../src/core/users.ts";
8 import { settled, subscribe, type MirrorStage } from "../src/origins/jobs.ts";
8 import {
9 runningJob,
10 settled,
11 subscribe,
12 type MirrorStage,
13 } from "../src/origins/jobs.ts";
914 import { forgetProviders } from "../src/origins/providers/index.ts";
1015 import {
1116 clearViewCache,
@@ -19,7 +24,7 @@ import {
1924 serveFakeForge,
2025 type FakeForge,
2126 } from "./fake-origin.ts";
22 import { fastFirstFetch } from "./helpers/globals.ts";
27 import { fastFirstFetch, mirrorOutbound } from "./helpers/globals.ts";
2328 import { seedAdmin } from "./helpers/admin.ts";
2429
2530 /**
@@ -54,6 +59,9 @@ const text = (body: Uint8Array): string => new TextDecoder().decode(body);
5459
5560 // A fetch that fails should say so now, not after the forge's patience.
5661 fastFirstFetch();
62 // Both origins are on loopback. Asked for here, not inherited, so a file
63 // earlier in the shard that left the vet tightened cannot refuse them (#7686).
64 mirrorOutbound({ allow: ["127.0.0.1", "::1"] });
5765
5866 describe("RepoSource: one repository, two places to read it from", () => {
5967 let dataDir: string;
@@ -653,6 +661,10 @@ describe("RepoSource: one repository, two places to read it from", () => {
653661 // ---- the equivalence that makes the interface worth having ----
654662
655663 test("the mirror and the origin answer the same questions the same way", async () => {
664 // Compare against the finished mirror: if the test that started it ran
665 // out of time on a loaded machine, its import may still be running.
666 const importing = runningJob(originId, "octo/widgets");
667 if (importing !== undefined) await settled(importing.id);
656668 const here = local("alice", "widgets");
657669 const there = live("octo/widgets");
658670 expect(here.where.kind).toBe("local");
@@ -796,7 +808,10 @@ describe("RepoSource: one repository, two places to read it from", () => {
796808 // And the one thing that must differ: what you may do here.
797809 expect(here.capabilities.write).toBe(true);
798810 expect(there.capabilities.write).toBe(false);
799 });
811 // Eight rounds of git reads against HTTP reads: milliseconds when idle,
812 // past bun's 5 s default on a loaded check machine (#7686). The verdict
813 // is the answers', not the clock's.
814 }, 60_000);

This comment sits after the last assertion and reads as if it belongs to nothing. Put it above the test or beside the title, and use the shared MIRROR_MS once #7713 lands.

800815
801816 test("a local source refuses a repo the viewer cannot read", () => {
802817 app.db

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs