Skip to content

Commit 8c9313c

Browse files
authored
[11.5] Add packages endpoints (#644)
1 parent aab681a commit 8c9313c

File tree

4 files changed

+340
-0
lines changed

4 files changed

+340
-0
lines changed

src/Api/Groups.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,58 @@ public function removeVariable($group_id, string $key)
432432
return $this->delete('groups/'.self::encodePath($group_id).'/variables/'.self::encodePath($key));
433433
}
434434

435+
/**
436+
* @param int|string $group_id
437+
* @param array $parameters {
438+
*
439+
* @var bool $exclude_subgroups if the parameter is included as true, packages from projects from subgroups
440+
* are not listed. default is false.
441+
* @var string $order_by the field to use as order. one of created_at (default), name, version, type,
442+
* or project_path.
443+
* @var string $sort the direction of the order, either asc (default) for ascending order
444+
* or desc for descending order
445+
* @var string $package_type filter the returned packages by type. one of conan, maven, npm, pypi,
446+
* composer, nuget, or golang.
447+
* @var string $package_name filter the project packages with a fuzzy search by name
448+
* @var bool $include_versionless when set to true, versionless packages are included in the response
449+
* @var string $status filter the returned packages by status. one of default (default),
450+
* hidden, or processing.
451+
* }
452+
*
453+
* @return mixed
454+
*/
455+
public function packages($group_id, array $parameters = [])
456+
{
457+
$resolver = $this->createOptionsResolver();
458+
$booleanNormalizer = function (Options $resolver, $value): string {
459+
return $value ? 'true' : 'false';
460+
};
461+
462+
$resolver->setDefined('exclude_subgroups')
463+
->setAllowedTypes('exclude_subgroups', 'bool')
464+
->setNormalizer('exclude_subgroups', $booleanNormalizer)
465+
;
466+
$resolver->setDefined('order_by')
467+
->setAllowedValues('order_by', ['created_at', 'name', 'version', 'type'])
468+
;
469+
$resolver->setDefined('sort')
470+
->setAllowedValues('sort', ['asc', 'desc'])
471+
;
472+
$resolver->setDefined('package_type')
473+
->setAllowedValues('package_type', ['conan', 'maven', 'npm', 'pypi', 'composer', 'nuget', 'golang'])
474+
;
475+
$resolver->setDefined('package_name');
476+
$resolver->setDefined('include_versionless')
477+
->setAllowedTypes('include_versionless', 'bool')
478+
->setNormalizer('include_versionless', $booleanNormalizer)
479+
;
480+
$resolver->setDefined('status')
481+
->setAllowedValues('status', ['default', 'hidden', 'processing'])
482+
;
483+
484+
return $this->get('groups/'.self::encodePath($group_id).'/packages', $resolver->resolve($parameters));
485+
}
486+
435487
/**
436488
* @return OptionsResolver
437489
*/

