From 4a7dea48ca1a0ae93013ad0d0bd505849716ce1e Mon Sep 17 00:00:00 2001 From: nrs <38722970+nrslib@users.noreply.github.com> Date: Sun, 22 Feb 2026 21:52:40 +0900 Subject: [PATCH] takt: tasuku-taktga-surupull-request (#336) --- src/__tests__/postExecution.test.ts | 57 +++++++++++++++++++++ src/features/pipeline/steps.ts | 2 +- src/features/tasks/execute/postExecution.ts | 6 ++- src/infra/task/summarize.ts | 5 +- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/__tests__/postExecution.test.ts b/src/__tests__/postExecution.test.ts index 284c0bb..dbb5718 100644 --- a/src/__tests__/postExecution.test.ts +++ b/src/__tests__/postExecution.test.ts @@ -173,6 +173,63 @@ describe('postExecutionFlow', () => { expect(result.prFailed).toBeUndefined(); expect(result.prUrl).toBe('https://github.com/org/repo/pull/1'); }); + + it('issues が渡された場合、PRタイトルにIssue番号プレフィックスが付与される', async () => { + mockFindExistingPr.mockReturnValue(undefined); + + await postExecutionFlow({ + ...baseOptions, + task: 'Fix the bug', + issues: [{ number: 123, title: 'This title should not appear in PR', body: '', labels: [], comments: 0 }], + }); + + expect(mockCreatePullRequest).toHaveBeenCalledWith( + '/project', + expect.objectContaining({ title: '[#123] Fix the bug' }), + ); + }); + + it('issues が空配列の場合、PRタイトルにプレフィックスは付与されない', async () => { + mockFindExistingPr.mockReturnValue(undefined); + + await postExecutionFlow({ + ...baseOptions, + issues: [], + }); + + expect(mockCreatePullRequest).toHaveBeenCalledWith( + '/project', + expect.objectContaining({ title: 'Fix the bug' }), + ); + }); + + it('issues が undefined の場合、PRタイトルにプレフィックスは付与されない', async () => { + mockFindExistingPr.mockReturnValue(undefined); + + await postExecutionFlow(baseOptions); + + expect(mockCreatePullRequest).toHaveBeenCalledWith( + '/project', + expect.objectContaining({ title: 'Fix the bug' }), + ); + }); + + it('Issueプレフィックス付きタイトルが100文字を超える場合、適切に省略される', async () => { + mockFindExistingPr.mockReturnValue(undefined); + const longTask = 'A'.repeat(120); + const expectedTitle = `[#123] ${'A'.repeat(90)}...`; + + await postExecutionFlow({ + ...baseOptions, + task: longTask, + issues: [{ number: 123, title: 'Long issue', body: '', labels: [], comments: 0 }], + }); + + expect(mockCreatePullRequest).toHaveBeenCalledWith( + '/project', + expect.objectContaining({ title: expectedTitle }), + ); + }); }); describe('resolveDraftPr', () => { diff --git a/src/features/pipeline/steps.ts b/src/features/pipeline/steps.ts index 48c23c0..bdf02a4 100644 --- a/src/features/pipeline/steps.ts +++ b/src/features/pipeline/steps.ts @@ -211,7 +211,7 @@ export function submitPullRequest( options: Pick, ): string | undefined { info('Creating pull request...'); - const prTitle = taskContent.issue ? taskContent.issue.title : (options.task ?? 'Pipeline task'); + const prTitle = taskContent.issue ? `[#${taskContent.issue.number}] ${taskContent.issue.title}` : (options.task ?? 'Pipeline task'); const report = `Piece \`${piece}\` completed successfully.`; const prBody = buildPipelinePrBody(pipelineConfig, taskContent.issue, report); diff --git a/src/features/tasks/execute/postExecution.ts b/src/features/tasks/execute/postExecution.ts index fbc03b5..00f99ed 100644 --- a/src/features/tasks/execute/postExecution.ts +++ b/src/features/tasks/execute/postExecution.ts @@ -103,9 +103,13 @@ export async function postExecutionFlow(options: PostExecutionOptions): Promise< } else { info('Creating pull request...'); const prBody = buildPrBody(issues, report); + const firstIssue = issues?.[0]; + const issuePrefix = firstIssue ? `[#${firstIssue.number}] ` : ''; + const truncatedTask = task.length > 100 - issuePrefix.length ? `${task.slice(0, 100 - issuePrefix.length - 3)}...` : task; + const prTitle = issuePrefix + truncatedTask; const prResult = createPullRequest(projectCwd, { branch, - title: task.length > 100 ? `${task.slice(0, 97)}...` : task, + title: prTitle, body: prBody, base: baseBranch, repo, diff --git a/src/infra/task/summarize.ts b/src/infra/task/summarize.ts index 01f53c9..17ba84f 100644 --- a/src/infra/task/summarize.ts +++ b/src/infra/task/summarize.ts @@ -29,9 +29,8 @@ function toRomajiSafely(text: string): string { ); } return convertedChunks.join(''); - } catch { - // Avoid blocking branch/task creation on rare parser edge cases or deep recursion - // with very long mixed/ASCII inputs. + } catch (err) { + log.error('Failed to convert to romaji', { error: err, textLength: text.length }); return text; } }