commit 82b375cd86ab9d3ec55a43771c34d7b62625e0c9
parent 0278e0af2c2dfefde5332afce1cd9ec53772875b
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Tue, 6 Oct 2026 08:24:00 -0400
publish: source publish reads ARCHILYZER_SOURCE_REPO before looking for a checkout
The runtime image has no .git; docker-compose.source.yml mounts the host's git
common dir read-only and names it here. A value that names nothing refuses the
publish by name instead of falling through to "no repository".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/common/publish/source.test.ts b/common/publish/source.test.ts
@@ -375,6 +375,35 @@ test("no git repository here (a docker runtime, a tarball install): the build ge
assert.ok(!existsSync(path.join(pub, "source")));
});
+test("ARCHILYZER_SOURCE_REPO names the repository where the checkout has none (the container's mount); one that names nothing refuses by name (release 18)", async () => {
+ const bare = dir("no-git-env");
+ const pub = path.join(dir("site"), "public");
+ const logs: string[] = [];
+ const base: SourcePublishOpts = {
+ paths: { monorepoRoot: bare } as Paths,
+ publicDir: pub,
+ onLog: (l) => logs.push(l),
+ scrubFile: path.join(bare, "none.txt"),
+ denylistFile: path.join(bare, "none.txt"),
+ check: true,
+ };
+ // A mounted repository: found, so the publish goes on to the next step —
+ // here, the operator's files, which this scenario leaves out on purpose.
+ // It is a git DIR — what the overlay mounts (the host's common dir), and what
+ // the checkout lookup answers.
+ const repo = path.join(sourceRepo(), ".git");
+ assert.equal(await publishSource({ ...base, env: { ...process.env, ARCHILYZER_SOURCE_REPO: repo } }), 1);
+ assert.ok(!logs.includes(`[source] ${NO_REPOSITORY}`), logs.join("\n"));
+ assert.match(logs.join("\n"), /none\.txt/, "it reached the operator's files");
+ // A variable naming a path that is not there: a refusal that names it, never
+ // the "no repository" sentence.
+ logs.length = 0;
+ const gone = path.join(bare, "not-mounted.git");
+ assert.equal(await publishSource({ ...base, env: { ...process.env, ARCHILYZER_SOURCE_REPO: gone } }), 1);
+ assert.match(logs.join("\n"), /REFUSED: ARCHILYZER_SOURCE_REPO names .*not-mounted\.git, which is not there/);
+ assert.ok(!logs.includes(`[source] ${NO_REPOSITORY}`));
+});
+
test("round trip: --check writes nothing; publish; a dumb clone of the mirror is main, scrubbed, from static files", async (t) => {
if (filterRepoProblem) return t.skip(`git-filter-repo unavailable: ${filterRepoProblem}`);
const repo = sourceRepo();
diff --git a/common/publish/source.ts b/common/publish/source.ts
@@ -133,7 +133,8 @@ export type SourcePublishOpts = PublishOpts & {
check?: boolean;
// Leave the scratch dir (the rewritten bare clone, the stage) for a look.
keepScratch?: boolean;
- // The repository to mirror. Default: this checkout's git COMMON dir, so a
+ // The repository to mirror. Default: ARCHILYZER_SOURCE_REPO (a container's
+ // mount of the host's repository), else this checkout's git COMMON dir, so a
// worktree build mirrors the primary's main.
sourceRepo?: string;
// Default: HOMEPAGE_PUBLIC_DIR, else <repo>/homepage/public.
@@ -611,6 +612,25 @@ async function commonDir(ctx: Ctx, cwd: string): Promise<string | null> {
throw new SourceRefusal(`git rev-parse exited ${r.code}${tail ? `: ${tail}` : ""}`);
}
+// The repository to mirror when the caller names none: ARCHILYZER_SOURCE_REPO
+// when it is set — in a container, the host's git common dir mounted read-only
+// by docker-compose.source.yml, since the image has no .git — else this
+// checkout's common dir. A variable that names nothing is a refusal, not a
+// silent fall-through to "no repository" (which would withdraw the publish
+// with a sentence about tarball installs).
+async function sourceRepoFor(ctx: Ctx, cwd: string): Promise<string | null> {
+ const named = ctx.env.ARCHILYZER_SOURCE_REPO?.trim();
+ if (named) {
+ if (!existsSync(named)) {
+ throw new SourceRefusal(
+ `ARCHILYZER_SOURCE_REPO names ${named}, which is not there — mount the host's git common dir there (docker-compose.source.yml), or unset it`,
+ );
+ }
+ return named;
+ }
+ return commonDir(ctx, cwd);
+}
+
// The real path of `p`, or of its deepest existing ancestor with the rest
// appended: a scratch root may not exist yet, and a symlink must not hide
// where it lands.
@@ -764,7 +784,7 @@ async function publish(
// 1. The private main — or no repository at all (L8: the docker runtime,
// a tarball install), where nothing can be mirrored and nothing can leak.
- const sourceRepo = opts.sourceRepo ?? (await commonDir(ctx, paths.monorepoRoot));
+ const sourceRepo = opts.sourceRepo ?? (await sourceRepoFor(ctx, paths.monorepoRoot));
if (sourceRepo === null) {
onLog(`[source] ${NO_REPOSITORY}`);
if (opts.check) return 1;
@@ -1328,7 +1348,7 @@ export async function publishedSourceProblem(
};
let main: string | null = null;
try {
- const repo = opts.sourceRepo ?? (await commonDir(ctx, paths.monorepoRoot));
+ const repo = opts.sourceRepo ?? (await sourceRepoFor(ctx, paths.monorepoRoot));
main = repo ? await revParse(ctx, repo, `refs/heads/${SOURCE_BRANCH}^{commit}`) : null;
} catch (err) {
if (!(err instanceof SourceRefusal)) throw err;