This commit is contained in:
nrslib 2026-02-09 19:09:37 +09:00
parent fdcce2e425
commit 22908d474c
3 changed files with 72 additions and 36 deletions

View File

@ -11,6 +11,11 @@ export interface TestRepo {
cleanup: () => void; cleanup: () => void;
} }
export interface CreateTestRepoOptions {
/** Skip creating a test branch (stay on default branch). Use for pipeline tests. */
skipBranch?: boolean;
}
function getGitHubUser(): string { function getGitHubUser(): string {
const user = execFileSync('gh', ['api', 'user', '--jq', '.login'], { const user = execFileSync('gh', ['api', 'user', '--jq', '.login'], {
encoding: 'utf-8', encoding: 'utf-8',
@ -33,7 +38,7 @@ function getGitHubUser(): string {
* 2. Close any PRs created during the test * 2. Close any PRs created during the test
* 3. Delete local directory * 3. Delete local directory
*/ */
export function createTestRepo(): TestRepo { export function createTestRepo(options?: CreateTestRepoOptions): TestRepo {
const user = getGitHubUser(); const user = getGitHubUser();
const repoName = `${user}/takt-testing`; const repoName = `${user}/takt-testing`;
@ -56,49 +61,80 @@ export function createTestRepo(): TestRepo {
stdio: 'pipe', stdio: 'pipe',
}); });
// Create test branch // Create test branch (unless skipped for pipeline tests)
const testBranch = `e2e-test-${Date.now()}`; const testBranch = options?.skipBranch
execFileSync('git', ['checkout', '-b', testBranch], { ? undefined
cwd: repoPath, : `e2e-test-${Date.now()}`;
stdio: 'pipe', if (testBranch) {
}); execFileSync('git', ['checkout', '-b', testBranch], {
cwd: repoPath,
stdio: 'pipe',
});
}
const currentBranch = testBranch
?? execFileSync('git', ['branch', '--show-current'], {
cwd: repoPath,
encoding: 'utf-8',
}).trim();
return { return {
path: repoPath, path: repoPath,
repoName, repoName,
branch: testBranch, branch: currentBranch,
cleanup: () => { cleanup: () => {
// 1. Delete remote branch (best-effort) if (testBranch) {
try { // 1. Delete remote branch (best-effort)
execFileSync( try {
'git',
['push', 'origin', '--delete', testBranch],
{ cwd: repoPath, stdio: 'pipe' },
);
} catch {
// Branch may not have been pushed; ignore
}
// 2. Close any PRs from this branch (best-effort)
try {
const prList = execFileSync(
'gh',
['pr', 'list', '--head', testBranch, '--repo', repoName, '--json', 'number', '--jq', '.[].number'],
{ encoding: 'utf-8', stdio: 'pipe' },
).trim();
for (const prNumber of prList.split('\n').filter(Boolean)) {
execFileSync( execFileSync(
'gh', 'git',
['pr', 'close', prNumber, '--repo', repoName, '--delete-branch'], ['push', 'origin', '--delete', testBranch],
{ stdio: 'pipe' }, { cwd: repoPath, stdio: 'pipe' },
); );
} catch {
// Branch may not have been pushed; ignore
}
// 2. Close any PRs from this branch (best-effort)
try {
const prList = execFileSync(
'gh',
['pr', 'list', '--head', testBranch, '--repo', repoName, '--json', 'number', '--jq', '.[].number'],
{ encoding: 'utf-8', stdio: 'pipe' },
).trim();
for (const prNumber of prList.split('\n').filter(Boolean)) {
execFileSync(
'gh',
['pr', 'close', prNumber, '--repo', repoName, '--delete-branch'],
{ stdio: 'pipe' },
);
}
} catch {
// No PRs or already closed; ignore
}
} else {
// Pipeline mode: clean up takt-created PRs (best-effort)
try {
const prNumbers = execFileSync(
'gh',
['pr', 'list', '--state', 'open', '--repo', repoName, '--json', 'number', '--jq', '.[].number'],
{ encoding: 'utf-8', stdio: 'pipe' },
).trim();
for (const prNumber of prNumbers.split('\n').filter(Boolean)) {
execFileSync(
'gh',
['pr', 'close', prNumber, '--repo', repoName, '--delete-branch'],
{ stdio: 'pipe' },
);
}
} catch {
// ignore
} }
} catch {
// No PRs or already closed; ignore
} }
// 3. Delete local directory last // Delete local directory last
try { try {
rmSync(repoPath, { recursive: true, force: true }); rmSync(repoPath, { recursive: true, force: true });
} catch { } catch {

View File

@ -17,7 +17,7 @@ describe('E2E: GitHub Issue processing', () => {
beforeEach(() => { beforeEach(() => {
isolatedEnv = createIsolatedEnv(); isolatedEnv = createIsolatedEnv();
testRepo = createTestRepo(); testRepo = createTestRepo({ skipBranch: true });
// Create a test issue // Create a test issue
const createOutput = execFileSync( const createOutput = execFileSync(

View File

@ -16,7 +16,7 @@ describe('E2E: Pipeline mode (--pipeline --auto-pr)', () => {
beforeEach(() => { beforeEach(() => {
isolatedEnv = createIsolatedEnv(); isolatedEnv = createIsolatedEnv();
testRepo = createTestRepo(); testRepo = createTestRepo({ skipBranch: true });
}); });
afterEach(() => { afterEach(() => {