src/Api/Packages.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Gitlab API library.
7+
*
8+
* (c) Matt Humphrey <[email protected]>
9+
* (c) Graham Campbell <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Gitlab\Api;
16+
17+
use Symfony\Component\OptionsResolver\Options;
18+
19+
class Packages extends AbstractApi
20+
{
21+
/**
22+
* @param int|string $project_id
23+
* @param array $parameters {
24+
*
25+
* @var string $order_by the field to use as order. one of created_at (default), name,
26+
* version, or type
27+
* @var string $sort the direction of the order, either asc (default) for ascending order or
28+
* desc for descending order
29+
* @var string $package_type filter the returned packages by type. one of conan, maven, npm, pypi,
30+
* composer, nuget, or golang.
31+
* @var string $package_name filter the project packages with a fuzzy search by name
32+
* @var bool $include_versionless when set to true, versionless packages are included in the response
33+
* @var string $status filter the returned packages by status. one of default (default),
34+
* hidden, or processing.
35+
* }
36+
*
37+
* @return mixed
38+
*/
39+
public function all($project_id, array $parameters = [])
40+
{
41+
$resolver = $this->createOptionsResolver();
42+
43+
$resolver->setDefined('order_by')
44+
->setAllowedValues('order_by', ['created_at', 'name', 'version', 'type'])
45+
;
46+
$resolver->setDefined('sort')
47+
->setAllowedValues('sort', ['asc', 'desc'])
48+
;
49+
$resolver->setDefined('package_type')
50+
->setAllowedValues('package_type', ['conan', 'maven', 'npm', 'pypi', 'composer', 'nuget', 'golang'])
51+
;
52+
$resolver->setDefined('package_name');
53+
$resolver->setDefined('include_versionless')
54+
->setAllowedTypes('include_versionless', 'bool')
55+
->setNormalizer('include_versionless', function (Options $resolver, $value): string {
56+
return $value ? 'true' : 'false';
57+
})
58+
;
59+
$resolver->setDefined('status')
60+
->setAllowedValues('status', ['default', 'hidden', 'processing'])
61+
;
62+
63+
return $this->get($this->getProjectPath($project_id, 'packages'), $resolver->resolve($parameters));
64+
}
65+
66+
/**
67+
* @param int|string $project_id
68+
* @param int $package_id
69+
*
70+
* @return mixed
71+
*/
72+
public function show($project_id, int $package_id)
73+
{
74+
return $this->get($this->getPackagePath($project_id, $package_id));
75+
}
76+
77+
/**
78+
* @param int|string $project_id
79+
* @param int $package_id
80+
*
81+
* @return mixed
82+
*/
83+
public function allFiles($project_id, int $package_id)
84+
{
85+
return $this->get($this->getPackagePath($project_id, $package_id).'/package_files');
86+
}
87+
88+
/**
89+
* @param int|string $project_id
90+
* @param int $package_id
91+
*
92+
* @return mixed
93+
*/
94+
public function remove($project_id, int $package_id)
95+
{
96+
return $this->delete($this->getPackagePath($project_id, $package_id));
97+
}
98+
99+
/**
100+
* @param int|string $project_id
101+
* @param int $package_id
102+
* @param int $package_file_id
103+
*
104+
* @return mixed
105+
*/
106+
public function removeFile($project_id, int $package_id, int $package_file_id)
107+
{
108+
return $this->delete(
109+
$this->getPackagePath($project_id, $package_id).'/package_files/'.self::encodePath($package_file_id)
110+
);
111+
}
112+
113+
/**
114+
* @param int|string $project_id
115+
* @param int $package_id
116+
*
117+
* @return string
118+
*/
119+
private function getPackagePath($project_id, int $package_id): string
120+
{
121+
return $this->getProjectPath($project_id, 'packages/'.self::encodePath($package_id));
122+
}
123+
}

tests/Api/GroupsTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,4 +655,44 @@ public function shouldGetAllGroupProjectsIncludingCustomAttributes(): void
655655

656656
$this->assertEquals($expectedArray, $api->projects(1, ['with_custom_attributes' => true]));
657657
}
658+
659+
/**
660+
* @test
661+
*/
662+
public function shouldGetPackages(): void
663+
{
664+
$expectedArray = [
665+
'id' => 2,
666+
'name' => '@foo/bar',
667+
'version' => '1.0.3',
668+
'package_type' => 'npm',
669+
'_links' => [
670+
'web_path' => '/namespace1/project1/-/packages/1',
671+
'delete_api_path' => '/namespace1/project1/-/packages/1',
672+
],
673+
'created_at' => '2019-11-27T03:37:38.711Z',
674+
'pipelines' => [
675+
'id' => 123,
676+
'status' => 'pending',
677+
'ref' => 'new-pipeline',
678+
'sha' => 'a91957a858320c0e17f3a0eca7cfacbff50ea29a',
679+
'web_url' => 'https://example.com/foo/bar/pipelines/47',
680+
'created_at' => '2016-08-11T11:28:34.085Z',
681+
'updated_at' => '2016-08-11T11:32:35.169Z',
682+
'user' => [
683+
'name' => 'Administrator',
684+
'avatar_url' => 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
685+
],
686+
],
687+
];
688+
689+
$api = $this->getApiMock();
690+
$api->expects($this->once())
691+
->method('get')
692+
->with('groups/1/packages')
693+
->will($this->returnValue($expectedArray))
694+
;
695+
696+
$this->assertEquals($expectedArray, $api->packages(1));
697+
}
658698
}

