diff --git a/CHANGELOG.md b/CHANGELOG.md index e38ab0f9..9ab09057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add support for `symfony/options-resolver:^8.0` * Add support for `visibility` in `Groups::all` * Add support for personal access tokens +* Add support for project integrations endpoints * Add support for `job_inputs` and `job_variables_attributes` in `Jobs::play` * Add support for filters in `Projects::projectAccessTokens` * Add support for `Projects::rotateProjectAccessToken` diff --git a/src/Api/Integrations.php b/src/Api/Integrations.php new file mode 100644 index 00000000..ec3f3d3a --- /dev/null +++ b/src/Api/Integrations.php @@ -0,0 +1,47 @@ + + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gitlab\Api; + +class Integrations extends AbstractApi +{ + public function all(int|string $project_id): mixed + { + return $this->get($this->getProjectPath($project_id, 'integrations')); + } + + public function show(int|string $project_id, string $integration_slug): mixed + { + return $this->get($this->getProjectPath($project_id, 'integrations/'.self::encodePath($integration_slug))); + } + + /** + * Configure a project integration by slug. + * + * Integration parameters vary by slug and are passed through to GitLab. + * + * @see https://docs.gitlab.com/api/project_integrations/ + * + * @param array $parameters + */ + public function set(int|string $project_id, string $integration_slug, array $parameters = []): mixed + { + return $this->put($this->getProjectPath($project_id, 'integrations/'.self::encodePath($integration_slug)), $parameters); + } + + public function remove(int|string $project_id, string $integration_slug): mixed + { + return $this->delete($this->getProjectPath($project_id, 'integrations/'.self::encodePath($integration_slug))); + } +} diff --git a/src/Client.php b/src/Client.php index dfdc02d7..bcca7dbd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -22,6 +22,7 @@ use Gitlab\Api\GroupsBoards; use Gitlab\Api\GroupsEpics; use Gitlab\Api\GroupsMilestones; +use Gitlab\Api\Integrations; use Gitlab\Api\IssueBoards; use Gitlab\Api\IssueLinks; use Gitlab\Api\Issues; @@ -172,6 +173,11 @@ public function groupsMilestones(): GroupsMilestones return new GroupsMilestones($this); } + public function integrations(): Integrations + { + return new Integrations($this); + } + public function issueBoards(): IssueBoards { return new IssueBoards($this); diff --git a/tests/Api/IntegrationsTest.php b/tests/Api/IntegrationsTest.php new file mode 100644 index 00000000..7a5e66ba --- /dev/null +++ b/tests/Api/IntegrationsTest.php @@ -0,0 +1,119 @@ + + * (c) Graham Campbell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gitlab\Tests\Api; + +use Gitlab\Api\Integrations; +use PHPUnit\Framework\Attributes\Test; + +class IntegrationsTest extends TestCase +{ + #[Test] + public function shouldGetAllIntegrations(): void + { + $expectedArray = [ + ['id' => 75, 'title' => 'Jenkins CI', 'slug' => 'jenkins'], + ['id' => 76, 'title' => 'Alerts endpoint', 'slug' => 'alerts'], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/integrations') + ->willReturn($expectedArray) + ; + + $this->assertEquals($expectedArray, $api->all(1)); + } + + #[Test] + public function shouldShowIntegration(): void + { + $expectedArray = [ + 'id' => 1, + 'title' => 'Jira', + 'slug' => 'jira', + 'active' => true, + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/integrations/jira') + ->willReturn($expectedArray) + ; + + $this->assertEquals($expectedArray, $api->show(1, 'jira')); + } + + #[Test] + public function shouldSetIntegration(): void + { + $expectedArray = [ + 'id' => 2, + 'title' => 'Microsoft Teams notifications', + 'slug' => 'microsoft-teams', + 'active' => true, + ]; + $parameters = [ + 'webhook' => 'https://example.com/webhook', + 'push_events' => true, + 'branches_to_be_notified' => 'default', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/integrations/microsoft-teams', $parameters) + ->willReturn($expectedArray) + ; + + $this->assertEquals($expectedArray, $api->set(1, 'microsoft-teams', $parameters)); + } + + #[Test] + public function shouldRemoveIntegration(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/integrations/microsoft-teams') + ->willReturn($expectedBool) + ; + + $this->assertEquals($expectedBool, $api->remove(1, 'microsoft-teams')); + } + + #[Test] + public function shouldEncodeProjectPathAndIntegrationSlug(): void + { + $expectedArray = ['slug' => 'custom/integration']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/group%2Fproject/integrations/custom%2Fintegration') + ->willReturn($expectedArray) + ; + + $this->assertEquals($expectedArray, $api->show('group/project', 'custom/integration')); + } + + protected function getApiClass(): string + { + return Integrations::class; + } +}