import { createHash } from "node:crypto"; import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "bun:test"; import { agentRunManagedRepositoryDesiredConfig, agentRunManagedRepositoryRenderHash, renderAgentRunManagedRepositoryReconcilerFragment, } from "./agentrun-managed-repository-reconciler"; import { parseAgentRunGitFetchCredentialCapability, resolveAgentRunLaneTarget, } from "./agentrun-lanes"; import { resolveCicdDeliveryAuthority } from "./cicd-delivery-authority"; import { renderGitMirrorStatusEnvelope } from "./agentrun/git-mirror"; import { yamlLaneGitMirrorStatusScript } from "./agentrun/secrets"; import { renderPlatformInfraGiteaDesiredFragments } from "./platform-infra-gitea-desired-fragments"; const controllerPath = new URL("../native/agentrun/managed-repository-reconciler.mjs", import.meta.url).pathname; const askPassPath = new URL("../native/agentrun/git-askpass.mjs", import.meta.url).pathname; describe("AgentRun YAML-owned managed repository reconciler", () => { test("renders one narrow controller from the lane repository list", () => { const spec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec; const desired = agentRunManagedRepositoryDesiredConfig(spec); expect(desired.repositories.map((item) => item.repository)).toEqual([ "pikasTech/agentrun", "pikasTech/unidesk", "pikasTech/agent_skills", ]); expect(desired.repositories.every((item) => item.remote.startsWith("https://github.com/"))).toBe(true); expect(desired.remoteAuth).toMatchObject({ authMode: "github-https-token", host: "github.com", proxy: { host: "127.0.0.1", port: 10808 }, }); expect(desired.lifecycle).toEqual({ undeclaredRepositoryPolicy: "retain", managedRefs: "source-branch-only", }); const documents = renderAgentRunManagedRepositoryReconcilerFragment("NC01") .split(/^---\s*$/mu) .map((item) => Bun.YAML.parse(item) as any); expect(documents.map((item) => item.kind)).toEqual(["ServiceAccount", "ConfigMap", "Deployment"]); expect(documents[0].automountServiceAccountToken).toBe(false); expect(documents[1].metadata.annotations["unidesk.ai/undeclared-repository-policy"]).toBe("retain"); expect(JSON.parse(documents[1].data["config.json"]).repositories).toEqual(desired.repositories); expect(documents[2].spec.strategy.type).toBe("Recreate"); expect(documents[2].spec.template.spec.automountServiceAccountToken).toBe(false); expect(documents[2].spec.template.spec.hostNetwork).toBe(spec.gitMirror.repositoryReconciler.hostNetwork); expect(documents[2].spec.template.spec.dnsPolicy).toBe(spec.gitMirror.repositoryReconciler.dnsPolicy); expect(documents[2].spec.template.spec.containers[0].readinessProbe.exec.command).toContain("--health"); const authVolume = documents[2].spec.template.spec.volumes.find((item: any) => item.name === "git-auth"); expect(authVolume.projected.sources).toHaveLength(2); expect(authVolume.projected.sources[1].secret).toEqual({ name: "gitea-github-sync-secrets", items: [{ key: "github-token", path: "token", mode: 256 }], }); expect(JSON.stringify(authVolume)).not.toContain("gitea-username"); expect(JSON.stringify(authVolume)).not.toContain("gitea-password"); expect(JSON.stringify(authVolume)).not.toContain("github-webhook-secret"); expect(documents[2].spec.template.spec.volumes.some((item: any) => item.name === "git-ssh")).toBe(false); expect(renderAgentRunManagedRepositoryReconcilerFragment("JD01")).toBe(""); const controllerSource = readFileSync(controllerPath, "utf8"); expect(controllerSource).not.toContain("agent_skills"); expect(controllerSource).not.toContain("pikasTech/"); expect(controllerSource).not.toContain("github.com"); }); test("registers after PaC-owned admission objects without identity or separator conflicts", () => { const spec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec; const desired = agentRunManagedRepositoryDesiredConfig(spec); const fragment = renderPlatformInfraGiteaDesiredFragments("NC01"); expect(fragment).not.toContain("---\n---"); const documents = fragment .split(/^---\s*$/mu) .map((item) => Bun.YAML.parse(item) as any); expect(documents.map((item) => item.kind)).toEqual([ "Role", "RoleBinding", "ValidatingAdmissionPolicy", "ValidatingAdmissionPolicyBinding", "ServiceAccount", "ConfigMap", "Deployment", ]); const identities = documents.map((item) => [ item.apiVersion, item.kind, item.metadata.namespace ?? "_cluster", item.metadata.name, ].join("/")); expect(new Set(identities).size).toBe(documents.length); const managed = documents.slice(-3); expect(managed.map((item) => item.metadata.name)).toEqual([ spec.gitMirror.repositoryReconciler.serviceAccountName, spec.gitMirror.repositoryReconciler.configMapName, spec.gitMirror.repositoryReconciler.deploymentName, ]); const config = JSON.parse(managed[1].data["config.json"]); expect(config.desiredHash).toBe(desired.desiredHash); expect(managed[1].metadata.annotations["unidesk.ai/managed-repository-desired-sha"]).toBe(desired.desiredHash); expect(managed[2].metadata.annotations["unidesk.ai/managed-repository-desired-sha"]).toBe(desired.desiredHash); expect(managed[1].metadata.annotations["unidesk.ai/managed-repository-render-sha"]).toMatch(/^[0-9a-f]{64}$/u); expect(managed[2].metadata.annotations["unidesk.ai/managed-repository-render-sha"]).toBe( managed[1].metadata.annotations["unidesk.ai/managed-repository-render-sha"], ); }); test("requires every repository entry to own a matching remote", () => { const temporary = mkdtempSync("/tmp/unidesk-agentrun-repository-config-"); try { const source = readFileSync(new URL("../../config/agentrun.yaml", import.meta.url), "utf8"); const invalid = source.replace( "remote: https://github.com/pikasTech/agent_skills.git", "remote: https://github.com/pikasTech/unidesk.git", ); const configPath = join(temporary, "agentrun.yaml"); writeFileSync(configPath, invalid); expect(() => resolveAgentRunLaneTarget( { node: "NC01", lane: "nc01-v02" }, { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: configPath }, )).toThrow("same repository entry"); } finally { rmSync(temporary, { recursive: true, force: true }); } }); test("fails closed on non-canonical remotes and malformed credential capabilities", () => { const source = readFileSync(new URL("../../config/agentrun.yaml", import.meta.url), "utf8"); const canonical = "https://github.com/pikasTech/agent_skills.git"; const invalidRemotes = [ "ssh://git@ssh.github.com:443/pikasTech/agent_skills.git", "https://user@github.com/pikasTech/agent_skills.git", "https://github.com:443/pikasTech/agent_skills.git", "https://github.com/pikasTech/agent_skills.git?token=forbidden", "https://github.com/pikasTech/agent_skills.git#forbidden", "https://example.com/pikasTech/agent_skills.git", "https://github.com/pikasTech/unidesk.git", ]; const temporary = mkdtempSync("/tmp/unidesk-agentrun-remote-contract-"); try { for (const [index, remote] of invalidRemotes.entries()) { const configPath = join(temporary, `invalid-${index}.yaml`); writeFileSync(configPath, source.replace(`remote: ${canonical}`, `remote: ${remote}`)); expect(() => resolveAgentRunLaneTarget( { node: "NC01", lane: "nc01-v02" }, { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: configPath }, )).toThrow(); } } finally { rmSync(temporary, { recursive: true, force: true }); } const validCapability = { apiVersion: "unidesk.ai/v1", kind: "GitFetchCredential", authMode: "github-https-token", host: "github.com", secretRef: { namespace: "devops-infra", name: "gitea-github-sync-secrets", key: "github-token" }, }; expect(parseAgentRunGitFetchCredentialCapability(validCapability)).toEqual(validCapability); for (const invalid of [ { ...validCapability, kind: "Secret" }, { ...validCapability, authMode: "ssh" }, { ...validCapability, host: "example.com" }, { ...validCapability, secretRef: { ...validCapability.secretRef, key: "invalid/key" } }, ]) expect(() => parseAgentRunGitFetchCredentialCapability(invalid)).toThrow(); }); test("renders host networking only from the explicit reconciler fields", () => { const temporary = mkdtempSync("/tmp/unidesk-agentrun-repository-network-"); try { const source = readFileSync(new URL("../../config/agentrun.yaml", import.meta.url), "utf8"); const nonLoopbackProxy = source.replace( "githubProxy:\n host: 127.0.0.1\n port: 10808", "githubProxy:\n host: proxy.internal.example\n port: 10808", ); const nonLoopbackPath = join(temporary, "non-loopback.yaml"); writeFileSync(nonLoopbackPath, nonLoopbackProxy); const nonLoopbackEnv = { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: nonLoopbackPath }; const nonLoopbackDeployment = renderAgentRunManagedRepositoryReconcilerFragment("NC01", nonLoopbackEnv) .split(/^---\s*$/mu) .map((item) => Bun.YAML.parse(item) as any) .find((item) => item.kind === "Deployment"); expect(nonLoopbackDeployment.spec.template.spec.hostNetwork).toBe(true); expect(nonLoopbackDeployment.spec.template.spec.dnsPolicy).toBe("ClusterFirstWithHostNet"); const clusterNetwork = source.replace( "hostNetwork: true\n dnsPolicy: ClusterFirstWithHostNet", "hostNetwork: false\n dnsPolicy: ClusterFirst", ); const clusterNetworkPath = join(temporary, "cluster-network.yaml"); writeFileSync(clusterNetworkPath, clusterNetwork); const clusterNetworkEnv = { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: clusterNetworkPath }; const clusterNetworkSpec = resolveAgentRunLaneTarget( { node: "NC01", lane: "nc01-v02" }, clusterNetworkEnv, ).spec; const clusterNetworkDeployment = renderAgentRunManagedRepositoryReconcilerFragment("NC01", clusterNetworkEnv) .split(/^---\s*$/mu) .map((item) => Bun.YAML.parse(item) as any) .find((item) => item.kind === "Deployment"); expect(clusterNetworkDeployment.spec.template.spec.hostNetwork).toBe(false); expect(clusterNetworkDeployment.spec.template.spec.dnsPolicy).toBe("ClusterFirst"); const defaultSpec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec; expect(agentRunManagedRepositoryRenderHash(clusterNetworkSpec)).not.toBe(agentRunManagedRepositoryRenderHash(defaultSpec)); const invalidHostNetworkPath = join(temporary, "invalid-host-network.yaml"); writeFileSync(invalidHostNetworkPath, source.replace("dnsPolicy: ClusterFirstWithHostNet", "dnsPolicy: ClusterFirst")); expect(() => resolveAgentRunLaneTarget( { node: "NC01", lane: "nc01-v02" }, { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: invalidHostNetworkPath }, )).toThrow("must be ClusterFirstWithHostNet when"); const invalidClusterNetworkPath = join(temporary, "invalid-cluster-network.yaml"); writeFileSync(invalidClusterNetworkPath, source.replace("hostNetwork: true", "hostNetwork: false")); expect(() => resolveAgentRunLaneTarget( { node: "NC01", lane: "nc01-v02" }, { ...process.env, AGENTRUN_CONTROL_PLANE_CONFIG: invalidClusterNetworkPath }, )).toThrow("must not be ClusterFirstWithHostNet when"); } finally { rmSync(temporary, { recursive: true, force: true }); } }); test("materializes source refs, exposes health, and retains undeclared cache content", () => { const temporary = mkdtempSync("/tmp/unidesk-agentrun-managed-repository-"); try { const work = join(temporary, "work"); const remote = join(temporary, "remote.git"); const cache = join(temporary, "cache"); const auth = join(temporary, "auth"); const fakeBin = join(temporary, "bin"); const gitObservationPath = join(temporary, "git-observations.jsonl"); const tokenPath = join(auth, "token"); const fixtureAskPassPath = join(auth, "git-askpass.mjs"); mkdirSync(work, { recursive: true }); mkdirSync(cache, { recursive: true }); mkdirSync(auth, { recursive: true }); mkdirSync(fakeBin, { recursive: true }); git(["init", work]); git(["-C", work, "config", "user.name", "UniDesk fixture"]); git(["-C", work, "config", "user.email", "fixture@unidesk.invalid"]); writeFileSync(join(work, "README.md"), "managed repository fixture\n"); git(["-C", work, "add", "README.md"]); git(["-C", work, "commit", "-m", "fixture"]); git(["-C", work, "branch", "-M", "main"]); git(["clone", "--bare", work, remote]); const fixtureToken = "github_pat_fixture_not_for_logs"; writeFileSync(tokenPath, `${fixtureToken}\n`); copyFileSync(askPassPath, fixtureAskPassPath); chmodSync(fixtureAskPassPath, 0o555); const retainedPath = join(cache, "undeclared", "retained.git"); mkdirSync(retainedPath, { recursive: true }); writeFileSync(join(retainedPath, "marker"), "retain\n"); const remoteUrl = "https://github.com/acme/example.git"; writeGitShim({ path: join(fakeBin, "git"), realGit: Bun.which("git")!, observationPath: gitObservationPath, remoteUrl, replacementRemoteUrl: `file://${remote}`, }); const repository = { key: "fixture", repository: "acme/example", remote: remoteUrl, sourceBranch: "main", desiredFingerprint: sha256(["fixture", "acme/example", remoteUrl, "main"].join("\0")), }; const desired = { schemaVersion: 1, kind: "AgentRunManagedRepositoryReconciler", nodeId: "fixture-node", lane: "fixture-lane", cacheMountPath: cache, stateDirectory: ".managed-state", reconcileIntervalMs: 1000, fetchTimeoutMs: 10000, shutdownGraceMs: 1000, maxConcurrentRepositories: 1, retry: { maxAttempts: 1, initialDelayMs: 10, maxDelayMs: 10 }, freshness: { maxAgeMs: 60000 }, lifecycle: { undeclaredRepositoryPolicy: "retain", managedRefs: "source-branch-only" }, repositories: [repository], remoteAuth: { configRef: "config/platform-infra/gitea.yaml#sourceAuthority.credentials.github.gitFetchCredential", capabilitySha256: "a".repeat(64), authMode: "github-https-token", host: "github.com", tokenFile: tokenPath, askPassFile: fixtureAskPassPath, proxy: { host: "127.0.0.1", port: 10808 }, }, }; const config = { ...desired, desiredHash: sha256(JSON.stringify(desired)) }; const configPath = join(temporary, "config.json"); writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`); const once = Bun.spawnSync(["node", controllerPath, "--once", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, fixtureToken), }); expect(once.exitCode, once.stderr.toString()).toBe(0); expect(`${once.stdout.toString()}\n${once.stderr.toString()}`).not.toContain(fixtureToken); const onceStatus = JSON.parse(once.stdout.toString()); expect(onceStatus.ready).toBe(true); expect(onceStatus.repositories[0].remoteFingerprint).toBe(`sha256:${sha256(remoteUrl)}`); expect(existsSync(join(retainedPath, "marker"))).toBe(true); const gitObservations = readFileSync(gitObservationPath, "utf8") .trim() .split("\n") .map((line) => JSON.parse(line)); expect(gitObservations.some((item) => item.args.includes(remoteUrl))).toBe(true); expect(gitObservations.every((item) => item.inheritedGitSsh === false)).toBe(true); expect(gitObservations.every((item) => item.inheritedGitConfig === false)).toBe(true); expect(gitObservations.every((item) => item.inheritedGithubToken === false)).toBe(true); expect(gitObservations.every((item) => item.askPassConfigured === true)).toBe(true); expect(gitObservations.every((item) => item.tlsVerifyForced === true)).toBe(true); expect(readFileSync(gitObservationPath, "utf8")).not.toContain(fixtureToken); const mirroredCommit = git([ "--git-dir", join(cache, "acme", "example.git"), "rev-parse", "--verify", "refs/heads/main^{commit}", ]).trim(); expect(mirroredCommit).toMatch(/^[0-9a-f]{40}$/u); expect(readFileSync(join(cache, "acme", "example.git", "config"), "utf8")).not.toContain(fixtureToken); expect(readFileSync(join(cache, ".managed-state", "status.json"), "utf8")).not.toContain(fixtureToken); git([ "--git-dir", join(cache, "acme", "example.git"), "update-ref", "refs/heads/retained-gitops", mirroredCommit, ]); const secondOnce = Bun.spawnSync(["node", controllerPath, "--once", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, fixtureToken), }); expect(secondOnce.exitCode, secondOnce.stderr.toString()).toBe(0); expect(git([ "--git-dir", join(cache, "acme", "example.git"), "rev-parse", "--verify", "refs/heads/retained-gitops^{commit}", ])).toBe(mirroredCommit); expect(git([ "--git-dir", join(cache, "acme", "example.git"), "for-each-ref", "--format=%(refname)", "refs/agentrun-managed", ])).toBe(""); const health = Bun.spawnSync(["node", controllerPath, "--health", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, fixtureToken), }); expect(health.exitCode, health.stderr.toString()).toBe(0); const healthStatus = JSON.parse(health.stdout.toString()); expect(healthStatus.ready).toBe(true); expect(healthStatus.repositories[0]).toMatchObject({ refPresent: true, fresh: true, commit: mirroredCommit, remoteFingerprintAligned: true, }); } finally { rmSync(temporary, { recursive: true, force: true }); } }); test("keeps readiness false and skips Git when the projected credential is missing or empty", () => { const temporary = mkdtempSync("/tmp/unidesk-agentrun-managed-repository-credential-"); try { const cache = join(temporary, "cache"); const auth = join(temporary, "auth"); const fakeBin = join(temporary, "bin"); const gitMarker = join(temporary, "git-invoked"); const tokenPath = join(auth, "token"); const fixtureAskPassPath = join(auth, "git-askpass.mjs"); mkdirSync(cache, { recursive: true }); mkdirSync(auth, { recursive: true }); mkdirSync(fakeBin, { recursive: true }); copyFileSync(askPassPath, fixtureAskPassPath); chmodSync(fixtureAskPassPath, 0o555); writeFileSync(join(fakeBin, "git"), `#!/bin/sh\ntouch ${JSON.stringify(gitMarker)}\nexit 99\n`); chmodSync(join(fakeBin, "git"), 0o755); const configPath = join(temporary, "config.json"); writeControllerConfig(configPath, { cache, tokenPath, askPassFile: fixtureAskPassPath }); writeFileSync(tokenPath, "\n"); const empty = Bun.spawnSync(["node", controllerPath, "--once", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, "inherited-token-must-not-leak"), }); expect(empty.exitCode).toBe(1); const emptyStatus = lastJsonLine(empty.stdout.toString()); expect(emptyStatus).toMatchObject({ ready: false, credential: { ready: false, errorCode: "credential-empty", valuesPrinted: false }, repositories: [{ lastAttemptOk: false, errorCode: "credential-empty" }], valuesPrinted: false, }); expect(existsSync(gitMarker)).toBe(false); rmSync(tokenPath); const missing = Bun.spawnSync(["node", controllerPath, "--health", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, "inherited-token-must-not-leak"), }); expect(missing.exitCode).toBe(1); expect(JSON.parse(missing.stdout.toString())).toMatchObject({ ready: false, credential: { ready: false, errorCode: "credential-file-missing", valuesPrinted: false }, valuesPrinted: false, }); expect(existsSync(gitMarker)).toBe(false); } finally { rmSync(temporary, { recursive: true, force: true }); } }); test("redacts authentication failures from logs, status, and repository config", () => { const temporary = mkdtempSync("/tmp/unidesk-agentrun-managed-repository-redaction-"); try { const work = join(temporary, "work"); const remote = join(temporary, "remote.git"); const cache = join(temporary, "cache"); const auth = join(temporary, "auth"); const fakeBin = join(temporary, "bin"); const tokenPath = join(auth, "token"); const fixtureAskPassPath = join(auth, "git-askpass.mjs"); const gitObservationPath = join(temporary, "git-observations.jsonl"); const remoteUrl = "https://github.com/acme/example.git"; const sensitive = "github_pat_sensitive_authentication_failure"; mkdirSync(work, { recursive: true }); mkdirSync(cache, { recursive: true }); mkdirSync(auth, { recursive: true }); mkdirSync(fakeBin, { recursive: true }); git(["init", work]); git(["clone", "--bare", work, remote]); writeFileSync(tokenPath, `${sensitive}\n`); copyFileSync(askPassPath, fixtureAskPassPath); chmodSync(fixtureAskPassPath, 0o555); writeGitShim({ path: join(fakeBin, "git"), realGit: Bun.which("git")!, observationPath: gitObservationPath, remoteUrl, replacementRemoteUrl: `file://${remote}`, failFetchMessage: `authentication failed for ${sensitive}`, }); const configPath = join(temporary, "config.json"); writeControllerConfig(configPath, { cache, tokenPath, askPassFile: fixtureAskPassPath }); const once = Bun.spawnSync(["node", controllerPath, "--once", "--config", configPath], { stdout: "pipe", stderr: "pipe", env: inheritedHostileGitEnvironment(fakeBin, sensitive), }); expect(once.exitCode).toBe(1); const combined = `${once.stdout.toString()}\n${once.stderr.toString()}`; expect(combined).not.toContain(sensitive); const status = lastJsonLine(once.stdout.toString()); expect(status.repositories[0]).toMatchObject({ lastAttemptOk: false, errorCode: "authentication-failed", }); expect(status.repositories[0].errorFingerprint).toMatch(/^[0-9a-f]{16}$/u); expect(readFileSync(gitObservationPath, "utf8")).not.toContain(sensitive); expect(readFileSync(join(cache, ".managed-state", "status.json"), "utf8")).not.toContain(sensitive); expect(existsSync(join(cache, "acme", "example.git"))).toBe(false); } finally { rmSync(temporary, { recursive: true, force: true }); } }); test("keeps the legacy default summary contract and bounds the final CLI envelope", () => { const target = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }); const spec = target.spec; const authority = resolveCicdDeliveryAuthority({ node: spec.nodeId, lane: spec.lane, sourceRepository: spec.source.repository, sourceBranch: spec.source.branch, declaredSourceAuthorityMode: spec.source.sourceAuthority?.mode ?? null, declaredConfigRef: target.configPath, }); expect(authority.kind).toBe("pac-pr-merge"); const defaultRepositoryLimit = spec.gitMirror.repositoryReconciler.status.defaultRepositoryLimit; const fixtureRepositoryTotal = defaultRepositoryLimit + 2; const repositories = Array.from({ length: fixtureRepositoryTotal }, (_, index) => ({ key: `repo-${index}`, repository: `acme/repo-${index}`, sourceBranch: "main", cacheCommit: String(index).repeat(40), cacheRefPresent: true, servedCommit: String(index).repeat(40), servedRefPresent: true, refAligned: true, remoteFingerprintAligned: true, fresh: true, })); const summary = { ok: true, repository: "pikasTech/agentrun", sourceBranch: "v0.2", gitopsBranch: "nc01-v0.2-gitops", sourceCommit: "a".repeat(40), gitopsCommit: "b".repeat(40), controller: { deploymentReady: true, configRendered: true, workloadRendered: true, statusAligned: true, heartbeatFresh: true, }, repositories, firstDrift: null, valuesPrinted: false, }; const observation = { ok: true, summary, raw: JSON.stringify(summary), result: { exitCode: 0, stdout: JSON.stringify(summary), stderr: "" }, } as any; const baseOptions = { node: "NC01", lane: "nc01-v02" }; const compact = renderGitMirrorStatusEnvelope( target, authority, observation, { ...baseOptions, full: false, raw: false }, ) as any; expect(compact.summary).toMatchObject({ repository: "pikasTech/agentrun", sourceBranch: "v0.2", gitopsBranch: "nc01-v0.2-gitops", sourceCommit: "a".repeat(40), gitopsCommit: "b".repeat(40), }); expect(compact.summary.repositories).toHaveLength(defaultRepositoryLimit); expect(compact.summary.repositoryView).toEqual({ limit: defaultRepositoryLimit, total: fixtureRepositoryTotal, shown: defaultRepositoryLimit, omitted: fixtureRepositoryTotal - defaultRepositoryLimit, }); expect(compact.target.repositoryView).toEqual({ limit: defaultRepositoryLimit, total: spec.gitMirror.repositories.length, shown: spec.gitMirror.repositories.length, omitted: 0, }); expect(compact.probe.stdoutTailOmitted).toBe(true); expect(compact.disclosure.probeTailOmitted).toBe(true); expect(compact.next).toMatchObject({ status: expect.any(String), history: expect.any(String) }); expect(compact.next.sync).toBeUndefined(); for (const options of [ { ...baseOptions, full: true, raw: false }, { ...baseOptions, full: false, raw: true }, ]) { const expanded = renderGitMirrorStatusEnvelope(target, authority, observation, options) as any; expect(expanded.summary.repositories).toHaveLength(fixtureRepositoryTotal); expect(expanded.summary.repositoryView).toEqual({ limit: null, total: fixtureRepositoryTotal, shown: fixtureRepositoryTotal, omitted: 0, }); expect(expanded.target.repositories).toHaveLength(spec.gitMirror.repositories.length); expect(expanded.target.repositoryView).toEqual({ limit: null, total: spec.gitMirror.repositories.length, shown: spec.gitMirror.repositories.length, omitted: 0, }); expect(expanded.probe.stdoutTailOmitted).toBe(!options.raw); expect(expanded.probe.stdoutTail).toBe(options.raw ? JSON.stringify(summary) : undefined); expect(expanded.disclosure.probeTailOmitted).toBe(!options.raw); } }); test("keeps legacy main-repository fields and bounds per-repository probes", () => { const spec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec; const script = yamlLaneGitMirrorStatusScript(spec); expect(script).toContain("'repository': os.environ.get('REPOSITORY')"); expect(script).toContain("'sourceCommit': legacy_ref("); expect(script).toContain("'gitopsCommit': legacy_ref("); expect(script.match(/timeout 20 kubectl/gu)?.length).toBe(spec.gitMirror.repositories.length); expect(script.match(/timeout 20 kubectl[^\n]+ &/gu)?.length).toBe(spec.gitMirror.repositories.length); expect(script).toContain("remoteFingerprintAligned"); }); }); function git(args: string[]): string { const result = Bun.spawnSync(["git", ...args], { stdout: "pipe", stderr: "pipe" }); if (result.exitCode !== 0) throw new Error(`git ${args[0]} failed: ${result.stderr.toString()}`); return result.stdout.toString().trim(); } function sha256(value: string): string { return createHash("sha256").update(value).digest("hex"); } function writeControllerConfig(path: string, input: { cache: string; tokenPath: string; askPassFile: string }): void { const remote = "https://github.com/acme/example.git"; const repository = { key: "fixture", repository: "acme/example", remote, sourceBranch: "main", desiredFingerprint: sha256(["fixture", "acme/example", remote, "main"].join("\0")), }; const desired = { schemaVersion: 1, kind: "AgentRunManagedRepositoryReconciler", nodeId: "fixture-node", lane: "fixture-lane", cacheMountPath: input.cache, stateDirectory: ".managed-state", reconcileIntervalMs: 1000, fetchTimeoutMs: 10000, shutdownGraceMs: 1000, maxConcurrentRepositories: 1, retry: { maxAttempts: 1, initialDelayMs: 10, maxDelayMs: 10 }, freshness: { maxAgeMs: 60000 }, lifecycle: { undeclaredRepositoryPolicy: "retain", managedRefs: "source-branch-only" }, repositories: [repository], remoteAuth: { configRef: "config/platform-infra/gitea.yaml#sourceAuthority.credentials.github.gitFetchCredential", capabilitySha256: "a".repeat(64), authMode: "github-https-token", host: "github.com", tokenFile: input.tokenPath, askPassFile: input.askPassFile, proxy: { host: "127.0.0.1", port: 10808 }, }, }; writeFileSync(path, `${JSON.stringify({ ...desired, desiredHash: sha256(JSON.stringify(desired)) }, null, 2)}\n`); } function lastJsonLine(output: string): any { const lines = output.trim().split("\n"); return JSON.parse(lines.at(-1) ?? "null"); } function inheritedHostileGitEnvironment(fakeBin: string, fixtureToken: string): NodeJS.ProcessEnv { return { ...process.env, PATH: `${fakeBin}:${process.env.PATH ?? ""}`, GIT_SSH: "/tmp/inherited-git-ssh", GIT_SSH_COMMAND: "inherited-ssh-command", GIT_CONFIG: "/tmp/inherited-git-config", GIT_CONFIG_COUNT: "1", GIT_CONFIG_KEY_0: "credential.helper", GIT_CONFIG_VALUE_0: "!inherited-credential-helper", GIT_SSL_NO_VERIFY: "1", GH_TOKEN: fixtureToken, GITHUB_TOKEN: fixtureToken, }; } function writeGitShim(input: { path: string; realGit: string; observationPath: string; remoteUrl: string; replacementRemoteUrl: string; failFetchMessage?: string; }): void { writeFileSync(input.path, `#!/usr/bin/env node import { appendFileSync } from "node:fs"; import { spawnSync } from "node:child_process"; const args = process.argv.slice(2); appendFileSync(${JSON.stringify(input.observationPath)}, JSON.stringify({ args, inheritedGitSsh: Object.hasOwn(process.env, "GIT_SSH") || Object.hasOwn(process.env, "GIT_SSH_COMMAND"), inheritedGitConfig: Object.hasOwn(process.env, "GIT_CONFIG") || Object.hasOwn(process.env, "GIT_CONFIG_COUNT") || Object.keys(process.env).some((key) => /^GIT_CONFIG_(?:KEY|VALUE)_/u.test(key)), inheritedGithubToken: Object.hasOwn(process.env, "GH_TOKEN") || Object.hasOwn(process.env, "GITHUB_TOKEN"), askPassConfigured: typeof process.env.GIT_ASKPASS === "string" && process.env.GIT_ASKPASS.length > 0 && process.env.GIT_ASKPASS_REQUIRE === "force", tlsVerifyForced: process.env.GIT_SSL_NO_VERIFY === "0" && args.includes("http.sslVerify=true"), }) + "\\n"); if (args.includes("fetch") && ${JSON.stringify(input.failFetchMessage ?? null)} !== null) { process.stderr.write(${JSON.stringify(input.failFetchMessage ?? "")} + "\\n"); process.exit(1); } const mapped = args.map((arg) => arg === ${JSON.stringify(input.remoteUrl)} ? ${JSON.stringify(input.replacementRemoteUrl)} : arg); const result = spawnSync(${JSON.stringify(input.realGit)}, mapped, { env: process.env, stdio: "inherit" }); process.exit(result.status ?? 1); `); chmodSync(input.path, 0o755); }