Skip to content
Draft
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
9 changes: 5 additions & 4 deletions src/workflows/repo-config-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,18 @@ describe("RepoConfigWorkflow dispatch — happy path", () => {
});

describe("RepoConfigWorkflow dispatch — file absent", () => {
test("present=false → early return, no DO write, complete", async () => {
test("present=false → skips parse, still writes empty settings, complete", async () => {
const instanceId = "config_push-repo-missing-delivery-2";
await using instance = await introspectWorkflowInstance(
env.REPO_CONFIG_WORKFLOW,
instanceId,
);
await instance.modify(async (m) => {
await m.mockStepResult({ name: "fetch-config-file" }, { present: false });
// parse-and-validate / store-repo-config intentionally NOT mocked — if
// the workflow tried to run them unmocked it would fail, exposing a
// regression in the early-exit branch.
// parse-and-validate intentionally NOT mocked — if the workflow tried
// to run it when the file is absent, the unmocked step would fail and
// expose a regression in the skip-parse branch.
await m.mockStepResult({ name: "store-repo-config" }, { ok: true });
});
await env.REPO_CONFIG_WORKFLOW.create({ id: instanceId, params: base });
await expect(instance.waitForStatus("complete")).resolves.not.toThrow();
Expand Down
18 changes: 13 additions & 5 deletions src/workflows/steps/sync-repo-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe("runSyncRepoConfig", () => {
});
});

test("file absent — only runs fetch-config-file and makes no DO writes", async () => {
test("file absent — skips parse-and-validate and writes empty settings to DO", async () => {
const { step, calls } = makeStep();
const { REPO_CONFIG_DO, idFromName, get, setRepoConfig } = makeDO();
const github = {
Expand All @@ -127,10 +127,18 @@ describe("runSyncRepoConfig", () => {
logger: noopLogger,
});

expect(calls.map((c) => c.name)).toEqual(["fetch-config-file"]);
expect(idFromName).not.toHaveBeenCalled();
expect(get).not.toHaveBeenCalled();
expect(setRepoConfig).not.toHaveBeenCalled();
expect(calls.map((c) => c.name)).toEqual([
"fetch-config-file",
"store-repo-config",
]);
expect(idFromName).toHaveBeenCalledWith("acme/repo");
expect(get).toHaveBeenCalledTimes(1);
expect(setRepoConfig).toHaveBeenCalledWith({
repositoryId: 42,
repositoryFullName: "acme/repo",
installationId: 100,
settings: {},
});
});

test("TOML syntax invalid — parse-and-validate throws; store-repo-config not invoked", async () => {
Expand Down
28 changes: 16 additions & 12 deletions src/workflows/steps/sync-repo-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,34 @@ export async function runSyncRepoConfig(
return { present: true as const, contentBase64: res.contentBase64 };
});

if (!fileResult.present) {
logger.info("No repo config file present; skipping DO write", {
let settings: StoredRepoConfig["settings"];
if (fileResult.present) {
const parseResult = await step.do("parse-and-validate", async () => {
const raw = Buffer.from(fileResult.contentBase64, "base64").toString(
"utf8",
);
return { settings: parseRepoConfigToml(raw) };
});
settings = parseResult.settings;
} else {
// No config file at head SHA: persist empty settings so downstream
// `getRepoConfig()` returns a defaulted `RepoConfig` instead of `null`,
// which would otherwise push the task onto the legacy template path.
logger.info("No repo config file present; storing empty settings", {
fullName,
sha: event.head.sha,
});
return;
settings = {};
}

const parseResult = await step.do("parse-and-validate", async () => {
const raw = Buffer.from(fileResult.contentBase64, "base64").toString(
"utf8",
);
const settings = parseRepoConfigToml(raw);
return { settings };
});

await step.do("store-repo-config", async () => {
const id = env.REPO_CONFIG_DO.idFromName(fullName);
const stub = env.REPO_CONFIG_DO.get(id);
const cfg: StoredRepoConfig = {
repositoryId,
repositoryFullName: fullName,
installationId,
settings: parseResult.settings,
settings,
};
await stub.setRepoConfig(cfg);
return { ok: true as const };
Expand Down
Loading