From 1fe3b0ad323312578e70aae35128b32c6718b77c Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 15 Mar 2026 20:04:48 -0500 Subject: [PATCH] fix: ship skill detects base branch instead of hardcoding main Replaces ~14 hardcoded 'main' references with dynamic detection via {{BASE_BRANCH_DETECT}}. Fixes stacked branches and Conductor workspaces targeting non-main branches. Adds --base to gh pr create. Co-Authored-By: Claude Opus 4.6 (1M context) --- ship/SKILL.md | 49 ++++++++++++++++++++++++++++++++-------------- ship/SKILL.md.tmpl | 32 ++++++++++++++++-------------- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/ship/SKILL.md b/ship/SKILL.md index 386299b9..6fdcb625 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -2,7 +2,7 @@ name: ship version: 1.0.0 description: | - Ship workflow: merge main, run tests, review diff, bump VERSION, update CHANGELOG, commit, push, create PR. + Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION, update CHANGELOG, commit, push, create PR. allowed-tools: - Bash - Read @@ -24,12 +24,31 @@ _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/sk If output shows `UPGRADE_AVAILABLE `: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED `: tell user "Running gstack v{to} (just updated!)" and continue. +## Step 0: Detect base branch + +Determine which branch this PR targets. Use the result as "the base branch" in all subsequent steps. + +1. Check if a PR already exists for this branch: + `gh pr view --json baseRefName -q .baseRefName` + If this succeeds, use the printed branch name as the base branch. + +2. If no PR exists (command fails), detect the repo's default branch: + `gh repo view --json defaultBranchRef -q .defaultBranchRef.name` + +3. If both commands fail, fall back to `main`. + +Print the detected base branch name. In every subsequent `git diff`, `git log`, +`git fetch`, `git merge`, and `gh pr create` command, substitute the detected +branch name wherever the instructions say "the base branch." + +--- + # Ship: Fully Automated Ship Workflow You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end. **Only stop for:** -- On `main` branch (abort) +- On the base branch (abort) - Merge conflicts that can't be auto-resolved (stop, show conflicts) - Test failures (stop, show failures) - Pre-landing review finds CRITICAL issues and user chooses to fix (not acknowledge or skip) @@ -50,20 +69,20 @@ You are running the `/ship` workflow. This is a **non-interactive, fully automat ## Step 1: Pre-flight -1. Check the current branch. If on `main`, **abort**: "You're on main. Ship from a feature branch." +1. Check the current branch. If on the base branch or the repo's default branch, **abort**: "You're on the base branch. Ship from a feature branch." 2. Run `git status` (never use `-uall`). Uncommitted changes are always included — no need to ask. -3. Run `git diff main...HEAD --stat` and `git log main..HEAD --oneline` to understand what's being shipped. +3. Run `git diff ...HEAD --stat` and `git log ..HEAD --oneline` to understand what's being shipped. --- -## Step 2: Merge origin/main (BEFORE tests) +## Step 2: Merge the base branch (BEFORE tests) -Fetch and merge `origin/main` into the feature branch so tests run against the merged state: +Fetch and merge the base branch into the feature branch so tests run against the merged state: ```bash -git fetch origin main && git merge origin/main --no-edit +git fetch origin && git merge origin/ --no-edit ``` **If there are merge conflicts:** Try to auto-resolve if they are simple (VERSION, schema.rb, CHANGELOG ordering). If conflicts are complex or ambiguous, **STOP** and show them. @@ -101,7 +120,7 @@ Evals are mandatory when prompt-related files change. Skip this step entirely if **1. Check if the diff touches prompt-related files:** ```bash -git diff origin/main --name-only +git diff origin/ --name-only ``` Match against these patterns (from CLAUDE.md): @@ -162,7 +181,7 @@ Review the diff for structural issues that tests don't catch. 1. Read `.claude/skills/review/checklist.md`. If the file cannot be read, **STOP** and report the error. -2. Run `git diff origin/main` to get the full diff (scoped to feature changes against the freshly-fetched remote main). +2. Run `git diff origin/` to get the full diff (scoped to feature changes against the freshly-fetched base branch). 3. Apply the review checklist in two passes: - **Pass 1 (CRITICAL):** SQL & Data Safety, LLM Output Trust Boundary @@ -230,7 +249,7 @@ For each classified comment: 1. Read the current `VERSION` file (4-digit format: `MAJOR.MINOR.PATCH.MICRO`) 2. **Auto-decide the bump level based on the diff:** - - Count lines changed (`git diff origin/main...HEAD --stat | tail -1`) + - Count lines changed (`git diff origin/...HEAD --stat | tail -1`) - **MICRO** (4th digit): < 50 lines changed, trivial tweaks, typos, config - **PATCH** (3rd digit): 50+ lines changed, bug fixes, small-medium features - **MINOR** (2nd digit): **ASK the user** — only for major features or significant architectural changes @@ -249,8 +268,8 @@ For each classified comment: 1. Read `CHANGELOG.md` header to know the format. 2. Auto-generate the entry from **ALL commits on the branch** (not just recent ones): - - Use `git log main..HEAD --oneline` to see every commit being shipped - - Use `git diff main...HEAD` to see the full diff against main + - Use `git log ..HEAD --oneline` to see every commit being shipped + - Use `git diff ...HEAD` to see the full diff against the base branch - The CHANGELOG entry must be comprehensive of ALL changes going into the PR - If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version - Categorize changes into applicable sections: @@ -298,8 +317,8 @@ Read TODOS.md and verify it follows the recommended structure: This step is fully automatic — no user interaction. Use the diff and commit history already gathered in earlier steps: -- `git diff main...HEAD` (full diff against main) -- `git log main..HEAD --oneline` (all commits being shipped) +- `git diff ...HEAD` (full diff against the base branch) +- `git log ..HEAD --oneline` (all commits being shipped) For each TODO item, check if the changes in this PR complete it by: - Matching commit messages against the TODO title and description @@ -374,7 +393,7 @@ git push -u origin Create a pull request using `gh`: ```bash -gh pr create --title ": " --body "$(cat <<'EOF' +gh pr create --base --title ": " --body "$(cat <<'EOF' ## Summary diff --git a/ship/SKILL.md.tmpl b/ship/SKILL.md.tmpl index 81bd7e3c..a518066e 100644 --- a/ship/SKILL.md.tmpl +++ b/ship/SKILL.md.tmpl @@ -2,7 +2,7 @@ name: ship version: 1.0.0 description: | - Ship workflow: merge main, run tests, review diff, bump VERSION, update CHANGELOG, commit, push, create PR. + Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION, update CHANGELOG, commit, push, create PR. allowed-tools: - Bash - Read @@ -15,12 +15,14 @@ allowed-tools: {{UPDATE_CHECK}} +{{BASE_BRANCH_DETECT}} + # Ship: Fully Automated Ship Workflow You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end. **Only stop for:** -- On `main` branch (abort) +- On the base branch (abort) - Merge conflicts that can't be auto-resolved (stop, show conflicts) - Test failures (stop, show failures) - Pre-landing review finds CRITICAL issues and user chooses to fix (not acknowledge or skip) @@ -41,20 +43,20 @@ You are running the `/ship` workflow. This is a **non-interactive, fully automat ## Step 1: Pre-flight -1. Check the current branch. If on `main`, **abort**: "You're on main. Ship from a feature branch." +1. Check the current branch. If on the base branch or the repo's default branch, **abort**: "You're on the base branch. Ship from a feature branch." 2. Run `git status` (never use `-uall`). Uncommitted changes are always included — no need to ask. -3. Run `git diff main...HEAD --stat` and `git log main..HEAD --oneline` to understand what's being shipped. +3. Run `git diff ...HEAD --stat` and `git log ..HEAD --oneline` to understand what's being shipped. --- -## Step 2: Merge origin/main (BEFORE tests) +## Step 2: Merge the base branch (BEFORE tests) -Fetch and merge `origin/main` into the feature branch so tests run against the merged state: +Fetch and merge the base branch into the feature branch so tests run against the merged state: ```bash -git fetch origin main && git merge origin/main --no-edit +git fetch origin && git merge origin/ --no-edit ``` **If there are merge conflicts:** Try to auto-resolve if they are simple (VERSION, schema.rb, CHANGELOG ordering). If conflicts are complex or ambiguous, **STOP** and show them. @@ -92,7 +94,7 @@ Evals are mandatory when prompt-related files change. Skip this step entirely if **1. Check if the diff touches prompt-related files:** ```bash -git diff origin/main --name-only +git diff origin/ --name-only ``` Match against these patterns (from CLAUDE.md): @@ -153,7 +155,7 @@ Review the diff for structural issues that tests don't catch. 1. Read `.claude/skills/review/checklist.md`. If the file cannot be read, **STOP** and report the error. -2. Run `git diff origin/main` to get the full diff (scoped to feature changes against the freshly-fetched remote main). +2. Run `git diff origin/` to get the full diff (scoped to feature changes against the freshly-fetched base branch). 3. Apply the review checklist in two passes: - **Pass 1 (CRITICAL):** SQL & Data Safety, LLM Output Trust Boundary @@ -221,7 +223,7 @@ For each classified comment: 1. Read the current `VERSION` file (4-digit format: `MAJOR.MINOR.PATCH.MICRO`) 2. **Auto-decide the bump level based on the diff:** - - Count lines changed (`git diff origin/main...HEAD --stat | tail -1`) + - Count lines changed (`git diff origin/...HEAD --stat | tail -1`) - **MICRO** (4th digit): < 50 lines changed, trivial tweaks, typos, config - **PATCH** (3rd digit): 50+ lines changed, bug fixes, small-medium features - **MINOR** (2nd digit): **ASK the user** — only for major features or significant architectural changes @@ -240,8 +242,8 @@ For each classified comment: 1. Read `CHANGELOG.md` header to know the format. 2. Auto-generate the entry from **ALL commits on the branch** (not just recent ones): - - Use `git log main..HEAD --oneline` to see every commit being shipped - - Use `git diff main...HEAD` to see the full diff against main + - Use `git log ..HEAD --oneline` to see every commit being shipped + - Use `git diff ...HEAD` to see the full diff against the base branch - The CHANGELOG entry must be comprehensive of ALL changes going into the PR - If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version - Categorize changes into applicable sections: @@ -289,8 +291,8 @@ Read TODOS.md and verify it follows the recommended structure: This step is fully automatic — no user interaction. Use the diff and commit history already gathered in earlier steps: -- `git diff main...HEAD` (full diff against main) -- `git log main..HEAD --oneline` (all commits being shipped) +- `git diff ...HEAD` (full diff against the base branch) +- `git log ..HEAD --oneline` (all commits being shipped) For each TODO item, check if the changes in this PR complete it by: - Matching commit messages against the TODO title and description @@ -365,7 +367,7 @@ git push -u origin Create a pull request using `gh`: ```bash -gh pr create --title ": " --body "$(cat <<'EOF' +gh pr create --base --title ": " --body "$(cat <<'EOF' ## Summary