Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/guest-guided-build/test_guided_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def load(name,path):
rt=load('reader_test_helpers',HERE.parent/'guest-reader-build'/'test_provenance.py') # inert ELF/Bun-layout/git fixtures only
elf,standalone_pair,git_commit,put=rt.elf,rt.standalone_pair,rt.git_commit,rt.put
REPO=HERE.parents[1]
WORKFLOW=REPO/'.github/workflows/cowork-guided-packet-compile-fixture.yml'
WORKFLOW=REPO/'.github/retired-workflows/cowork-guided-packet-compile-fixture.yml'
GUEST='packages/runtime/src/guest/'

class Fixture(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion scripts/guest-reader-native/test_fixture_stderr.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def test_hosted_export_has_no_production_import_route_or_raw_log(self):
root=Path(__file__).resolve().parents[2]
for source in (root/'src').rglob('*.ts'):
self.assertNotIn('guest-reader-native/wrapper',source.read_text())
workflow=(root/'.github/workflows/cowork-reader-native-reviewed.yml').read_text()
workflow=(root/'.github/retired-workflows/cowork-reader-native-reviewed.yml').read_text()
self.assertEqual(workflow.count('module.log_result_projection(result)'),2)
self.assertNotIn('print(json.dumps(result,sort_keys=True))',workflow)

Expand Down
4 changes: 2 additions & 2 deletions scripts/guest-reader-native/test_report_family.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ def test_the_compile_pin_acquisition_and_intake_pins_agree_across_every_module(s
self.assertIn(needle, download)

def test_workflow_and_gate_pins_name_the_actual_bootstrap_and_wrapper(self):
workflow = (ROOT / '.github/workflows/cowork-reader-native-reviewed.yml').read_text()
workflow = (ROOT / '.github/retired-workflows/cowork-reader-native-reviewed.yml').read_text()
gate = (ROOT / 'test/gates/release-gates.test.ts').read_text()
bootstrap, wrapper = self.digest('bootstrap.py'), self.digest('wrapper.py')
self.assertEqual(workflow.count(bootstrap), 4); self.assertEqual(workflow.count(wrapper), 1)
Expand All @@ -950,7 +950,7 @@ def test_workflow_and_gate_pins_name_the_actual_bootstrap_and_wrapper(self):
self.assertEqual(workflow.count(download), 1); self.assertEqual(gate.count('"' + download + '"'), 1)

def test_origins_base_is_a_commit_that_carries_exactly_the_files_the_bootstrap_pins(self):
workflow = (ROOT / '.github/workflows/cowork-reader-native-reviewed.yml').read_text()
workflow = (ROOT / '.github/retired-workflows/cowork-reader-native-reviewed.yml').read_text()
gate = (ROOT / 'test/gates/release-gates.test.ts').read_text()
ref = re.search(r"ref: ([0-9a-f]{40})\n\s+path: origins/base", workflow).group(1)
self.assertEqual(gate.count('{ ref: "' + ref + '", path: "origins/base"'), 1)
Expand Down
9 changes: 5 additions & 4 deletions test/gates/guided-packet-compile-gates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const ALLOWED_ACTIONS = new Set(["actions/checkout", "actions/upload-artifact"])
const USED_BRANCHES = ["cowork/instruction-reader-compile-fixture", "cowork/reader-hosted-dependency-probe", "cowork/reader-hosted-fixture-stderr", "cowork/guided-packet-build", "cowork/guided-packet-compile-fixture", "cowork/guided-packet-compile-fixture-2", "cowork/guided-packet-compile-fixture-3", "cowork/guided-packet-compile-fixture-4"];
const ZERO_HEAD = "0".repeat(40);
const BUN_URL = "https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-linux-aarch64.zip";
const WORKFLOW_PATH = ".github/workflows/cowork-guided-packet-compile-fixture.yml";
const WORKFLOW_PATH = ".github/workflows/cowork-guided-packet-compile-fixture.yml"; // the path the RETIRED file had: the arming guard text inside it still names it

/** The arming guard, line for line. It runs before any builder code is checked out and refuses unless BUILDER_HEAD is an
* ancestor of the pushed commit AND the whole difference is the one BUILDER_HEAD line of this workflow. */
const GUARD: Array<[string, string]> = [
Expand Down Expand Up @@ -292,7 +293,7 @@ describe("the runtime-sdk origin's tree is its head's real tree", () => {
});

describe("guided packet compile-fixture workflow gates", () => {
const WORKFLOW = read(`.github/workflows/${WORKFLOW_NAME}`);
const WORKFLOW = read(`.github/retired-workflows/${WORKFLOW_NAME}`);

test("the committed workflow satisfies every gate", () => {
expect(violations(WORKFLOW)).toEqual([]);
Expand Down Expand Up @@ -464,7 +465,7 @@ const MUTATIONS: Array<[string, (text: string) => string, string]> = [

// A mutation is only evidence if it changed the text and was caught by the violation it names.
describe("guided packet compile-fixture workflow gate mutations", () => {
const WORKFLOW = read(`.github/workflows/${WORKFLOW_NAME}`);
const WORKFLOW = read(`.github/retired-workflows/${WORKFLOW_NAME}`);
const ctx = loadContext();
test("the table has one entry per gate it claims and no duplicate names", () => {
expect(new Set(MUTATIONS.map(([name]) => name)).size).toBe(MUTATIONS.length);
Expand Down Expand Up @@ -502,7 +503,7 @@ describe("guided packet compile-fixture workflow gate mutations", () => {

// The guard is run for real, as bash, against throwaway Git repositories: each way an arming commit can be wrong must fail.
describe("arming guard behaviour (runs the workflow's own guard script against temporary repositories)", () => {
const doc = yaml.parse(read(`.github/workflows/${WORKFLOW_NAME}`)) as Doc;
const doc = yaml.parse(read(`.github/retired-workflows/${WORKFLOW_NAME}`)) as Doc;
const script = (Object.values(doc.jobs ?? {})[0]?.steps ?? [])[1]?.run ?? "";
const workflow = (head: string, extra = "") => `name: x\nenv:\n BUILDER_HEAD: '${head}'\n OTHER: 1\n${extra}`;
function git(cwd: string, ...args: string[]): string {
Expand Down
6 changes: 4 additions & 2 deletions test/gates/guided-packet-pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,24 @@ const RUN5_ORIGINS: Record<string, { repository: string; head: string; tree: str
...RUN4_ORIGINS,
runtime: { repository: "yanlingLabs/winter-runtime-sdk", head: "2b170ab0a0cd3d137b620b1a30dc0ea9502e1822", tree: "e507b5e54046c75a0deb77662c14f446fda81c1c" },
};
/** Builder files changed AFTER run 39399991186: its test reads the compile workflow from the retired-workflows directory now. History for run 5's pin only. */
export const RUN5_SUPERSEDED_BUILDER_FILES = [`${BUILD}/test_guided_build.py`] as const;
interface RunSpec { branch: string; artifactId: number; origins: Record<string, { repository: string; head: string; tree: string }>; placeholders: string[]; superseded: readonly string[] }
/** The runs this directory pins, by run id. A pin whose run id is not here is refused. */
const RUNS: Record<number, RunSpec> = {
39165162201: { branch: "cowork/guided-packet-compile-fixture", artifactId: 12149668717, origins: RUN1_ORIGINS, placeholders: PLACEHOLDERS, superseded: SUPERSEDED_BUILDER_FILES },
39227365159: { branch: "cowork/guided-packet-compile-fixture-2", artifactId: 12174387240, origins: RUN2_ORIGINS, placeholders: [], superseded: RUN2_HISTORY_BUILDER_FILES },
39327386044: { branch: "cowork/guided-packet-compile-fixture-3", artifactId: 12223150881, origins: RUN3_ORIGINS, placeholders: [], superseded: RUN3_SUPERSEDED_BUILDER_FILES },
39391435225: { branch: "cowork/guided-packet-compile-fixture-4", artifactId: 12249582986, origins: RUN4_ORIGINS, placeholders: [], superseded: RUN4_SUPERSEDED_BUILDER_FILES },
39399991186: { branch: "cowork/guided-packet-compile-fixture-5", artifactId: 12254327073, origins: RUN5_ORIGINS, placeholders: [], superseded: [] },
39399991186: { branch: "cowork/guided-packet-compile-fixture-5", artifactId: 12254327073, origins: RUN5_ORIGINS, placeholders: [], superseded: RUN5_SUPERSEDED_BUILDER_FILES },
};

export function pinFiles(): string[] {
return readdirSync(join(ROOT, INTAKE)).filter((name) => /^compile-\d+\.pin\.json$/.test(name));
}
export function loadContext(): Context {
const inputs = JSON.parse(read(`${BUILD}/guided-compile-inputs.pin.json`)) as Inputs;
return { inputs, dependencyListSha256: sha256(`${BUILD}/dependencies.lst`), pinsPy: read(`${BUILD}/pins.py`), workflow: read(".github/workflows/cowork-guided-packet-compile-fixture.yml"), limits: inputs.limits,
return { inputs, dependencyListSha256: sha256(`${BUILD}/dependencies.lst`), pinsPy: read(`${BUILD}/pins.py`), workflow: read(".github/retired-workflows/cowork-guided-packet-compile-fixture.yml"), limits: inputs.limits,
files: (path) => (existsSync(join(ROOT, path)) ? sha256(path) : null) };
}

Expand Down
7 changes: 4 additions & 3 deletions test/gates/release-gates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
// guard, and the absence of any committed Anthropic artifact (this repository's own hard rule).
import { describe, expect, test } from "bun:test";
import { execFileSync } from "node:child_process";
import { readdirSync, readFileSync } from "node:fs";
import { existsSync, readdirSync, readFileSync } from "node:fs";
import { join, resolve } from "node:path";

const REPO_ROOT = resolve(import.meta.dir, "..", "..");
const WORKFLOW_DIR = join(REPO_ROOT, ".github", "workflows");

const readWorkflow = (name: string): string => readFileSync(join(WORKFLOW_DIR, name), "utf8");
const RETIRED_DIR = join(REPO_ROOT, ".github", "retired-workflows"); // spent one-run workflows: inert records, never run by GitHub
const readWorkflow = (name: string): string => readFileSync(join(existsSync(join(WORKFLOW_DIR, name)) ? WORKFLOW_DIR : RETIRED_DIR, name), "utf8");

/**
* The parsed workflow. `Bun.YAML.parse` is the structural reading (review r1, M6): the text slice
Expand Down Expand Up @@ -71,7 +72,7 @@ describe("the release workflow", () => {

test("the publish steps are gated behind that workflow and nowhere else", () => {
const workflows = readdirSync(WORKFLOW_DIR).sort();
expect(workflows).toEqual(["ci.yml", "cowork-guided-build-source.yml", "cowork-guided-packet-compile-fixture.yml", "cowork-reader-abi-source.yml", "cowork-reader-build-source.yml", "cowork-reader-compile-fixture.yml", "cowork-reader-intake-source.yml", "cowork-reader-native-reviewed.yml", "cowork-reader-native-source.yml", "release.yml"]);
expect(workflows).toEqual(["ci.yml", "cowork-guided-build-source.yml", "cowork-reader-abi-source.yml", "cowork-reader-build-source.yml", "cowork-reader-intake-source.yml", "cowork-reader-native-source.yml", "release.yml"]);
for (const name of workflows.filter((name) => name !== "release.yml")) {
const source = readWorkflow(name);
// Non-release workflows may explain this rule in comments, but cannot run publication.
Expand Down
51 changes: 51 additions & 0 deletions test/gates/retired-workflows.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// The spent one-run workflows are RETIRED: moved out of `.github/workflows/` (GitHub runs nothing outside it) into `.github/retired-workflows/`, where the gate tests
// and the pin tests still read them as inert records (the guided compile pins hash the workflow's env; the reader gates assert its reviewed shape).
//
// Why moved and not edited to "disabled": each fired on the FIRST CREATION of a named branch (or a push to one with matching paths). Those branches now exist and are
// frozen, but deleting and recreating a name would fire a live file again, and an `if: false` edit is one revert from live. A file outside the workflows directory cannot run.
//
// Kept live: ci.yml, release.yml and the five `*-source` workflows (portable source tests on named branches; they arm and run nothing privileged).
import { describe, expect, test } from "bun:test";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { join, resolve } from "node:path";

const ROOT = resolve(import.meta.dir, "..", "..");
export const RETIRED = ["cowork-guided-packet-compile-fixture.yml", "cowork-reader-compile-fixture.yml", "cowork-reader-native-reviewed.yml"] as const;
export const LIVE = ["ci.yml", "cowork-guided-build-source.yml", "cowork-reader-abi-source.yml", "cowork-reader-build-source.yml", "cowork-reader-intake-source.yml", "cowork-reader-native-source.yml", "release.yml"] as const;
/** First-creation branches of the retired one-run workflows. All exist and are frozen. */
export const SPENT_BRANCHES = [
"cowork/guided-packet-compile-fixture", "cowork/guided-packet-compile-fixture-2", "cowork/guided-packet-compile-fixture-3", "cowork/guided-packet-compile-fixture-4",
"cowork/guided-packet-compile-fixture-5", "cowork/instruction-reader-compile-fixture",
] as const;

/** Pure: the violations of a listing of the live workflows directory (name -> text). */
export function violations(files: Record<string, string>): string[] {
const found: string[] = [];
for (const name of Object.keys(files).sort()) {
if ((RETIRED as readonly string[]).includes(name)) found.push(`retired workflow is back: ${name}`);
else if (!(LIVE as readonly string[]).includes(name)) found.push(`workflow is not on the allow-list: ${name}`);
for (const branch of SPENT_BRANCHES) if (new RegExp(`${branch.replace(/[/.]/g, "\\$&")}(?![\\w-])`).test(files[name]!)) found.push(`${name} names a spent branch: ${branch}`);
}
return found;
}
const live = (): Record<string, string> => Object.fromEntries(readdirSync(join(ROOT, ".github/workflows")).filter((name) => /\.ya?ml$/.test(name)).map((name) => [name, readFileSync(join(ROOT, ".github/workflows", name), "utf8")]));

describe("retired workflows stay out of .github/workflows", () => {
test("the retired files are records under .github/retired-workflows, not workflows", () => {
for (const name of RETIRED) {
expect(existsSync(join(ROOT, ".github/workflows", name))).toBe(false);
expect(existsSync(join(ROOT, ".github/retired-workflows", name))).toBe(true);
}
});
test("the live workflows are exactly the allow-list and name no spent branch", () => {
expect(violations(live())).toEqual([]);
expect(Object.keys(live()).sort()).toEqual([...LIVE].sort());
});
test("the pure check flags a returned file, a new workflow and a spent branch name (mutations)", () => {
const base = live();
expect(violations({ ...base, "cowork-guided-packet-compile-fixture.yml": "on: push" })).toEqual(["retired workflow is back: cowork-guided-packet-compile-fixture.yml"]);
expect(violations({ ...base, "one-run.yml": "on: push" })).toEqual(["workflow is not on the allow-list: one-run.yml"]);
expect(violations({ ...base, "ci.yml": `${base["ci.yml"]}\n# branches: [cowork/guided-packet-compile-fixture-5]` })).toEqual(["ci.yml names a spent branch: cowork/guided-packet-compile-fixture-5"]);
expect(violations({ ...base, "ci.yml": `${base["ci.yml"]}\n# cowork/guided-packet-compile-fixture-6` })).toEqual([]);
});
});
Loading