From 7882713a459930e5a61f8d9e646aceff2a3bc93d Mon Sep 17 00:00:00 2001 From: Xenira <1288524+Xenira@users.noreply.github.com> Date: Wed, 14 Jan 2026 16:22:10 +0100 Subject: [PATCH] feat(api): add job token api Added endpoints as described in https://docs.gitlab.com/api/project_job_token_scopes --- src/Api/Projects.php | 76 +++++++++++++++++++++++ tests/Api/ProjectsTest.php | 124 +++++++++++++++++++++++++++++++++++++ tests/Api/TestCase.php | 2 +- 3 files changed, 201 insertions(+), 1 deletion(-) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index 32aa168a..9ae14353 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -1280,4 +1280,80 @@ public function search(int|string $id, array $parameters = []): mixed return $this->get('projects/'.self::encodePath($id).'/search', $resolver->resolve($parameters)); } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-access-settings + */ + public function jobTokenScope(int|string $project_id): mixed + { + return $this->get($this->getProjectPath($project_id, 'job_token_scope')); + } + + /** + * @param bool $enabled Restricts job token access to allowlisted projects only. Set to false to allow access from all projects. This parameter can be overridden by the Enforce job token allowlist instance setting. + * + * @see https://docs.gitlab.com/api/project_job_token_scopes/#patch-a-projects-cicd-job-token-access-settings + */ + public function setJobTokenAllowListEnabled(int|string $project_id, bool $enabled): mixed + { + return $this->patch($this->getProjectPath($project_id, 'job_token_scope'), ['enabled' => $enabled]); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-inbound-allowlist + */ + public function jobTokenAllowList(int|string $project_id): mixed + { + return $this->get($this->getProjectPath($project_id, 'job_token_scope/allowlist')); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#add-a-project-to-a-cicd-job-token-inbound-allowlist + */ + public function addJobTokenAllowList(int|string $project_id, int $target_project_id): mixed + { + return $this->post( + $this->getProjectPath($project_id, 'job_token_scope/allowlist'), + ['target_project_id' => $target_project_id] + ); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#remove-a-project-from-a-cicd-job-token-inbound-allowlist + */ + public function removeJobTokenAllowList(int|string $project_id, int $target_project_id): mixed + { + return $this->delete( + $this->getProjectPath($project_id, 'job_token_scope/allowlist/'.self::encodePath($target_project_id)) + ); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-allowlist-of-groups + */ + public function jobTokenGroupAllowList(int|string $project_id): mixed + { + return $this->get($this->getProjectPath($project_id, 'job_token_scope/groups_allowlist')); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#add-a-group-to-a-cicd-job-token-allowlist + */ + public function addJobTokenGroupAllowList(int|string $project_id, int $target_group_id): mixed + { + return $this->post( + $this->getProjectPath($project_id, 'job_token_scope/groups_allowlist'), + ['target_group_id' => $target_group_id] + ); + } + + /** + * @see https://docs.gitlab.com/api/project_job_token_scopes/#remove-a-group-from-a-cicd-job-token-allowlist + */ + public function removeJobTokenGroupAllowList(int|string $project_id, int $target_group_id): mixed + { + return $this->delete( + $this->getProjectPath($project_id, 'job_token_scope/groups_allowlist/'.self::encodePath($target_group_id)) + ); + } } diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index 62b5dfcc..9669f379 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -2765,4 +2765,128 @@ public function shouldSearchGroups(): void 'sort' => 'desc', ])); } + + #[Test] + public function shouldGetJobTokenSettings(): void + { + $expectedArray = ['inbound_enabled' => true, 'outbound_enabled' => false]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/job_token_scope') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->jobTokenScope(1)); + } + + #[Test] + public function shouldUpdateJobTokenSettings(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('patch') + ->with('projects/1/job_token_scope', ['enabled' => false]) + ->willReturn($expectedBool); + + $this->assertEquals($expectedBool, $api->setJobTokenAllowListEnabled(1, false)); + } + + #[Test] + public function shouldGetJobTokenAllowList(): void + { + $expectedArray = [[ + 'id' => 1, + ]]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/job_token_scope/allowlist') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->jobTokenAllowList(1)); + } + + #[Test] + public function shouldAddToJobTokenAllowList(): void + { + $expectedArray = [ + 'source_project_id' => 1, + 'target_project_id' => 42, + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/job_token_scope/allowlist', ['target_project_id' => 42]) + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->addJobTokenAllowList(1, 42)); + } + + #[Test] + public function shouldRemoveToJobTokenAllowList(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/job_token_scope/allowlist/42') + ->willReturn($expectedBool); + + $this->assertEquals($expectedBool, $api->removeJobTokenAllowList(1, 42)); + } + + #[Test] + public function shouldGetJobTokenGroupAllowList(): void + { + $expectedArray = [[ + 'id' => 1, + 'name' => 'my-group', + 'web_url' => 'https://gitlab.example.com/groups/my-group', + ]]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/job_token_scope/groups_allowlist') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->jobTokenGroupAllowList(1)); + } + + #[Test] + public function shouldAddToJobTokenGroupsAllowList(): void + { + $expectedArray = [ + 'source_project_id' => 1, + 'target_group_id' => 42, + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/job_token_scope/groups_allowlist', ['target_group_id' => 42]) + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->addJobTokenGroupAllowList(1, 42)); + } + + #[Test] + public function shouldRemoveToJobTokenGroupsAllowList(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/job_token_scope/groups_allowlist/42') + ->willReturn($expectedBool); + + $this->assertEquals($expectedBool, $api->removeJobTokenGroupAllowList(1, 42)); + } } diff --git a/tests/Api/TestCase.php b/tests/Api/TestCase.php index 34f192c6..6b080746 100644 --- a/tests/Api/TestCase.php +++ b/tests/Api/TestCase.php @@ -35,7 +35,7 @@ protected function getApiMock(array $methods = []): MockObject $client = Client::createWithHttpClient($httpClient); return $this->getMockBuilder($this->getApiClass()) - ->onlyMethods(\array_merge(['getAsResponse', 'get', 'post', 'delete', 'put'], $methods)) + ->onlyMethods(\array_merge(['getAsResponse', 'get', 'post', 'delete', 'put', 'patch'], $methods)) ->setConstructorArgs([$client, null]) ->getMock(); }