From 1b71cdeabfda776ab10c23958944f67fae34bf16 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Fri, 5 Jul 2024 11:46:56 +0200 Subject: [PATCH 1/6] Implement Container registry API Implement the functions from the Container registry API described in https://docs.gitlab.com/ee/api/container_registry.html --- src/Api/Groups.php | 12 ++++ src/Api/Projects.php | 28 ++++++++ src/Api/Registry.php | 139 +++++++++++++++++++++++++++++++++++++ tests/Api/GroupsTest.php | 20 ++++++ tests/Api/ProjectsTest.php | 41 +++++++++++ tests/Api/RegistryTest.php | 122 ++++++++++++++++++++++++++++++++ 6 files changed, 362 insertions(+) create mode 100644 src/Api/Registry.php create mode 100644 tests/Api/RegistryTest.php diff --git a/src/Api/Groups.php b/src/Api/Groups.php index 5a97e0cf..67975eb0 100644 --- a/src/Api/Groups.php +++ b/src/Api/Groups.php @@ -1031,4 +1031,16 @@ public function search($id, array $parameters = []) return $this->get('groups/'.self::encodePath($id).'/search', $resolver->resolve($parameters)); } + + /** + * Get a list of registry repositories in a group + * @see https://docs.gitlab.com/ee/api/container_registry.html#within-a-group + * + * @param $id: The ID of a group + * @return mixed + */ + public function registryRepositories(int $id) + { + return $this->get('groups/'.self::encodePath($id).'/registry/repositories'); + } } diff --git a/src/Api/Projects.php b/src/Api/Projects.php index 3f5d1962..1178a93e 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -1832,4 +1832,32 @@ public function search($id, array $parameters = []) return $this->get('projects/'.self::encodePath($id).'/search', $resolver->resolve($parameters)); } + + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#within-a-project + * + * @param int|string $project_id + * @param array $parameters { + * @var bool $tags If the parameter is included as true, each repository includes an array of "tags" in the response. + * @var bool $tags_count If the parameter is included as true, each repository includes "tags_count" in the response. + * } + * + * @return mixed + */ + public function registryRepositories($project_id, array $parameters = []) + { + $resolver = $this->createOptionsResolver(); + $booleanNormalizer = function (Options $resolver, $value): string { + return $value ? 'true' : 'false'; + }; + + $resolver->setDefined('tags') + ->setAllowedTypes('tags', 'bool') + ->setNormalizer('tags', $booleanNormalizer); + $resolver->setDefined('tags_count') + ->setAllowedTypes('tags_count', 'bool') + ->setNormalizer('tags_count', $booleanNormalizer); + + return $this->get($this->getProjectPath($project_id, 'registry/repositories'), $resolver->resolve($parameters)); + } } diff --git a/src/Api/Registry.php b/src/Api/Registry.php new file mode 100644 index 00000000..92c65be6 --- /dev/null +++ b/src/Api/Registry.php @@ -0,0 +1,139 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the Gitlab API library. + * + * (c) Matt Humphrey <matth@windsor-telecom.co.uk> + * (c) Graham Campbell <hello@gjcampbell.co.uk> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gitlab\Api; + +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class Registry extends AbstractApi +{ + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-single-repository + * + * @param int|string $repository_id The ID of the registry repository accessible by the authenticated user. + * @param array $parameters { + * @var bool $tags + * @var bool $tags_count + * @var bool $size + * } + * @return mixed + */ + public function repositories($repository_id, array $parameters = []) + { + $resolver = $this->createOptionsResolver(); + $booleanNormalizer = function (Options $resolver, $value): string { + return $value ? 'true' : 'false'; + }; + + $resolver->setDefined('tags') + ->setAllowedTypes('tags', 'bool') + ->setNormalizer('tags', $booleanNormalizer); + $resolver->setDefined('tags_count') + ->setAllowedTypes('tags_count', 'bool') + ->setNormalizer('tags_count', $booleanNormalizer); + $resolver->setDefined('size') + ->setAllowedTypes('size', 'bool') + ->setNormalizer('size', $booleanNormalizer); + + return $this->get('registry/repositories/'.self::encodePath($repository_id), $resolver->resolve($parameters)); + } + + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repository-tags + * + * @param int|string $project_id + * @param int $repository_id + * @return mixed + */ + public function repositoryTags($project_id, int $repository_id) + { + return $this->get( + $this->getProjectPath($project_id, 'registry/repositories/'.self::encodePath($repository_id).'/tags') + ); + } + + + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-registry-repository-tag + * + * @param int|string $project_id + * @param int $repository_id + * @param string $tag_name + * @return mixed + */ + public function repositoryTag($project_id, int $repository_id, string $tag_name) + { + return $this->get( + $this->getProjectPath( + $project_id, + 'registry/repositories/'.self::encodePath($repository_id).'/tags/'.self::encodePath($tag_name) + ) + ); + } + + + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#delete-a-registry-repository-tag + * + * @param int|string $project_id + * @param int $repository_id + * @param string $tag_name + * @return mixed + */ + public function removeRepositoryTag($project_id, int $repository_id, string $tag_name) + { + return $this->delete( + $this->getProjectPath( + $project_id, + 'registry/repositories/'.self::encodePath($repository_id).'/tags/'.self::encodePath($tag_name) + ) + ); + } + + /** + * @see https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository-tags-in-bulk + * + * @param int|string $project_id + * @param int $repository_id + * @param array $parameters { + * @var string $name_regex_delete + * @var string $name_regex_keep + * @var int $keep_n + * @var string $older_than + * } + * @return mixed + */ + public function removeRepositoryTags($project_id, int $repository_id, array $parameters = []) + { + $resolver = $this->createOptionsResolver(); + $resolver->setRequired('name_regex_delete') + ->setAllowedTypes('name_regex_delete', 'string'); + $resolver->setDefined('name_regex_keep') + ->setAllowedTypes('name_regex_keep', 'string'); + $resolver->setDefined('keep_n') + ->setAllowedTypes('keep_n', 'int'); + $resolver->setDefined('older_than') + ->setAllowedTypes('older_than', 'string'); + + + return $this->delete( + $this->getProjectPath( + $project_id, + 'registry/repositories/'.self::encodePath($repository_id).'/tags' + ), + $resolver->resolve($parameters) + ); + } +} \ No newline at end of file diff --git a/tests/Api/GroupsTest.php b/tests/Api/GroupsTest.php index 19209bfd..bd7ad7fb 100644 --- a/tests/Api/GroupsTest.php +++ b/tests/Api/GroupsTest.php @@ -972,4 +972,24 @@ public function shouldSearchGroups(): void 'sort' => 'desc', ])); } + + /** + * @test + */ + public function shouldGetGroupRegistryRepositories(): void + { + $expectedArray = [ + ['id' => 1, 'name' => 'A registry'], + ['id' => 2, 'name' => 'Another registry'], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/registry/repositories') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->registryRepositories(1)); + } } diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index c3296d62..c83c0eda 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -3049,4 +3049,45 @@ public function shouldSearchGroups(): void 'sort' => 'desc', ])); } + + /** + * @test + */ + public function shouldGetProjectRegistryRepositories(): void + { + $expectedArray = [ + ['id' => 1, 'name' => 'A registry'], + ['id' => 2, 'name' => 'Another registry'], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/123/registry/repositories') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->registryRepositories(123)); + } + + /** + * @test + */ + public function shouldGetProjectRegistryRepositoriesTags(): void + { + $expectedArray = [ + ['id' => 1, 'name' => 'A registry', 'tags' => ['1.0', '1.1'], 'tags_count' => 2], + ['id' => 2, 'name' => 'Another registry', 'tags' => ['2.0', '2.1'], 'tags_count' => 2] + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/123/registry/repositories', [ + 'tags' => true, + 'tags_count' => true + ]) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->registryRepositories(123, ['tags' => true, 'tags_count' => true])); + } } diff --git a/tests/Api/RegistryTest.php b/tests/Api/RegistryTest.php new file mode 100644 index 00000000..f6eb2cf2 --- /dev/null +++ b/tests/Api/RegistryTest.php @@ -0,0 +1,122 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the Gitlab API library. + * + * (c) Matt Humphrey <matth@windsor-telecom.co.uk> + * (c) Graham Campbell <hello@gjcampbell.co.uk> + * + * 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\Registry; + +class RegistryTest extends TestCase +{ + protected function getApiClass(): string + { + return Registry::class; + } + + /** + * @test + */ + public function shouldGetSingleRepository(): void + { + $expectedArray = ['id' => 1, 'name' => 'John Doe']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('registry/repositories/1') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->repositories(1)); + } + + /** + * @test + */ + public function shouldGetSingleRepositoryWithParams(): void + { + $expectedArray = ['id' => 1, 'name' => 'John Doe', 'tags' => ['tag1', 'tag2'], 'tags_count' => 2]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('registry/repositories/1', ['tags' => 'true', 'tags_count' => 'true']) + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->repositories(1, ['tags' => true, 'tags_count' => true])); + } + + /** + * @test + */ + public function shouldGetRepositoryTags(): void + { + $expectedArray = [['name' => "A", 'path' => 'group/project:A'], ['name' => "B", 'path' => 'group/project:B']]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/registry/repositories/1/tags') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->repositoryTags(1, 1)); + } + + + /** + * @test + */ + public function shouldGetRepositoryTag(): void + { + $expectedArray = ['name' => "A", 'path' => 'group/project:A']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/registry/repositories/1/tags/A') + ->willReturn($expectedArray); + + $this->assertEquals($expectedArray, $api->repositoryTag(1, 1, 'A')); + } + + /** + * @test + */ + public function shouldRemoveRepositoryTag(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/registry/repositories/1/tags/A') + ->will($this->returnValue($expectedBool)); + + $this->assertEquals($expectedBool, $api->removeRepositoryTag(1, 1, 'A')); + } + + /** + * @test + */ + public function shouldRemoveRepositoryTags(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/registry/repositories/1/tags', ['name_regex_delete' => '.*', 'keep_n' => 12]) + ->will($this->returnValue($expectedBool)); + + $this->assertEquals($expectedBool, $api->removeRepositoryTags(1, 1, ['name_regex_delete' => '.*', 'keep_n' => 12])); + } +} \ No newline at end of file From 8b0c8216981f537f201d1f96faa5e98b2ed98123 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Fri, 5 Jul 2024 11:56:37 +0200 Subject: [PATCH 2/6] Fix StyleCI issues --- src/Api/Groups.php | 3 ++- src/Api/Projects.php | 1 + src/Api/Registry.php | 11 ++++++++--- tests/Api/ProjectsTest.php | 4 ++-- tests/Api/RegistryTest.php | 5 ++--- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Api/Groups.php b/src/Api/Groups.php index 67975eb0..90f387eb 100644 --- a/src/Api/Groups.php +++ b/src/Api/Groups.php @@ -1033,10 +1033,11 @@ public function search($id, array $parameters = []) } /** - * Get a list of registry repositories in a group + * Get a list of registry repositories in a group. * @see https://docs.gitlab.com/ee/api/container_registry.html#within-a-group * * @param $id: The ID of a group + * * @return mixed */ public function registryRepositories(int $id) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index 1178a93e..ae40a6fa 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -1838,6 +1838,7 @@ public function search($id, array $parameters = []) * * @param int|string $project_id * @param array $parameters { + * * @var bool $tags If the parameter is included as true, each repository includes an array of "tags" in the response. * @var bool $tags_count If the parameter is included as true, each repository includes "tags_count" in the response. * } diff --git a/src/Api/Registry.php b/src/Api/Registry.php index 92c65be6..0ebaf47e 100644 --- a/src/Api/Registry.php +++ b/src/Api/Registry.php @@ -15,19 +15,20 @@ namespace Gitlab\Api; use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; class Registry extends AbstractApi { /** * @see https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-single-repository * - * @param int|string $repository_id The ID of the registry repository accessible by the authenticated user. + * @param int|string $repository_id The ID of the registry repository accessible by the authenticated user * @param array $parameters { + * * @var bool $tags * @var bool $tags_count * @var bool $size * } + * * @return mixed */ public function repositories($repository_id, array $parameters = []) @@ -55,6 +56,7 @@ public function repositories($repository_id, array $parameters = []) * * @param int|string $project_id * @param int $repository_id + * * @return mixed */ public function repositoryTags($project_id, int $repository_id) @@ -71,6 +73,7 @@ public function repositoryTags($project_id, int $repository_id) * @param int|string $project_id * @param int $repository_id * @param string $tag_name + * * @return mixed */ public function repositoryTag($project_id, int $repository_id, string $tag_name) @@ -90,6 +93,7 @@ public function repositoryTag($project_id, int $repository_id, string $tag_name) * @param int|string $project_id * @param int $repository_id * @param string $tag_name + * * @return mixed */ public function removeRepositoryTag($project_id, int $repository_id, string $tag_name) @@ -108,11 +112,13 @@ public function removeRepositoryTag($project_id, int $repository_id, string $tag * @param int|string $project_id * @param int $repository_id * @param array $parameters { + * * @var string $name_regex_delete * @var string $name_regex_keep * @var int $keep_n * @var string $older_than * } + * * @return mixed */ public function removeRepositoryTags($project_id, int $repository_id, array $parameters = []) @@ -127,7 +133,6 @@ public function removeRepositoryTags($project_id, int $repository_id, array $par $resolver->setDefined('older_than') ->setAllowedTypes('older_than', 'string'); - return $this->delete( $this->getProjectPath( $project_id, diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index c83c0eda..e66b6fca 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -3076,7 +3076,7 @@ public function shouldGetProjectRegistryRepositoriesTags(): void { $expectedArray = [ ['id' => 1, 'name' => 'A registry', 'tags' => ['1.0', '1.1'], 'tags_count' => 2], - ['id' => 2, 'name' => 'Another registry', 'tags' => ['2.0', '2.1'], 'tags_count' => 2] + ['id' => 2, 'name' => 'Another registry', 'tags' => ['2.0', '2.1'], 'tags_count' => 2], ]; $api = $this->getApiMock(); @@ -3084,7 +3084,7 @@ public function shouldGetProjectRegistryRepositoriesTags(): void ->method('get') ->with('projects/123/registry/repositories', [ 'tags' => true, - 'tags_count' => true + 'tags_count' => true, ]) ->will($this->returnValue($expectedArray)); diff --git a/tests/Api/RegistryTest.php b/tests/Api/RegistryTest.php index f6eb2cf2..70691126 100644 --- a/tests/Api/RegistryTest.php +++ b/tests/Api/RegistryTest.php @@ -60,8 +60,7 @@ public function shouldGetSingleRepositoryWithParams(): void */ public function shouldGetRepositoryTags(): void { - $expectedArray = [['name' => "A", 'path' => 'group/project:A'], ['name' => "B", 'path' => 'group/project:B']]; - + $expectedArray = [['name' => 'A', 'path' => 'group/project:A'], ['name' => 'B', 'path' => 'group/project:B']]; $api = $this->getApiMock(); $api->expects($this->once()) ->method('get') @@ -77,7 +76,7 @@ public function shouldGetRepositoryTags(): void */ public function shouldGetRepositoryTag(): void { - $expectedArray = ['name' => "A", 'path' => 'group/project:A']; + $expectedArray = ['name' => 'A', 'path' => 'group/project:A']; $api = $this->getApiMock(); $api->expects($this->once()) From 326920d52d33c59ab6984feea2ce0878946cc838 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Fri, 5 Jul 2024 12:03:18 +0200 Subject: [PATCH 3/6] Fix StyleCI issues no 2 --- src/Api/Groups.php | 1 + src/Api/Projects.php | 2 +- src/Api/Registry.php | 4 +--- tests/Api/RegistryTest.php | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Api/Groups.php b/src/Api/Groups.php index 90f387eb..e205c173 100644 --- a/src/Api/Groups.php +++ b/src/Api/Groups.php @@ -1034,6 +1034,7 @@ public function search($id, array $parameters = []) /** * Get a list of registry repositories in a group. + * * @see https://docs.gitlab.com/ee/api/container_registry.html#within-a-group * * @param $id: The ID of a group diff --git a/src/Api/Projects.php b/src/Api/Projects.php index ae40a6fa..92b4781c 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -1839,7 +1839,7 @@ public function search($id, array $parameters = []) * @param int|string $project_id * @param array $parameters { * - * @var bool $tags If the parameter is included as true, each repository includes an array of "tags" in the response. + * @var bool $tags if the parameter is included as true, each repository includes an array of "tags" in the response * @var bool $tags_count If the parameter is included as true, each repository includes "tags_count" in the response. * } * diff --git a/src/Api/Registry.php b/src/Api/Registry.php index 0ebaf47e..2d8cc3d6 100644 --- a/src/Api/Registry.php +++ b/src/Api/Registry.php @@ -66,7 +66,6 @@ public function repositoryTags($project_id, int $repository_id) ); } - /** * @see https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-registry-repository-tag * @@ -86,7 +85,6 @@ public function repositoryTag($project_id, int $repository_id, string $tag_name) ); } - /** * @see https://docs.gitlab.com/ee/api/container_registry.html#delete-a-registry-repository-tag * @@ -141,4 +139,4 @@ public function removeRepositoryTags($project_id, int $repository_id, array $par $resolver->resolve($parameters) ); } -} \ No newline at end of file +} diff --git a/tests/Api/RegistryTest.php b/tests/Api/RegistryTest.php index 70691126..7c3ceeb6 100644 --- a/tests/Api/RegistryTest.php +++ b/tests/Api/RegistryTest.php @@ -70,7 +70,6 @@ public function shouldGetRepositoryTags(): void $this->assertEquals($expectedArray, $api->repositoryTags(1, 1)); } - /** * @test */ @@ -118,4 +117,4 @@ public function shouldRemoveRepositoryTags(): void $this->assertEquals($expectedBool, $api->removeRepositoryTags(1, 1, ['name_regex_delete' => '.*', 'keep_n' => 12])); } -} \ No newline at end of file +} From 959265c93117c88a85e1c60bc9a7c198abc645b8 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Fri, 5 Jul 2024 12:16:25 +0200 Subject: [PATCH 4/6] Make Registry() also available via the client... --- src/Client.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Client.php b/src/Client.php index 4082f1ac..dad812a4 100644 --- a/src/Client.php +++ b/src/Client.php @@ -32,6 +32,7 @@ use Gitlab\Api\Milestones; use Gitlab\Api\ProjectNamespaces; use Gitlab\Api\Projects; +use Gitlab\Api\Registry; use Gitlab\Api\Repositories; use Gitlab\Api\RepositoryFiles; use Gitlab\Api\ResourceIterationEvents; @@ -336,6 +337,15 @@ public function projects(): Projects return new Projects($this); } + + /** + * @return Registry + */ + public function registry(): Registry + { + return new Registry($this); + } + /** * @return Repositories */ From f5a1c75ead20e672a6ed3236b0f97f485cc95340 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Fri, 5 Jul 2024 12:17:36 +0200 Subject: [PATCH 5/6] Fix StyleCI issues no 3 --- src/Client.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index dad812a4..dae75dfd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -337,7 +337,6 @@ public function projects(): Projects return new Projects($this); } - /** * @return Registry */ From c64e181760132c15f89087a245b775eb9ebfdee9 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann <philipp@kolmann.at> Date: Mon, 24 Feb 2025 16:30:40 +0100 Subject: [PATCH 6/6] Update Registry.php --- src/Api/Registry.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Api/Registry.php b/src/Api/Registry.php index 2d8cc3d6..5fdc0103 100644 --- a/src/Api/Registry.php +++ b/src/Api/Registry.php @@ -55,7 +55,6 @@ public function repositories($repository_id, array $parameters = []) * @see https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repository-tags * * @param int|string $project_id - * @param int $repository_id * * @return mixed */ @@ -70,8 +69,6 @@ public function repositoryTags($project_id, int $repository_id) * @see https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-registry-repository-tag * * @param int|string $project_id - * @param int $repository_id - * @param string $tag_name * * @return mixed */ @@ -89,8 +86,6 @@ public function repositoryTag($project_id, int $repository_id, string $tag_name) * @see https://docs.gitlab.com/ee/api/container_registry.html#delete-a-registry-repository-tag * * @param int|string $project_id - * @param int $repository_id - * @param string $tag_name * * @return mixed */ @@ -108,7 +103,6 @@ public function removeRepositoryTag($project_id, int $repository_id, string $tag * @see https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository-tags-in-bulk * * @param int|string $project_id - * @param int $repository_id * @param array $parameters { * * @var string $name_regex_delete