diff --git a/scripts/resolvers/preamble.ts b/scripts/resolvers/preamble.ts index 1fdfed1d..83d3ded6 100644 --- a/scripts/resolvers/preamble.ts +++ b/scripts/resolvers/preamble.ts @@ -222,14 +222,22 @@ Use AskUserQuestion: git log --format="%an (%ae)" -1 -- \`\`\` If these are different people, prefer the production code author — they likely introduced the regression. -- Create a GitHub issue assigned to that person: - \`\`\`bash - gh issue create \\ - --title "Pre-existing test failure: " \\ - --body "Found failing on branch . Failure is pre-existing.\\n\\n**Error:**\\n\`\`\`\\n\\n\`\`\`\\n\\n**Last modified by:** \\n**Noticed by:** gstack /ship on " \\ - --assignee "" - \`\`\` -- If \`gh\` is not available or \`--assignee\` fails (user not in org, etc.), create the issue without assignee and note who should look at it in the body. +- Create an issue assigned to that person (use the platform detected in Step 0): + - **If GitHub:** + \`\`\`bash + gh issue create \\ + --title "Pre-existing test failure: " \\ + --body "Found failing on branch . Failure is pre-existing.\\n\\n**Error:**\\n\`\`\`\\n\\n\`\`\`\\n\\n**Last modified by:** \\n**Noticed by:** gstack /ship on " \\ + --assignee "" + \`\`\` + - **If GitLab:** + \`\`\`bash + glab issue create \\ + -t "Pre-existing test failure: " \\ + -d "Found failing on branch . Failure is pre-existing.\\n\\n**Error:**\\n\`\`\`\\n\\n\`\`\`\\n\\n**Last modified by:** \\n**Noticed by:** gstack /ship on " \\ + -a "" + \`\`\` +- If neither CLI is available or \`--assignee\`/\`-a\` fails (user not in org, etc.), create the issue without assignee and note who should look at it in the body. - Continue with the workflow. **If "Skip":** diff --git a/scripts/resolvers/utility.ts b/scripts/resolvers/utility.ts index 03e72e21..6cd912f2 100644 --- a/scripts/resolvers/utility.ts +++ b/scripts/resolvers/utility.ts @@ -9,22 +9,42 @@ export function generateSlugSetup(ctx: TemplateContext): string { } export function generateBaseBranchDetect(_ctx: TemplateContext): string { - return `## Step 0: Detect base branch + return `## Step 0: Detect platform and base branch -Determine which branch this PR targets. Use the result as "the base branch" in all subsequent steps. +First, detect the git hosting platform from the remote URL: -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. +\`\`\`bash +git remote get-url origin 2>/dev/null +\`\`\` -2. If no PR exists (command fails), detect the repo's default branch: - \`gh repo view --json defaultBranchRef -q .defaultBranchRef.name\` +- If the URL contains "github.com" → platform is **GitHub** +- If the URL contains "gitlab" → platform is **GitLab** +- Otherwise, check CLI availability: + - \`gh auth status 2>/dev/null\` succeeds → platform is **GitHub** (covers GitHub Enterprise) + - \`glab auth status 2>/dev/null\` succeeds → platform is **GitLab** (covers self-hosted) + - Neither → **unknown** (use git-native commands only) -3. If both commands fail, fall back to \`main\`. +Determine which branch this PR/MR targets, or the repo's default branch if no +PR/MR exists. Use the result as "the base branch" in all subsequent steps. + +**If GitHub:** +1. \`gh pr view --json baseRefName -q .baseRefName\` — if succeeds, use it +2. \`gh repo view --json defaultBranchRef -q .defaultBranchRef.name\` — if succeeds, use it + +**If GitLab:** +1. \`glab mr view -F json 2>/dev/null\` and extract the \`target_branch\` field — if succeeds, use it +2. \`glab repo view -F json 2>/dev/null\` and extract the \`default_branch\` field — if succeeds, use it + +**Git-native fallback (if unknown platform, or CLI commands fail):** +1. \`git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'\` +2. If that fails: \`git rev-parse --verify origin/main 2>/dev/null\` → use \`main\` +3. If that fails: \`git rev-parse --verify origin/master 2>/dev/null\` → use \`master\` + +If all 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." +\`git fetch\`, \`git merge\`, and PR/MR creation command, substitute the detected +branch name wherever the instructions say "the base branch" or \`\`. ---`; } diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index d0da767a..e600b90e 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -333,6 +333,39 @@ describe('BASE_BRANCH_DETECT resolver', () => { test('resolver output uses "the base branch" phrasing', () => { expect(shipContent).toContain('the base branch'); }); + + test('resolver output contains GitLab CLI commands', () => { + expect(shipContent).toContain('glab'); + }); + + test('resolver output contains git-native fallback', () => { + expect(shipContent).toContain('git symbolic-ref'); + }); + + test('resolver output mentions GitLab platform', () => { + expect(shipContent).toMatch(/gitlab/i); + }); +}); + +describe('GitLab support in generated skills', () => { + const retroContent = fs.readFileSync(path.join(ROOT, 'retro', 'SKILL.md'), 'utf-8'); + const shipSkillContent = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md'), 'utf-8'); + + test('retro contains GitLab MR number extraction', () => { + expect(retroContent).toContain('[#!]'); + }); + + test('retro uses BASE_BRANCH_DETECT (contains glab)', () => { + expect(retroContent).toContain('glab'); + }); + + test('ship contains glab mr create', () => { + expect(shipSkillContent).toContain('glab mr create'); + }); + + test('ship checks .gitlab-ci.yml', () => { + expect(shipSkillContent).toContain('.gitlab-ci.yml'); + }); }); /**