mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-06 08:07:53 +02:00
test(land): composition + scrub guard, coverage, postfail relocation, touchfiles
- gen-skill-docs: assert land-and-deploy composes {{INVOKE_SKILL:land}} and
/land carries no deploy/canary machinery (H9 generated-doc scrub)
- relocate the PR #1620 post-failure invariant test to /land (where the
merge now lives), preserving every pinned invariant
- register /land in the skill coverage matrix
- link land/**, bin/gstack-merge, lib/merge.ts into the land-and-deploy and
setup-deploy E2E touchfiles so the composition path re-runs on change
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,31 +2,30 @@
|
||||
* Coverage for PR #1620 — Post-failure PR-state check after `gh pr merge`
|
||||
* non-zero exit.
|
||||
*
|
||||
* The fix lives in land-and-deploy/SKILL.md.tmpl as Step §4a-postfail.
|
||||
* After ANY non-zero `gh pr merge`, the skill must query authoritative PR
|
||||
* state via `gh pr view --json state,mergeCommit,mergedAt,mergedBy` and
|
||||
* branch on the result instead of retrying `gh pr merge` (cli/cli#3442,
|
||||
* cli/cli#13380).
|
||||
* The merge step (and this invariant) moved out of /land-and-deploy into the
|
||||
* extracted /land skill (§4.2a). After ANY non-zero `gh pr merge`, the skill
|
||||
* must query authoritative PR state via
|
||||
* `gh pr view --json state,mergeCommit,mergedAt,mergedBy` and branch on the
|
||||
* result instead of retrying `gh pr merge` (cli/cli#3442, cli/cli#13380).
|
||||
*
|
||||
* Static invariants pin:
|
||||
* - §4a-postfail header present
|
||||
* Static invariants pin (now in /land):
|
||||
* - §4.2a Post-failure PR-state check header present
|
||||
* - Universal invariant text + reference to upstream gh bugs
|
||||
* - All three state branches (MERGED, OPEN, CLOSED) named explicitly
|
||||
* - MERGED branch: capture merge SHA via mergeCommit.oid
|
||||
* - MERGED branch: non-destructive worktree cleanup with uncommitted-work guard
|
||||
* - MERGED branch: continues to §4a CI watch
|
||||
* - OPEN branch: checks autoMergeRequest before treating as failure
|
||||
* - CLOSED branch: STOPs
|
||||
* - Hard rule: never retry `gh pr merge`
|
||||
* - .tmpl edit propagated to generated SKILL.md (atomic per T-Codex-3)
|
||||
* - .tmpl edit propagated to generated SKILL.md (atomic regen)
|
||||
*/
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
|
||||
const ROOT = path.resolve(import.meta.dir, "..");
|
||||
const TMPL = path.join(ROOT, "land-and-deploy", "SKILL.md.tmpl");
|
||||
const MD = path.join(ROOT, "land-and-deploy", "SKILL.md");
|
||||
const TMPL = path.join(ROOT, "land", "SKILL.md.tmpl");
|
||||
const MD = path.join(ROOT, "land", "SKILL.md");
|
||||
|
||||
function readTmpl(): string {
|
||||
return fs.readFileSync(TMPL, "utf-8");
|
||||
@@ -35,18 +34,18 @@ function readMd(): string {
|
||||
return fs.readFileSync(MD, "utf-8");
|
||||
}
|
||||
|
||||
describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
|
||||
test("§4a-postfail header present in template", () => {
|
||||
expect(readTmpl()).toMatch(/### 4a-postfail: Post-failure PR-state check/);
|
||||
describe("PR #1620 post-failure PR-state check in /land template", () => {
|
||||
test("post-failure header present in template", () => {
|
||||
expect(readTmpl()).toMatch(/### 4\.2a: Post-failure PR-state check/);
|
||||
});
|
||||
|
||||
test("§4a-postfail comes before §4a (Merge queue detection)", () => {
|
||||
test("post-failure check comes before the wait step", () => {
|
||||
const body = readTmpl();
|
||||
const postfail = body.indexOf("### 4a-postfail:");
|
||||
const queue = body.indexOf("### 4a: Merge queue detection");
|
||||
const postfail = body.indexOf("### 4.2a: Post-failure PR-state check");
|
||||
const wait = body.indexOf("### 4.3: Wait for it to land");
|
||||
expect(postfail).toBeGreaterThan(-1);
|
||||
expect(queue).toBeGreaterThan(-1);
|
||||
expect(postfail).toBeLessThan(queue);
|
||||
expect(wait).toBeGreaterThan(-1);
|
||||
expect(postfail).toBeLessThan(wait);
|
||||
});
|
||||
|
||||
test("Universal invariant + upstream gh bug references", () => {
|
||||
@@ -82,11 +81,6 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
|
||||
expect(body).toMatch(/Do NOT remove the user's primary working tree/);
|
||||
});
|
||||
|
||||
test("MERGED branch continues to §4a CI auto-deploy detection", () => {
|
||||
const body = readTmpl();
|
||||
expect(body).toMatch(/continue to §4a/);
|
||||
});
|
||||
|
||||
test("OPEN branch checks autoMergeRequest before treating as failure", () => {
|
||||
const body = readTmpl();
|
||||
expect(body).toMatch(/gh pr view --json autoMergeRequest/);
|
||||
@@ -103,9 +97,9 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
|
||||
expect(body).toMatch(/never call `gh pr merge` a second time/);
|
||||
});
|
||||
|
||||
test("Generated SKILL.md carries the §4a-postfail section (atomic regen per T-Codex-3)", () => {
|
||||
test("Generated SKILL.md carries the post-failure section (atomic regen)", () => {
|
||||
const md = readMd();
|
||||
expect(md).toMatch(/### 4a-postfail: Post-failure PR-state check/);
|
||||
expect(md).toMatch(/### 4\.2a: Post-failure PR-state check/);
|
||||
expect(md).toMatch(/state == "MERGED"/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user