diff --git a/packages/codev/scripts/forge/github/pr-search.sh b/packages/codev/scripts/forge/github/pr-search.sh index cbb84cc5c8..edc2736d96 100755 --- a/packages/codev/scripts/forge/github/pr-search.sh +++ b/packages/codev/scripts/forge/github/pr-search.sh @@ -2,4 +2,6 @@ # Forge concept: pr-search (GitHub via gh CLI) # Input: CODEV_SEARCH_QUERY # Output: JSON [{number, headRefName, baseRefName}] -exec gh pr list --search "$CODEV_SEARCH_QUERY" --json number,headRefName,baseRefName +# --state all is required so the search includes merged/closed PRs; without it +# `gh pr list` defaults to --state open and post-merge lookups return nothing (#759). +exec gh pr list --state all --search "$CODEV_SEARCH_QUERY" --json number,headRefName,baseRefName diff --git a/packages/codev/scripts/forge/gitlab/pr-search.sh b/packages/codev/scripts/forge/gitlab/pr-search.sh index 67e29a96b4..8da4306c9d 100755 --- a/packages/codev/scripts/forge/gitlab/pr-search.sh +++ b/packages/codev/scripts/forge/gitlab/pr-search.sh @@ -1,3 +1,5 @@ #!/bin/sh # Forge concept: pr-search (GitLab via glab CLI) -exec glab mr list --search "$CODEV_SEARCH_QUERY" --output json +# --all is required so the search includes merged/closed MRs; without it +# `glab mr list` defaults to opened only and post-merge lookups return nothing (#759). +exec glab mr list --all --search "$CODEV_SEARCH_QUERY" --output json diff --git a/packages/codev/src/commands/porch/__tests__/bugfix-759-pr-search-state-all.test.ts b/packages/codev/src/commands/porch/__tests__/bugfix-759-pr-search-state-all.test.ts new file mode 100644 index 0000000000..bcbf11e32f --- /dev/null +++ b/packages/codev/src/commands/porch/__tests__/bugfix-759-pr-search-state-all.test.ts @@ -0,0 +1,54 @@ +/** + * Regression test for pr-search forge scripts. + * + * Bugfix #759: pr-search must include all PR states so post-merge lookups + * (consult --type pr after a PR merges) still find the PR. Without it, + * `gh pr list --search` / `glab mr list --search` default to open-only and + * return nothing once the PR has merged. + * + * These tests validate the forge scripts directly, not protocol.json commands. + */ + +import { describe, it, expect } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +const SCRIPTS_ROOT = path.resolve(__dirname, '../../../../scripts/forge'); + +describe('pr-search forge scripts', () => { + describe('github/pr-search.sh', () => { + const scriptPath = path.join(SCRIPTS_ROOT, 'github', 'pr-search.sh'); + + it('exists and is readable', () => { + expect(fs.existsSync(scriptPath)).toBe(true); + }); + + it('fetches all PR states (--state all) so merged PRs are found (#759)', () => { + const content = fs.readFileSync(scriptPath, 'utf-8'); + expect(content).toContain('--state all'); + }); + + it('still searches with the provided query', () => { + const content = fs.readFileSync(scriptPath, 'utf-8'); + expect(content).toContain('--search "$CODEV_SEARCH_QUERY"'); + }); + }); + + describe('gitlab/pr-search.sh', () => { + const scriptPath = path.join(SCRIPTS_ROOT, 'gitlab', 'pr-search.sh'); + + it('exists and is readable', () => { + expect(fs.existsSync(scriptPath)).toBe(true); + }); + + it('fetches all MR states (--all) so merged MRs are found (#759)', () => { + const content = fs.readFileSync(scriptPath, 'utf-8'); + expect(content).toContain('--all'); + }); + + it('still searches with the provided query', () => { + const content = fs.readFileSync(scriptPath, 'utf-8'); + expect(content).toContain('--search "$CODEV_SEARCH_QUERY"'); + }); + }); +});