tests/Api/PackagesTest.php

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Gitlab API library.
7+
*
8+
* (c) Matt Humphrey <[email protected]>
9+
* (c) Graham Campbell <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Gitlab\Tests\Api;
16+
17+
use Gitlab\Api\Packages;
18+
19+
final class PackagesTest extends TestCase
20+
{
21+
/**
22+
* @test
23+
*/
24+
public function shouldGetAllPackages(): void
25+
{
26+
$expectedArray = [
27+
[
28+
'id' => 3,
29+
'name' => 'Hello/0.1@mycompany/stable',
30+
'conan_package_name' => 'Hello',
31+
'version' => '0.1',
32+
'package_type' => 'conan',
33+
'_links' => [
34+
'web_path' => '/foo/bar/-/packages/3',
35+
'delete_api_path' => 'https://gitlab.example.com/api/v4/projects/1/packages/3',
36+
],
37+
'created_at' => '2029-12-16T20:33:34.316Z',
38+
'tags' => [],
39+
],
40+
];
41+
42+
$api = $this->getApiMock();
43+
$api->expects($this->once())
44+
->method('get')
45+
->with('projects/1/packages')
46+
->will($this->returnValue($expectedArray));
47+
48+
$this->assertEquals($expectedArray, $api->all(1));
49+
}
50+
51+
/**
52+
* @test
53+
*/
54+
public function shouldShowPackage(): void
55+
{
56+
$expectedArray = [
57+
['id' => 1, 'name' => 'com/mycompany/my-app', 'version' => '1.0-SNAPSHOT', 'package_type' => 'maven'],
58+
];
59+
60+
$api = $this->getApiMock();
61+
$api->expects($this->once())
62+
->method('get')
63+
->with('projects/1/packages/1')
64+
->will($this->returnValue($expectedArray));
65+
66+
$this->assertEquals($expectedArray, $api->show(1, 1));
67+
}
68+
69+
/**
70+
* @test
71+
*/
72+
public function shouldGetAllPackageFiles(): void
73+
{
74+
$expectedArray = [
75+
['id' => 25, 'file_name' => 'my-app-1.5-20181107.152550-1.jar', 'size' => 2421],
76+
['id' => 26, 'file_name' => 'my-app-1.5-20181107.152550-1.pom', 'size' => 1122],
77+
['id' => 27, 'file_name' => 'maven-metadata.xml', 'size' => 767],
78+
];
79+
80+
$api = $this->getApiMock();
81+
$api->expects($this->once())
82+
->method('get')
83+
->with('projects/1/packages/1/package_files')
84+
->will($this->returnValue($expectedArray));
85+
86+
$this->assertEquals($expectedArray, $api->allFiles(1, 1));
87+
}
88+
89+
/**
90+
* @test
91+
*/
92+
public function shouldRemovePackage(): void
93+
{
94+
$expectedBool = true;
95+
96+
$api = $this->getApiMock();
97+
$api->expects($this->once())
98+
->method('delete')
99+
->with('projects/1/packages/1')
100+
->will($this->returnValue($expectedBool));
101+
102+
$this->assertEquals($expectedBool, $api->remove(1, 1));
103+
}
104+
105+
/**
106+
* @test
107+
*/
108+
public function shouldRemovePackageFile(): void
109+
{
110+
$expectedBool = true;
111+
112+
$api = $this->getApiMock();
113+
$api->expects($this->once())
114+
->method('delete')
115+
->with('projects/1/packages/1/package_files/25')
116+
->will($this->returnValue($expectedBool));
117+
118+
$this->assertEquals($expectedBool, $api->removeFile(1, 1, 25));
119+
}
120+
121+
protected function getApiClass()
122+
{
123+
return Packages::class;
124+
}
125+
}

0 commit comments

Comments
 (0)