diff --git a/src/VCS/Adapter.php b/src/VCS/Adapter.php index 2e9ffa77..823fbe89 100644 --- a/src/VCS/Adapter.php +++ b/src/VCS/Adapter.php @@ -150,6 +150,16 @@ abstract public function getPullRequestFromBranch(string $owner, string $reposit */ abstract public function getPullRequest(string $owner, string $repositoryName, int $pullRequestNumber): array; + /** + * Get files changed in a pull request + * + * @param string $owner Owner name of the repository + * @param string $repositoryName Name of the repository + * @param int $pullRequestNumber The pull request number + * @return array List of files changed in the pull request + */ + abstract public function getPullRequestFiles(string $owner, string $repositoryName, int $pullRequestNumber): array; + /** * Add Comment to Pull Request * diff --git a/src/VCS/Adapter/Git/GitHub.php b/src/VCS/Adapter/Git/GitHub.php index 32afa0aa..b2ae68e0 100644 --- a/src/VCS/Adapter/Git/GitHub.php +++ b/src/VCS/Adapter/Git/GitHub.php @@ -670,6 +670,38 @@ public function getPullRequest(string $owner, string $repositoryName, int $pullR return $response['body'] ?? []; } + /** + * Get files changed in a pull request + * + * @return array List of files changed in the pull request + */ + public function getPullRequestFiles(string $owner, string $repositoryName, int $pullRequestNumber): array + { + $allFiles = []; + $perPage = 30; + $currentPage = 1; + + while (true) { + $url = "/repos/{$owner}/{$repositoryName}/pulls/{$pullRequestNumber}/files"; + + $response = $this->call(self::METHOD_GET, $url, ['Authorization' => "Bearer $this->accessToken"], [ + 'per_page' => $perPage, + 'page' => $currentPage, + ]); + + $files = $response['body'] ?? []; + $allFiles = array_merge($allFiles, $files); + + if (\count($files) < $perPage) { + break; + } + + $currentPage++; + } + + return $allFiles; + } + /** * Get latest opened pull request with specific base branch * @return array diff --git a/src/VCS/Adapter/Git/Gitea.php b/src/VCS/Adapter/Git/Gitea.php index 09488929..2886581b 100644 --- a/src/VCS/Adapter/Git/Gitea.php +++ b/src/VCS/Adapter/Git/Gitea.php @@ -651,6 +651,39 @@ public function getPullRequest(string $owner, string $repositoryName, int $pullR return $response['body'] ?? []; } + /** + * Get files changed in a pull request + * + * @return array List of files changed in the pull request + */ + public function getPullRequestFiles(string $owner, string $repositoryName, int $pullRequestNumber): array + { + $allFiles = []; + $limit = 30; + $maxPages = 100; + + for ($currentPage = 1; $currentPage <= $maxPages; $currentPage++) { + $url = "/repos/{$owner}/{$repositoryName}/pulls/{$pullRequestNumber}/files?page={$currentPage}&limit={$limit}"; + + $response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]); + + $responseHeaders = $response['headers'] ?? []; + $responseHeadersStatusCode = $responseHeaders['status-code'] ?? 0; + if ($responseHeadersStatusCode >= 400) { + throw new Exception("Failed to get pull request files: HTTP {$responseHeadersStatusCode}"); + } + + $files = $response['body'] ?? []; + $allFiles = array_merge($allFiles, $files); + + if (\count($files) < $limit) { + break; + } + } + + return $allFiles; + } + public function getPullRequestFromBranch(string $owner, string $repositoryName, string $branch): array { diff --git a/tests/VCS/Adapter/GitHubTest.php b/tests/VCS/Adapter/GitHubTest.php index cb2c54ba..5d48ae79 100644 --- a/tests/VCS/Adapter/GitHubTest.php +++ b/tests/VCS/Adapter/GitHubTest.php @@ -355,6 +355,21 @@ public function testGetPullRequest(): void $this->assertSame($repositoryName, $result['base']['repo']['name']); } + public function testGetPullRequestFiles(): void + { + $owner = 'vermakhushboo'; + $repositoryName = 'basic-js-crud'; + $pullRequestNumber = 1; + + $result = $this->vcsAdapter->getPullRequestFiles($owner, $repositoryName, $pullRequestNumber); + + $this->assertIsArray($result); + $this->assertNotEmpty($result); + + $filenames = array_column($result, 'filename'); + $this->assertContains('README.md', $filenames); + } + public function testGenerateCloneCommand(): void { \exec('rm -rf /tmp/clone-branch'); diff --git a/tests/VCS/Adapter/GiteaTest.php b/tests/VCS/Adapter/GiteaTest.php index 078e16fd..c10afe4a 100644 --- a/tests/VCS/Adapter/GiteaTest.php +++ b/tests/VCS/Adapter/GiteaTest.php @@ -480,6 +480,37 @@ public function testGetPullRequest(): void $this->vcsAdapter->deleteRepository(static::$owner, $repositoryName); } + public function testGetPullRequestFiles(): void + { + $repositoryName = 'test-get-pull-request-files-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test'); + $this->vcsAdapter->createBranch(self::$owner, $repositoryName, 'feature-branch', static::$defaultBranch); + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'feature.txt', 'feature content', 'Add feature', 'feature-branch'); + + $pr = $this->vcsAdapter->createPullRequest( + self::$owner, + $repositoryName, + 'Test PR Files', + 'feature-branch', + static::$defaultBranch + ); + + $prNumber = $pr['number'] ?? 0; + $this->assertGreaterThan(0, $prNumber); + + $result = $this->vcsAdapter->getPullRequestFiles(self::$owner, $repositoryName, $prNumber); + + $this->assertIsArray($result); + $this->assertNotEmpty($result); + + $filenames = array_column($result, 'filename'); + $this->assertContains('feature.txt', $filenames); + + $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName); + } + public function testGetPullRequestWithInvalidNumber(): void { $repositoryName = 'test-get-pull-request-invalid-' . \uniqid(); diff --git a/tests/VCS/Base.php b/tests/VCS/Base.php index 026da39c..0542fcef 100644 --- a/tests/VCS/Base.php +++ b/tests/VCS/Base.php @@ -32,6 +32,8 @@ abstract public function testGetComment(): void; abstract public function testGetPullRequest(): void; + abstract public function testGetPullRequestFiles(): void; + abstract public function testGetRepositoryTree(): void; /** @return array */