From e5dda3b3e16d6340f02e68362a4c3fb37330d5b2 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 14 Aug 2026 19:32:36 -0700 Subject: [PATCH] fix(land-and-deploy,gen): auto-merge diagnosis + CRLF-stable generation Two small hardenings: land-and-deploy Step 4 no longer misdiagnoses a failed `gh pr merge --auto` as a permissions problem when the real cause is the merge-method mismatch the command names; and gen-skill-docs normalizes CRLF at the template entry point so Windows checkouts with autocrlf produce byte-identical generated output to CI instead of silently skipping the \n-anchored transforms. Contributed by @Jmeg8r (PR #2437) and @1ncludeSteven (PR #1051). Co-Authored-By: Claude Fable 5 --- land-and-deploy/SKILL.md | 16 ++++++++++++++-- land-and-deploy/SKILL.md.tmpl | 16 ++++++++++++++-- scripts/gen-skill-docs.ts | 7 ++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/land-and-deploy/SKILL.md b/land-and-deploy/SKILL.md index 74fa527cd..7c781b98e 100644 --- a/land-and-deploy/SKILL.md +++ b/land-and-deploy/SKILL.md @@ -1479,13 +1479,25 @@ Record the start timestamp for timing data. Also record which merge path is take Try auto-merge first (respects repo merge settings and merge queues): ```bash -gh pr merge --auto --delete-branch +gh pr merge --squash --auto --delete-branch ``` If `--auto` succeeds: record `MERGE_PATH=auto`. This means the repo has auto-merge enabled and may use merge queues. -If `--auto` is not available (repo doesn't have auto-merge enabled), merge directly: +`--auto` fails for two unrelated reasons. Both fall through to the direct merge below, so +the flow is unaffected — but do not report the second one as "auto-merge is disabled": + +1. **Auto-merge is disabled for the repo** — `Auto-merge is not allowed for this repository`. +2. **The PR is not waiting on anything.** `--auto` only *queues* a merge behind pending + required checks. When every required check has already settled — or the repo declares + no required status checks at all — GitHub treats the PR as immediately mergeable and + rejects the mutation: + `Pull request is in clean status` (everything green) or + `Pull request is in unstable status` (something red, but nothing required). + A repo with zero required status checks therefore takes the direct path 100% of the + time no matter how auto-merge is configured, and so does any repo whose CI finishes + before this step runs. ```bash gh pr merge --squash --delete-branch diff --git a/land-and-deploy/SKILL.md.tmpl b/land-and-deploy/SKILL.md.tmpl index 98976ad02..78c3cffc2 100644 --- a/land-and-deploy/SKILL.md.tmpl +++ b/land-and-deploy/SKILL.md.tmpl @@ -598,13 +598,25 @@ Record the start timestamp for timing data. Also record which merge path is take Try auto-merge first (respects repo merge settings and merge queues): ```bash -gh pr merge --auto --delete-branch +gh pr merge --squash --auto --delete-branch ``` If `--auto` succeeds: record `MERGE_PATH=auto`. This means the repo has auto-merge enabled and may use merge queues. -If `--auto` is not available (repo doesn't have auto-merge enabled), merge directly: +`--auto` fails for two unrelated reasons. Both fall through to the direct merge below, so +the flow is unaffected — but do not report the second one as "auto-merge is disabled": + +1. **Auto-merge is disabled for the repo** — `Auto-merge is not allowed for this repository`. +2. **The PR is not waiting on anything.** `--auto` only *queues* a merge behind pending + required checks. When every required check has already settled — or the repo declares + no required status checks at all — GitHub treats the PR as immediately mergeable and + rejects the mutation: + `Pull request is in clean status` (everything green) or + `Pull request is in unstable status` (something red, but nothing required). + A repo with zero required status checks therefore takes the direct path 100% of the + time no matter how auto-merge is configured, and so does any repo whose CI finishes + before this step runs. ```bash gh pr merge --squash --delete-branch diff --git a/scripts/gen-skill-docs.ts b/scripts/gen-skill-docs.ts index 6d70206cd..a19833b44 100644 --- a/scripts/gen-skill-docs.ts +++ b/scripts/gen-skill-docs.ts @@ -806,7 +806,12 @@ function processExternalHost( } function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath: string; content: string; symlinkLoop?: boolean; catalogParts?: CatalogParts | null } { - const tmplContent = fs.readFileSync(tmplPath, 'utf-8'); + // Normalize to LF at the entry point. Templates may have CRLF on disk when + // checked out on Windows with core.autocrlf=true. Downstream regexes + // (processVoiceTriggers, transformFrontmatter) hardcode \n, so without + // normalization they silently no-op on CRLF — producing different output + // than CI (Linux, LF) and breaking the Skill Docs Freshness check. + const tmplContent = fs.readFileSync(tmplPath, 'utf-8').replace(/\r\n/g, '\n'); const relTmplPath = path.relative(ROOT, tmplPath); let outputPath = tmplPath.replace(/\.tmpl$/, '');