fix: classify transient GitHub connectivity

Merge PR #102 after rebasing onto current master and validating focused GitHub transient/Code Queue preflight behavior. GitHub DNS/API failures now classify as retryable github-transient with retry/backoff or keep-fresh-heartbeat-task guidance.
This commit is contained in:
Lyon
2026-05-23 15:49:29 +08:00
committed by GitHub
parent 10bb228df5
commit 55c1b296ff
7 changed files with 292 additions and 14 deletions
+34
View File
@@ -202,6 +202,21 @@ async function startMockGitHub(): Promise<{ baseUrl: string; requests: MockReque
};
}
async function startResetGitHub(): Promise<{ baseUrl: string; close: () => Promise<void> }> {
const server = createServer((req) => {
req.socket.destroy();
});
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
const address = server.address();
assertCondition(typeof address === "object" && address !== null, "reset mock server should expose address");
const port = (address as AddressInfo).port;
assertCondition(typeof port === "number", "reset mock server should expose port");
return {
baseUrl: `http://127.0.0.1:${port}`,
close: () => new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve())),
};
}
function dataOf(response: JsonRecord): JsonRecord {
assertCondition(response.ok === true, "CLI command should succeed", response);
assertCondition(typeof response.data === "object" && response.data !== null && !Array.isArray(response.data), "response data should be object", response);
@@ -383,6 +398,24 @@ export async function runGhCliPrContract(): Promise<JsonRecord> {
await mock.close();
}
const resetMock = await startResetGitHub();
try {
const transient = await runCli(["gh", "auth", "status", "--repo", "pikasTech/unidesk"], {
GH_TOKEN: "contract-token",
UNIDESK_GITHUB_API_URL: resetMock.baseUrl,
});
assertCondition(transient.status !== 0, "GitHub DNS/API transient should fail structurally", transient.json ?? { stdout: transient.stdout });
const transientData = failedDataOf(transient.json ?? {});
assertCondition(transientData.degradedReason === "github-transient", "GitHub DNS/API transient should not be auth-missing or semantic failure", transientData);
assertCondition(transientData.runnerDisposition === "infra-blocked", "GitHub transient should remain infra-blocked", transientData);
const transientDetails = transientData.details as JsonRecord;
assertCondition(transientDetails.retryable === true, "GitHub transient should be retryable", transientDetails);
assertCondition(transientDetails.commanderAction === "retry-backoff-or-keep-running-if-heartbeat-fresh", "GitHub transient should expose bounded commander action", transientDetails);
assertCondition(!transient.stdout.includes("contract-token"), "GitHub transient output must not print token values", { stdout: transient.stdout });
} finally {
await resetMock.close();
}
const title = "contract pr create";
const bodyFile = join(tmpdir(), `unidesk-gh-pr-contract-${process.pid}.md`);
writeFileSync(bodyFile, "Line 1\n`code`\n| a | b |\n", "utf8");
@@ -519,6 +552,7 @@ export async function runGhCliPrContract(): Promise<JsonRecord> {
"pr read/view accept owner/repo#number shorthand and reject conflicting --repo",
"pr read/view --raw is explicit full disclosure",
"pr read normalizes open and merged lifecycle fields from REST",
"GitHub DNS/API transients are retryable and distinct from auth or PR semantic failures",
"pr view closeout metadata fields are accepted and hydrated through GraphQL",
"pr read unsupported fields fail structurally with supported closeout fields listed",
"pr create dry-run exposes planned operation",