Merge repair/audit-s7-release (S7 release/dogfood)

This commit is contained in:
John Smith
2026-10-10 21:09:51 -04:00
4 changed files with 255 additions and 3 deletions
+59
View File
@@ -0,0 +1,59 @@
// Packaging pin assertions (#212): the opencode triple-pin moves together,
// every release manifest declares an explicit `files` allowlist with no test
// paths, and the `--release` rendering keeps the `<dir> <slug>` contract
// `publish.yml` parses. File reads only: no network, no registry, no pack.
// Structural fixes (a peer range, narrower allowlists, publish parsing,
// the runtime-matrix wording) route to S9 via CROSS-SQUAD REQUEST.
import { describe, expect, test } from "bun:test"
import { readFile } from "node:fs/promises"
import path from "node:path"
import { releasePackages, tarballSlug, workspacePackages } from "../../../scripts/packages.ts"
const root = path.resolve(import.meta.dir, "../../..")
const manifest = async (dir: string) =>
JSON.parse(await readFile(path.join(root, "packages", dir, "package.json"), "utf8")) as Record<string, any>
describe("the opencode triple-pin moves together", () => {
test("@opencode/plugin, @opencode/sdk and the e2e CLI share one version", async () => {
const opencode = await manifest("opencode")
const plugin = opencode.dependencies?.["@opencode/plugin"] as string
const sdk = opencode.devDependencies?.["@opencode/sdk"] as string
expect(plugin).toMatch(/^\d+\.\d+\.\d+$/)
expect(sdk).toBe(plugin)
const e2e = await readFile(path.join(root, ".github/workflows/e2e-feedback.yml"), "utf8")
const cliPins = [...e2e.matchAll(/@opencode\/cli-linux-x64@([0-9A-Za-z._-]+)/g)].map((match) => match[1])
expect(cliPins.length).toBeGreaterThan(0)
expect(new Set(cliPins).size).toBe(1)
expect(cliPins[0]).toBe(plugin)
})
})
describe("release tarball allowlists", () => {
test("every release manifest declares an explicit files allowlist with no test paths", async () => {
for (const pkg of await releasePackages(root)) {
const files = (await manifest(pkg.dir)).files as unknown
expect(Array.isArray(files) && (files as unknown[]).length > 0).toBe(true)
for (const entry of files as string[]) {
expect(typeof entry).toBe("string")
expect(entry).not.toMatch(/test|spec|__tests__/i)
}
}
})
test("fleet and web stay private (never released)", async () => {
const all = await workspacePackages(root)
for (const dir of ["fleet", "web"]) {
expect(all.find((pkg) => pkg.dir === dir)?.private).toBe(true)
}
})
})
describe("the --release rendering contract", () => {
test('every line is "<dir> <slug>" with the slug derived from the manifest name', async () => {
for (const pkg of await releasePackages(root)) {
const line = `${pkg.dir} ${tarballSlug(pkg.name)}`
expect(line).toMatch(/^\S+ \S+$/)
expect(tarballSlug(pkg.name)).not.toContain(" ")
}
})
})
+7 -3
View File
@@ -1,6 +1,10 @@
// Release PR opener backed by the GitHub CLI. It pushes only the run's
// integration branch (never the base branch) and opens a draft PR for a human
// to review and merge.
// Factory release PR opener backed by the GitHub CLI. Every factory push
// path goes through here: it pushes only the run's `factory/` integration
// branch — `branch === base` or a non-`factory/` branch is refused before
// any push — and opens a draft PR for a human to review and merge. (Other
// push paths exist outside the factory: `es improve --open-pr` pushes
// `improve/*` branches on its own human-run path; phase fast-forwards and
// fleet landings never touch the base branch; only a human merges.)
import type { PrOpener } from "@heretek-ai/es-core"
import { buildPrArgs, git, run } from "@heretek-ai/es-core"
+80
View File
@@ -0,0 +1,80 @@
// PR-opener guard (#238): `ghPrOpener.open()` refuses `branch === base`
// and non-`factory/` branches before any git call, and builds the draft-PR
// argv through the shared builder. No network and no `gh` invocation: every
// refusal throws before the push, and the draft shape is asserted on the
// argv (the `gh pr create` spawn itself never runs in tests).
import { describe, expect, test } from "bun:test"
import { mkdtemp, rm } from "node:fs/promises"
import { tmpdir } from "node:os"
import path from "node:path"
import { buildPrArgs } from "@heretek-ai/es-core"
import { ghPrOpener } from "../src/pr.ts"
const open = (root: string, overrides: { branch: string; base?: string; preset?: string } = { branch: "x" }) =>
ghPrOpener.open({
root,
branch: overrides.branch,
base: overrides.base ?? "rewrite",
title: "t",
body: "b",
...(overrides.preset !== undefined ? { preset: overrides.preset } : {}),
})
describe("ghPrOpener.open() branch guard", () => {
test("branch === base is refused", async () => {
const root = await mkdtemp(path.join(tmpdir(), "es-pr-guard-"))
try {
await expect(open(root, { branch: "rewrite", base: "rewrite" })).rejects.toThrow(/refusing to push "rewrite"/)
} finally {
await rm(root, { recursive: true, force: true })
}
})
test("non-factory/ branches are refused", async () => {
const root = await mkdtemp(path.join(tmpdir(), "es-pr-guard-"))
try {
for (const branch of ["main", "feature/x", "improve/20260101", "factory"]) {
await expect(open(root, { branch })).rejects.toThrow(/refusing to push/)
}
} finally {
await rm(root, { recursive: true, force: true })
}
})
test("the refusal precedes any git call (a non-repo root still reports the refusal)", async () => {
// `root` is not a git repository: had the push run first, the failure
// would be git's, not the guard's. The guard's error proves the order
// (`pr.ts` checks the branch before `git push --set-upstream`).
const root = await mkdtemp(path.join(tmpdir(), "es-pr-guard-"))
try {
await open(root, { branch: "main", base: "rewrite" })
expect.unreachable("a non-factory/ branch must be refused")
} catch (error) {
expect((error as Error).message).toMatch(/refusing to push "main"/)
expect((error as Error).message).not.toMatch(/git/i)
} finally {
await rm(root, { recursive: true, force: true })
}
})
test("the branch guard runs before the preset-base guard", async () => {
const root = await mkdtemp(path.join(tmpdir(), "es-pr-guard-"))
try {
await open(root, { branch: "main", base: "main", preset: "self-dogfood" })
expect.unreachable("branch == base must be refused first")
} catch (error) {
expect((error as Error).message).toMatch(/refusing to push "main"/)
} finally {
await rm(root, { recursive: true, force: true })
}
})
})
describe("release PR argv", () => {
test("a factory branch opens a draft PR against the base", () => {
const argv = buildPrArgs({ branch: "factory/run-1/integration", base: "rewrite", title: "t", body: "b" })
expect(argv.slice(0, 4)).toEqual(["gh", "pr", "create", "--draft"])
expect(argv.slice(argv.indexOf("--head") + 1, argv.indexOf("--head") + 2)).toEqual(["factory/run-1/integration"])
expect(argv.slice(argv.indexOf("--base") + 1, argv.indexOf("--base") + 2)).toEqual(["rewrite"])
})
})
+109
View File
@@ -0,0 +1,109 @@
// Release base-branch safety against a local bare remote (#238): the
// factory release pushes a `factory/` branch only, `branch == base` (or a
// non-`factory/` branch) is refused before anything is pushed, and the base
// SHA on the remote is byte-identical afterwards. Local bare-remote fixture
// only (no real remote, no network); `gh` is never invoked — the authorized
// push runs the same `git push --set-upstream origin <branch>:<branch>`
// argv `pr.ts` uses, and the draft shape is asserted on the shared argv.
import { describe, expect, test } from "bun:test"
import { mkdtemp, rm, writeFile } from "node:fs/promises"
import { tmpdir } from "node:os"
import path from "node:path"
import { buildPrArgs, git } from "@heretek-ai/es-core"
import { ghPrOpener } from "../src/pr.ts"
const BASE = "rewrite"
const BRANCH = "factory/run-test-1/integration"
interface Remote {
readonly root: string
readonly remote: string
readonly baseSha: string
cleanup(): Promise<void>
}
/** A repo with a base branch pushed to a local bare remote, plus one factory-branch commit. */
async function bareRemote(): Promise<Remote> {
const root = await mkdtemp(path.join(tmpdir(), "es-release-"))
const remote = await mkdtemp(path.join(tmpdir(), "es-release-remote-"))
const cleanup = async () => {
await rm(root, { recursive: true, force: true })
await rm(remote, { recursive: true, force: true })
}
try {
await git(remote, ["init", "--bare", "-q"])
await git(root, ["init", "-q", "-b", BASE])
await writeFile(path.join(root, "README.md"), "# release fixture\n")
await git(root, ["add", "-A"])
await git(root, ["-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "-m", "init"])
await git(root, ["remote", "add", "origin", remote])
await git(root, ["push", "-q", "-u", "origin", `${BASE}:${BASE}`])
const baseSha = (await git(root, ["rev-parse", BASE])).stdout.trim()
await git(root, ["checkout", "-q", "-b", BRANCH])
await writeFile(path.join(root, "work.txt"), "factory work\n")
await git(root, ["add", "-A"])
await git(root, ["-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "-m", "factory work"])
return { root, remote, baseSha, cleanup }
} catch (error) {
await cleanup()
throw error
}
}
const remoteSha = async (remote: string, ref: string) =>
(await git(remote, ["rev-parse", "--verify", ref])).stdout.trim()
const remoteBranches = async (remote: string) =>
(await git(remote, ["for-each-ref", "--format=%(refname)", "refs/heads/"])).stdout
.split("\n")
.map((line) => line.trim())
.filter(Boolean)
describe("release against a local bare remote", () => {
test("branch == base is refused and the remote is untouched", async () => {
const fx = await bareRemote()
try {
await expect(ghPrOpener.open({ root: fx.root, branch: BASE, base: BASE, title: "t", body: "b" })).rejects.toThrow(
`refusing to push "${BASE}"`,
)
expect(await remoteBranches(fx.remote)).toEqual(["refs/heads/rewrite"])
expect(await remoteSha(fx.remote, "refs/heads/rewrite")).toBe(fx.baseSha)
} finally {
await fx.cleanup()
}
})
test("a non-factory/ branch is refused and the remote is untouched", async () => {
const fx = await bareRemote()
try {
await expect(
ghPrOpener.open({ root: fx.root, branch: "feature/x", base: BASE, title: "t", body: "b" }),
).rejects.toThrow(/refusing to push/)
expect(await remoteBranches(fx.remote)).toEqual(["refs/heads/rewrite"])
expect(await remoteSha(fx.remote, "refs/heads/rewrite")).toBe(fx.baseSha)
} finally {
await fx.cleanup()
}
})
test("the authorized push lands only the factory branch; the base SHA is byte-identical", async () => {
const fx = await bareRemote()
try {
const local = (await git(fx.root, ["rev-parse", BRANCH])).stdout.trim()
// The same argv `pr.ts` pushes with (the `gh pr create` spawn never
// runs in tests: no `gh` invocation here).
await git(fx.root, ["push", "--set-upstream", "origin", `${BRANCH}:${BRANCH}`])
expect(await remoteBranches(fx.remote)).toEqual(
["refs/heads/factory/run-test-1/integration", "refs/heads/rewrite"].sort(),
)
expect(await remoteSha(fx.remote, `refs/heads/${BRANCH}`)).toBe(local)
expect(await remoteSha(fx.remote, "refs/heads/rewrite")).toBe(fx.baseSha)
// The release PR itself is a draft against the base.
const argv = buildPrArgs({ branch: BRANCH, base: BASE, title: "t", body: "b" })
expect(argv.slice(0, 4)).toEqual(["gh", "pr", "create", "--draft"])
expect(argv.slice(argv.indexOf("--base") + 1, argv.indexOf("--base") + 2)).toEqual([BASE])
} finally {
await fx.cleanup()
}
})
})