From ad2565b6cb5e364d4976859c6ebfaac96c0a9d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Ondr=C3=A1=C4=8Dek?= Date: Sun, 16 Jul 2023 19:07:30 +0200 Subject: [PATCH] OpenAPI: add Link object and add missing properties of existing objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Roman Ondráček --- Makefile | 6 +- phpstan.neon | 1 - src/OpenApi/Schema/Components.php | 33 +- src/OpenApi/Schema/Header.php | 73 +- src/OpenApi/Schema/License.php | 18 + src/OpenApi/Schema/Link.php | 89 +- src/OpenApi/Schema/MediaType.php | 4 +- src/OpenApi/Schema/OpenApi.php | 18 +- src/OpenApi/Schema/Operation.php | 6 +- src/OpenApi/Schema/Parameter.php | 50 +- src/OpenApi/Schema/PathItem.php | 82 +- src/OpenApi/Schema/Paths.php | 12 +- src/OpenApi/Schema/Reference.php | 50 +- src/OpenApi/Schema/Response.php | 33 +- src/OpenApi/Schema/Responses.php | 2 +- src/OpenApi/Schema/Server.php | 6 +- tests/Cases/OpenApi/Schema/ExamplesTest.php | 17 +- tests/Cases/OpenApi/Schema/LicenseTest.php | 3 + tests/Cases/OpenApi/Schema/ParameterTest.php | 8 +- tests/Cases/OpenApi/Schema/ReferenceTest.php | 52 + .../Cases/OpenApi/Schema/examples/gitlab.yaml | 3524 +++++++++++++++++ 21 files changed, 4009 insertions(+), 78 deletions(-) create mode 100644 tests/Cases/OpenApi/Schema/ReferenceTest.php create mode 100644 tests/Cases/OpenApi/Schema/examples/gitlab.yaml diff --git a/Makefile b/Makefile index af542a91..740e007c 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,11 @@ phpstan: vendor/bin/phpstan analyse -c phpstan.neon tests: - vendor/bin/tester -s -p php --colors 1 -C tests/Cases + vendor/bin/tester -s -p php --colors 1 -C -d memory_limit=512M tests/Cases coverage: ifdef GITHUB_ACTION - vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.xml --coverage-src src tests/Cases + vendor/bin/tester -s -p phpdbg --colors 1 -C -d memory_limit=512M --coverage coverage.xml --coverage-src src tests/Cases else - vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.html --coverage-src src tests/Cases + vendor/bin/tester -s -p phpdbg --colors 1 -C -d memory_limit=512M --coverage coverage.html --coverage-src src tests/Cases endif diff --git a/phpstan.neon b/phpstan.neon index 86c32a65..28e39938 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -47,7 +47,6 @@ parameters: path: %currentWorkingDirectory%/src/OpenApi/SchemaDefinition/Entity/EntityAdapter.php - '#Property Apitte\\OpenApi\\Schema\\(\w+)::\$(\w+) is never read, only written.#' - - '#Property Apitte\\OpenApi\\Schema\\(\w+)::\$(\w+) is unused.#' # This should not happen because null is returned on error - '#Method Apitte\\Core\\Utils\\Helpers::slashless\(\) should return string but returns string\|null\.#' diff --git a/src/OpenApi/Schema/Components.php b/src/OpenApi/Schema/Components.php index c39c120a..ef14b77f 100644 --- a/src/OpenApi/Schema/Components.php +++ b/src/OpenApi/Schema/Components.php @@ -46,7 +46,7 @@ public static function fromArray(array $data): Components if (isset($data['responses'])) { foreach ($data['responses'] as $responseKey => $responseData) { - $components->setResponse($responseKey, Response::fromArray($responseData)); + $components->setResponse((string) $responseKey, Response::fromArray($responseData)); } } @@ -62,22 +62,20 @@ public static function fromArray(array $data): Components } } - if (isset($data['requestBodies'])) { - foreach ($data['requestBodies'] as $requestBodyKey => $requestBodyData) { - $components->setRequestBody($requestBodyKey, RequestBody::fromArray($requestBodyData)); - } + foreach ($data['requestBodies'] ?? [] as $requestBodyKey => $requestBodyData) { + $components->setRequestBody($requestBodyKey, RequestBody::fromArray($requestBodyData)); } - if (isset($data['headers'])) { - foreach ($data['headers'] as $headerKey => $headerData) { - $components->setHeader($headerKey, Header::fromArray($headerData)); - } + foreach ($data['headers'] ?? [] as $headerKey => $headerData) { + $components->setHeader($headerKey, Header::fromArray($headerData)); } - if (isset($data['securitySchemes'])) { - foreach ($data['securitySchemes'] as $securitySchemeKey => $securitySchemeData) { - $components->setSecurityScheme($securitySchemeKey, SecurityScheme::fromArray($securitySchemeData)); - } + foreach ($data['securitySchemes'] ?? [] as $securitySchemeKey => $securitySchemeData) { + $components->setSecurityScheme($securitySchemeKey, SecurityScheme::fromArray($securitySchemeData)); + } + + foreach ($data['links'] ?? [] as $linkKey => $linkData) { + $components->setLink($linkKey, Link::fromArray($linkData)); } return $components; @@ -118,6 +116,11 @@ public function setSecurityScheme(string $name, SecurityScheme|Reference $securi $this->securitySchemes[$name] = $securityScheme; } + public function setLink(string $name, Link|Reference $link): void + { + $this->links[$name] = $link; + } + /** * @return mixed[] */ @@ -152,6 +155,10 @@ public function toArray(): array $data['securitySchemes'][$securitySchemeKey] = $securityScheme->toArray(); } + foreach ($this->links as $linkKey => $link) { + $data['links'][$linkKey] = $link->toArray(); + } + return $data; } diff --git a/src/OpenApi/Schema/Header.php b/src/OpenApi/Schema/Header.php index cf258704..e9fc06e6 100644 --- a/src/OpenApi/Schema/Header.php +++ b/src/OpenApi/Schema/Header.php @@ -7,8 +7,19 @@ class Header private ?string $description = null; + private ?bool $required = null; + + private ?bool $deprecated = null; + + private ?bool $allowEmptyValue = null; + private Schema|Reference|null $schema = null; + private mixed $example = null; + + /** @var mixed[] */ + private array $examples = []; + /** * @param mixed[] $data */ @@ -16,7 +27,19 @@ public static function fromArray(array $data): Header { $header = new Header(); $header->setDescription($data['description'] ?? null); - $header->setSchema(isset($data['schema']) ? Schema::fromArray($data['schema']) : null); + $header->setRequired($data['required'] ?? null); + $header->setDeprecated($data['deprecated'] ?? null); + $header->setAllowEmptyValue($data['allowEmptyValue'] ?? null); + if (isset($data['schema'])) { + if (isset($data['schema']['$ref'])) { + $header->setSchema(Reference::fromArray($data['schema'])); + } else { + $header->setSchema(Schema::fromArray($data['schema'])); + } + } + + $header->setExample($data['example'] ?? null); + $header->setExamples($data['examples'] ?? []); return $header; } @@ -31,10 +54,30 @@ public function toArray(): array $data['description'] = $this->description; } + if ($this->required !== null) { + $data['required'] = $this->required; + } + + if ($this->deprecated !== null) { + $data['deprecated'] = $this->deprecated; + } + + if ($this->allowEmptyValue !== null) { + $data['allowEmptyValue'] = $this->allowEmptyValue; + } + if ($this->schema !== null) { $data['schema'] = $this->schema->toArray(); } + if ($this->example !== null) { + $data['example'] = $this->example; + } + + if ($this->examples !== []) { + $data['examples'] = $this->examples; + } + return $data; } @@ -43,9 +86,37 @@ public function setDescription(?string $description): void $this->description = $description; } + public function setRequired(?bool $required): void + { + $this->required = $required; + } + + public function setDeprecated(?bool $deprecated): void + { + $this->deprecated = $deprecated; + } + + public function setAllowEmptyValue(?bool $allowEmptyValue): void + { + $this->allowEmptyValue = $allowEmptyValue; + } + public function setSchema(Schema|Reference|null $schema): void { $this->schema = $schema; } + public function setExample(mixed $example): void + { + $this->example = $example; + } + + /** + * @param mixed[] $examples + */ + public function setExamples(array $examples): void + { + $this->examples = $examples; + } + } diff --git a/src/OpenApi/Schema/License.php b/src/OpenApi/Schema/License.php index 710db8e5..84ce650b 100644 --- a/src/OpenApi/Schema/License.php +++ b/src/OpenApi/Schema/License.php @@ -7,6 +7,8 @@ class License private string $name; + private ?string $identifier = null; + private ?string $url = null; public function __construct(string $name) @@ -20,6 +22,7 @@ public function __construct(string $name) public static function fromArray(array $data): License { $license = new License($data['name']); + $license->setIdentifier($data['identifier'] ?? null); $license->setUrl($data['url'] ?? null); return $license; @@ -33,6 +36,11 @@ public function toArray(): array $data = []; $data['name'] = $this->name; + // Optional SPDX identifier + if ($this->identifier !== null) { + $data['identifier'] = $this->identifier; + } + // Optional url if ($this->url !== null) { $data['url'] = $this->url; @@ -41,6 +49,11 @@ public function toArray(): array return $data; } + public function setIdentifier(?string $identifier): void + { + $this->identifier = $identifier; + } + public function setUrl(?string $url): void { $this->url = $url; @@ -51,6 +64,11 @@ public function getName(): string return $this->name; } + public function getIdentifier(): ?string + { + return $this->identifier; + } + public function getUrl(): ?string { return $this->url; diff --git a/src/OpenApi/Schema/Link.php b/src/OpenApi/Schema/Link.php index e5096f0d..e712920a 100644 --- a/src/OpenApi/Schema/Link.php +++ b/src/OpenApi/Schema/Link.php @@ -5,12 +5,99 @@ class Link { + private ?string $operationRef = null; + + private ?string $operationId = null; + + /** @var mixed[] */ + private array $parameters = []; + + private mixed $requestBody = null; + + private ?string $description = null; + + private ?Server $server = null; + + /** + * @param mixed[] $data + */ + public static function fromArray(array $data): Link + { + $link = new Link(); + $link->setOperationRef($data['operationRef'] ?? null); + $link->setOperationId($data['operationId'] ?? null); + $link->setParameters($data['parameters'] ?? []); + $link->setRequestBody($data['requestBody'] ?? null); + $link->setDescription($data['description'] ?? null); + $link->setServer(isset($data['server']) ? Server::fromArray($data['server']) : null); + + return $link; + } + + public function setOperationRef(?string $operationRef): void + { + $this->operationRef = $operationRef; + } + + public function setOperationId(?string $operationId): void + { + $this->operationId = $operationId; + } + + /** + * @param mixed[] $parameters + */ + public function setParameters(array $parameters): void + { + $this->parameters = $parameters; + } + + public function setRequestBody(mixed $requestBody): void + { + $this->requestBody = $requestBody; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + + public function setServer(?Server $server): void + { + $this->server = $server; + } + /** * @return mixed[] */ public function toArray(): array { - return []; + $data = []; + if ($this->operationRef !== null) { + $data['operationRef'] = $this->operationRef; + } + + if ($this->operationId !== null) { + $data['operationId'] = $this->operationId; + } + + if ($this->parameters !== []) { + $data['parameters'] = $this->parameters; + } + + if ($this->requestBody !== null) { + $data['requestBody'] = $this->requestBody; + } + + if ($this->description !== null) { + $data['description'] = $this->description; + } + + if ($this->server !== null) { + $data['server'] = $this->server->toArray(); + } + + return $data; } } diff --git a/src/OpenApi/Schema/MediaType.php b/src/OpenApi/Schema/MediaType.php index 26e433ce..58362231 100644 --- a/src/OpenApi/Schema/MediaType.php +++ b/src/OpenApi/Schema/MediaType.php @@ -20,7 +20,7 @@ public static function fromArray(array $data): MediaType $mediaType = new MediaType(); if (isset($data['schema'])) { if (isset($data['schema']['$ref'])) { - $mediaType->setSchema(new Reference($data['schema']['$ref'])); + $mediaType->setSchema(Reference::fromArray($data['schema'])); } else { $mediaType->setSchema(Schema::fromArray($data['schema'])); } @@ -30,7 +30,7 @@ public static function fromArray(array $data): MediaType if (isset($data['examples'])) { foreach ($data['examples'] as $name => $example) { if (isset($example['$ref'])) { - $mediaType->addExample($name, new Reference($example['$ref'])); + $mediaType->addExample($name, Reference::fromArray($example)); } else { $mediaType->addExample($name, Example::fromArray($example)); } diff --git a/src/OpenApi/Schema/OpenApi.php b/src/OpenApi/Schema/OpenApi.php index fba76901..e9788d08 100644 --- a/src/OpenApi/Schema/OpenApi.php +++ b/src/OpenApi/Schema/OpenApi.php @@ -41,30 +41,24 @@ public static function fromArray(array $data): OpenApi Info::fromArray($data['info']), Paths::fromArray($data['paths']) ); - if (isset($data['servers'])) { - foreach ($data['servers'] as $serverData) { - $openApi->addServer(Server::fromArray($serverData)); - } + foreach ($data['servers'] ?? [] as $serverData) { + $openApi->addServer(Server::fromArray($serverData)); } if (isset($data['components'])) { $openApi->setComponents(Components::fromArray($data['components'])); } - if (isset($data['tags'])) { - foreach ($data['tags'] as $tagData) { - $openApi->addTag(Tag::fromArray($tagData)); - } + foreach ($data['tags'] ?? [] as $tagData) { + $openApi->addTag(Tag::fromArray($tagData)); } if (isset($data['externalDocs'])) { $openApi->externalDocs = ExternalDocumentation::fromArray($data['externalDocs']); } - if (isset($data['security'])) { - foreach ($data['security'] as $security) { - $openApi->addSecurityRequirement(SecurityRequirement::fromArray($security)); - } + foreach ($data['security'] ?? [] as $security) { + $openApi->addSecurityRequirement(SecurityRequirement::fromArray($security)); } return $openApi; diff --git a/src/OpenApi/Schema/Operation.php b/src/OpenApi/Schema/Operation.php index 43d15f73..41a3b0e3 100644 --- a/src/OpenApi/Schema/Operation.php +++ b/src/OpenApi/Schema/Operation.php @@ -62,7 +62,7 @@ public static function fromArray(array $data): Operation foreach ($data['parameters'] ?? [] as $parameterData) { if (isset($parameterData['$ref'])) { - $operation->addParameter(new Reference($parameterData['$ref'])); + $operation->addParameter(Reference::fromArray($parameterData)); continue; } @@ -77,7 +77,7 @@ public static function fromArray(array $data): Operation if (isset($data['requestBody'])) { if (isset($data['requestBody']['$ref'])) { - $operation->setRequestBody(new Reference($data['requestBody']['$ref'])); + $operation->setRequestBody(Reference::fromArray($data['requestBody'])); } else { $operation->setRequestBody(RequestBody::fromArray($data['requestBody'])); } @@ -93,7 +93,7 @@ public static function fromArray(array $data): Operation foreach ($data['callbacks'] ?? [] as $callback) { if (isset($callback['$ref'])) { - $operation->addCallback(new Reference($callback['$ref'])); + $operation->addCallback(Reference::fromArray($callback)); } else { $operation->addCallback(Callback::fromArray($callback)); } diff --git a/src/OpenApi/Schema/Parameter.php b/src/OpenApi/Schema/Parameter.php index bcee8284..5f1e39b5 100644 --- a/src/OpenApi/Schema/Parameter.php +++ b/src/OpenApi/Schema/Parameter.php @@ -25,16 +25,19 @@ class Parameter private ?string $description = null; - private bool $required = false; + private ?bool $required = null; - private bool $deprecated = false; + private ?bool $deprecated = null; - private bool $allowEmptyValue = false; + private ?bool $allowEmptyValue = null; private Schema|Reference|null $schema = null; private mixed $example = null; + /** @var mixed[] */ + private array $examples = []; + private ?string $style = null; public function __construct(string $name, string $in) @@ -58,16 +61,19 @@ public static function fromArray(array $data): Parameter { $parameter = new Parameter($data['name'], $data['in']); $parameter->setDescription($data['description'] ?? null); - $parameter->setRequired($data['required'] ?? false); + $parameter->setRequired($data['required'] ?? null); + $parameter->setDeprecated($data['deprecated'] ?? null); + $parameter->setAllowEmptyValue($data['allowEmptyValue'] ?? null); if (isset($data['schema'])) { if (isset($data['schema']['$ref'])) { - $parameter->setSchema(new Reference($data['schema']['$ref'])); + $parameter->setSchema(Reference::fromArray($data['schema'])); } else { $parameter->setSchema(Schema::fromArray($data['schema'])); } } $parameter->setExample($data['example'] ?? null); + $parameter->setExamples($data['examples'] ?? []); $parameter->setStyle($data['style'] ?? null); return $parameter; @@ -78,17 +84,17 @@ public function setDescription(?string $description): void $this->description = $description; } - public function setRequired(bool $required): void + public function setRequired(?bool $required): void { $this->required = $required; } - public function setDeprecated(bool $deprecated): void + public function setDeprecated(?bool $deprecated): void { $this->deprecated = $deprecated; } - public function setAllowEmptyValue(bool $allowEmptyValue): void + public function setAllowEmptyValue(?bool $allowEmptyValue): void { $this->allowEmptyValue = $allowEmptyValue; } @@ -103,6 +109,14 @@ public function setExample(mixed $example): void $this->example = $example; } + /** + * @param mixed[] $examples + */ + public function setExamples(array $examples): void + { + $this->examples = $examples; + } + /** * @return mixed[] */ @@ -115,10 +129,18 @@ public function toArray(): array $data['description'] = $this->description; } - if ($this->required) { + if ($this->required !== null) { $data['required'] = $this->required; } + if ($this->deprecated !== null) { + $data['deprecated'] = $this->deprecated; + } + + if ($this->allowEmptyValue !== null) { + $data['allowEmptyValue'] = $this->allowEmptyValue; + } + if ($this->schema !== null) { $data['schema'] = $this->schema->toArray(); } @@ -127,6 +149,10 @@ public function toArray(): array $data['example'] = $this->example; } + if ($this->examples !== []) { + $data['examples'] = $this->examples; + } + if ($this->style !== null) { $data['style'] = $this->style; } @@ -149,17 +175,17 @@ public function getDescription(): ?string return $this->description; } - public function isRequired(): bool + public function isRequired(): ?bool { return $this->required; } - public function isDeprecated(): bool + public function isDeprecated(): ?bool { return $this->deprecated; } - public function isAllowEmptyValue(): bool + public function isAllowEmptyValue(): ?bool { return $this->allowEmptyValue; } diff --git a/src/OpenApi/Schema/PathItem.php b/src/OpenApi/Schema/PathItem.php index 247dd35f..94963d2e 100644 --- a/src/OpenApi/Schema/PathItem.php +++ b/src/OpenApi/Schema/PathItem.php @@ -26,8 +26,6 @@ class PathItem self::OPERATION_TRACE, ]; - private ?string $ref = null; - private ?string $summary = null; private ?string $description = null; @@ -38,7 +36,8 @@ class PathItem /** @var Server[] */ private array $servers = []; - private Parameter|Reference $params; + /** @var Parameter[]|Reference[] */ + private array $params = []; /** * @param mixed[] $pathItemData @@ -55,9 +54,44 @@ public static function fromArray(array $pathItemData): PathItem $pathItem->setOperation($allowedOperation, Operation::fromArray($pathItemData[$allowedOperation])); } + $pathItem->setSummary($pathItemData['summary'] ?? null); + $pathItem->setDescription($pathItemData['description'] ?? null); + + foreach ($pathItemData['servers'] ?? [] as $server) { + $pathItem->addServer(Server::fromArray($server)); + } + + foreach ($pathItemData['parameters'] ?? [] as $parameter) { + if (isset($parameter['$ref'])) { + $pathItem->addParameter(Reference::fromArray($parameter)); + } else { + $pathItem->addParameter(Parameter::fromArray($parameter)); + } + } + return $pathItem; } + public function addParameter(Parameter|Reference $parameter): void + { + $this->params[] = $parameter; + } + + public function addServer(Server $server): void + { + $this->servers[] = $server; + } + + public function setSummary(?string $summary): void + { + $this->summary = $summary; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + public function setOperation(string $key, Operation $operation): void { if (!in_array($key, self::$allowedOperations, true)) { @@ -67,6 +101,32 @@ public function setOperation(string $key, Operation $operation): void $this->operations[$key] = $operation; } + public function getSummary(): ?string + { + return $this->summary; + } + + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @return Parameter[]|Reference[] + */ + public function getParameters(): array + { + return $this->params; + } + + /** + * @return Server[] + */ + public function getServers(): array + { + return $this->servers; + } + /** * @return mixed[] */ @@ -77,6 +137,22 @@ public function toArray(): array $data[$key] = $operation->toArray(); } + if ($this->summary !== null) { + $data['summary'] = $this->summary; + } + + if ($this->description !== null) { + $data['description'] = $this->description; + } + + if ($this->servers !== []) { + $data['servers'] = array_map(static fn (Server $server): array => $server->toArray(), $this->servers); + } + + if ($this->params !== []) { + $data['parameters'] = array_map(static fn (Parameter|Reference $parameter): array => $parameter->toArray(), $this->params); + } + return $data; } diff --git a/src/OpenApi/Schema/Paths.php b/src/OpenApi/Schema/Paths.php index 0101f080..ebac5349 100644 --- a/src/OpenApi/Schema/Paths.php +++ b/src/OpenApi/Schema/Paths.php @@ -5,7 +5,7 @@ class Paths { - /** @var PathItem[] */ + /** @var PathItem[]|Reference[] */ private array $paths = []; /** @@ -15,6 +15,12 @@ public static function fromArray(array $data): Paths { $paths = new Paths(); foreach ($data as $path => $pathItemData) { + if (isset($pathItemData['$ref'])) { + $paths->setPathItem($path, Reference::fromArray($pathItemData)); + + continue; + } + $paths->setPathItem($path, PathItem::fromArray($pathItemData)); } @@ -34,12 +40,12 @@ public function toArray(): array return $data; } - public function setPathItem(string $path, PathItem $pathItem): void + public function setPathItem(string $path, PathItem|Reference $pathItem): void { $this->paths[$path] = $pathItem; } - public function getPath(string $path): ?PathItem + public function getPath(string $path): PathItem|Reference|null { return $this->paths[$path] ?? null; } diff --git a/src/OpenApi/Schema/Reference.php b/src/OpenApi/Schema/Reference.php index e42a8575..cd939e7c 100644 --- a/src/OpenApi/Schema/Reference.php +++ b/src/OpenApi/Schema/Reference.php @@ -7,22 +7,70 @@ class Reference private string $ref; + private ?string $summary = null; + + private ?string $description = null; + public function __construct(string $ref) { $this->ref = $ref; } + /** + * @param mixed[] $data + */ + public static function fromArray(array $data): Reference + { + $reference = new Reference($data['$ref']); + $reference->setSummary($data['summary'] ?? null); + $reference->setDescription($data['description'] ?? null); + + return $reference; + } + + public function setSummary(?string $summary): void + { + $this->summary = $summary; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + public function getRef(): string { return $this->ref; } + public function getSummary(): ?string + { + return $this->summary; + } + + public function getDescription(): ?string + { + return $this->description; + } + /** * @return mixed[] */ public function toArray(): array { - return ['$ref' => $this->ref]; + $data = [ + '$ref' => $this->ref, + ]; + + if ($this->summary !== null) { + $data['summary'] = $this->summary; + } + + if ($this->description !== null) { + $data['description'] = $this->description; + } + + return $data; } } diff --git a/src/OpenApi/Schema/Response.php b/src/OpenApi/Schema/Response.php index e70f7060..1bbdb883 100644 --- a/src/OpenApi/Schema/Response.php +++ b/src/OpenApi/Schema/Response.php @@ -27,19 +27,23 @@ public function __construct(string $description) public static function fromArray(array $data): Response { $response = new Response($data['description']); - if (isset($data['headers'])) { - foreach ($data['headers'] as $key => $headerData) { - if (isset($headerData['$ref'])) { - $response->setHeader($key, new Reference($headerData['$ref'])); - } else { - $response->setHeader($key, Header::fromArray($headerData)); - } + foreach ($data['headers'] ?? [] as $key => $headerData) { + if (isset($headerData['$ref'])) { + $response->setHeader($key, Reference::fromArray($headerData)); + } else { + $response->setHeader($key, Header::fromArray($headerData)); } } - if (isset($data['content'])) { - foreach ($data['content'] as $key => $contentData) { - $response->setContent($key, MediaType::fromArray($contentData)); + foreach ($data['content'] ?? [] as $key => $contentData) { + $response->setContent($key, MediaType::fromArray($contentData)); + } + + foreach ($data['links'] ?? [] as $key => $linkData) { + if (isset($linkData['$ref'])) { + $response->setLink($key, Reference::fromArray($linkData)); + } else { + $response->setLink($key, Link::fromArray($linkData)); } } @@ -56,6 +60,11 @@ public function setHeader(string $key, Header|Reference $header): void $this->headers[$key] = $header; } + public function setLink(string $key, Link|Reference $link): void + { + $this->links[$key] = $link; + } + /** * @return mixed[] */ @@ -71,6 +80,10 @@ public function toArray(): array $data['content'][$key] = $mediaType->toArray(); } + foreach ($this->links as $key => $link) { + $data['links'][$key] = $link->toArray(); + } + return $data; } diff --git a/src/OpenApi/Schema/Responses.php b/src/OpenApi/Schema/Responses.php index 692aa362..cf122d3f 100644 --- a/src/OpenApi/Schema/Responses.php +++ b/src/OpenApi/Schema/Responses.php @@ -16,7 +16,7 @@ public static function fromArray(array $data): Responses $responses = new Responses(); foreach ($data as $key => $responseData) { if (isset($responseData['$ref'])) { - $responses->setResponse((string) $key, new Reference($responseData['$ref'])); + $responses->setResponse((string) $key, Reference::fromArray($responseData)); } else { $responses->setResponse((string) $key, Response::fromArray($responseData)); } diff --git a/src/OpenApi/Schema/Server.php b/src/OpenApi/Schema/Server.php index 10ca1672..416048cb 100644 --- a/src/OpenApi/Schema/Server.php +++ b/src/OpenApi/Schema/Server.php @@ -24,10 +24,8 @@ public static function fromArray(array $data): Server { $server = new Server($data['url']); $server->setDescription($data['description'] ?? null); - if (isset($data['variables'])) { - foreach ($data['variables'] as $key => $variable) { - $server->addVariable($key, ServerVariable::fromArray($variable)); - } + foreach ($data['variables'] ?? [] as $key => $variable) { + $server->addVariable($key, ServerVariable::fromArray($variable)); } return $server; diff --git a/tests/Cases/OpenApi/Schema/ExamplesTest.php b/tests/Cases/OpenApi/Schema/ExamplesTest.php index 890bd868..15b97bc7 100644 --- a/tests/Cases/OpenApi/Schema/ExamplesTest.php +++ b/tests/Cases/OpenApi/Schema/ExamplesTest.php @@ -34,11 +34,18 @@ public function testCallbackExample(): void public function testLinkExample(): void { - // TODO links - //$rawData = Yaml::parseFile(__DIR__ . '/examples/link-example.yaml'); - //$openApi = OpenApi::fromArray($rawData); - //$openApiData = $openApi->toArray(); - //self::assertSameDataStructure($rawData, $openApiData); + $rawData = Yaml::parseFile(__DIR__ . '/examples/link-example.yaml'); + $openApi = OpenApi::fromArray($rawData); + $openApiData = $openApi->toArray(); + self::assertSameDataStructure($rawData, $openApiData); + } + + public function testGitLab(): void + { + $rawData = Yaml::parseFile(__DIR__ . '/examples/gitlab.yaml'); + $openApi = OpenApi::fromArray($rawData); + $openApiData = $openApi->toArray(); + self::assertSameDataStructure($rawData, $openApiData); } public function testPetstore(): void diff --git a/tests/Cases/OpenApi/Schema/LicenseTest.php b/tests/Cases/OpenApi/Schema/LicenseTest.php index 58ce1a04..aa952082 100644 --- a/tests/Cases/OpenApi/Schema/LicenseTest.php +++ b/tests/Cases/OpenApi/Schema/LicenseTest.php @@ -14,14 +14,17 @@ class LicenseTest extends TestCase public function testOptional(): void { $license = new License('Apache 2.0'); + $license->setIdentifier('Apache-2.0'); $license->setUrl('https://www.apache.org/licenses/LICENSE-2.0.html'); Assert::same('Apache 2.0', $license->getName()); + Assert::same('Apache-2.0', $license->getIdentifier()); Assert::same('https://www.apache.org/licenses/LICENSE-2.0.html', $license->getUrl()); $realData = $license->toArray(); $expectedData = [ 'name' => 'Apache 2.0', + 'identifier' => 'Apache-2.0', 'url' => 'https://www.apache.org/licenses/LICENSE-2.0.html', ]; diff --git a/tests/Cases/OpenApi/Schema/ParameterTest.php b/tests/Cases/OpenApi/Schema/ParameterTest.php index b50c0a21..25838fbb 100644 --- a/tests/Cases/OpenApi/Schema/ParameterTest.php +++ b/tests/Cases/OpenApi/Schema/ParameterTest.php @@ -47,6 +47,8 @@ public function testOptional(): void 'in' => 'cookie', 'description' => 'description', 'required' => true, + 'deprecated' => true, + 'allowEmptyValue' => true, 'schema' => [], 'example' => 'whatever', 'style' => 'whatever', @@ -64,9 +66,9 @@ public function testRequired(): void Assert::same(Parameter::IN_PATH, $parameter->getIn()); Assert::null($parameter->getDescription()); - Assert::false($parameter->isRequired()); - Assert::false($parameter->isDeprecated()); - Assert::false($parameter->isAllowEmptyValue()); + Assert::null($parameter->isRequired()); + Assert::null($parameter->isDeprecated()); + Assert::null($parameter->isAllowEmptyValue()); Assert::null($parameter->getStyle()); Assert::null($parameter->getExample()); diff --git a/tests/Cases/OpenApi/Schema/ReferenceTest.php b/tests/Cases/OpenApi/Schema/ReferenceTest.php new file mode 100644 index 00000000..a1151928 --- /dev/null +++ b/tests/Cases/OpenApi/Schema/ReferenceTest.php @@ -0,0 +1,52 @@ +setSummary('Server error'); + $ref->setDescription('Server error response, e.g. unhandled exception'); + + Assert::same('#/components/responses/ServerError', $ref->getRef()); + Assert::same('Server error', $ref->getSummary()); + Assert::same('Server error response, e.g. unhandled exception', $ref->getDescription()); + + $realData = $ref->toArray(); + $expectedData = [ + '$ref' => '#/components/responses/ServerError', + 'summary' => 'Server error', + 'description' => 'Server error response, e.g. unhandled exception', + ]; + + Assert::same($expectedData, $realData); + Assert::same($expectedData, Reference::fromArray($realData)->toArray()); + } + + public function testRequired(): void + { + $ref = new Reference('#/components/responses/ServerError'); + + Assert::same('#/components/responses/ServerError', $ref->getRef()); + Assert::null($ref->getSummary()); + Assert::null($ref->getDescription()); + + $realData = $ref->toArray(); + $expectedData = ['$ref' => '#/components/responses/ServerError']; + + Assert::same($expectedData, $realData); + Assert::same($expectedData, Reference::fromArray($realData)->toArray()); + } + +} + +(new ReferenceTest())->run(); diff --git a/tests/Cases/OpenApi/Schema/examples/gitlab.yaml b/tests/Cases/OpenApi/Schema/examples/gitlab.yaml new file mode 100644 index 00000000..54d53194 --- /dev/null +++ b/tests/Cases/OpenApi/Schema/examples/gitlab.yaml @@ -0,0 +1,3524 @@ +openapi: 3.0.1 +info: + title: GitLab API + version: v4 + description: | + An OpenAPI definition for the GitLab REST API. + Few API resources or endpoints are currently included. + The intent is to expand this to match the entire Markdown documentation of the API: + . Contributions are welcome. + + When viewing this on gitlab.com, you can test API calls directly from the browser + against the `gitlab.com` instance, if you are logged in. + The feature uses the current [GitLab session cookie](https://docs.gitlab.com/ee/api/index.html#session-cookie), + so each request is made using your account. + + Instructions for using this tool can be found in [Interactive API Documentation](https://docs.gitlab.com/ee/api/openapi/openapi_interactive.html) + termsOfService: 'https://about.gitlab.com/terms/' + license: + name: CC BY-SA 4.0 + url: 'https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE' +servers: +- url: https://www.gitlab.com/api/ +security: + - ApiKeyAuth: [] +tags: +- name: badges + description: Operations about badges +- name: branches + description: Operations about branches +- name: alert_management + description: Operations about alert_managements +- name: batched_background_migrations + description: Operations about batched_background_migrations +- name: admin + description: Operations about admins +- name: migrations + description: Operations about migrations +- name: applications + description: Operations about applications +- name: avatar + description: Operations about avatars +- name: broadcast_messages + description: Operations about broadcast_messages +- name: bulk_imports + description: Operations about bulk_imports +- name: application + description: Operations about applications +- name: access_requests + description: Operations related to access requests +- name: ci_lint + description: Operations related to linting a CI config file +- name: ci_resource_groups + description: Operations to manage job concurrency with resource groups +- name: ci_variables + description: Operations related to CI/CD variables +- name: cluster_agents + description: Operations related to the GitLab agent for Kubernetes +- name: clusters + description: Operations related to clusters +- name: composer_packages + description: Operations related to Composer packages +- name: conan_packages + description: Operations related to Conan packages +- name: container_registry + description: Operations related to container registry +- name: container_registry_event + description: Operations related to container registry events +- name: dashboard_annotations + description: Operations related to dashboard annotations +- name: debian_distribution + description: Operations related to Debian Linux distributions +- name: debian_packages + description: Operations related to Debian Linux packages +- name: dependency_proxy + description: Operations to manage dependency proxy for a groups +- name: deploy_keys + description: Operations related to deploy keys +- name: deploy_tokens + description: Operations related to deploy tokens +- name: deployments + description: Operations related to deployments +- name: dora_metrics + description: Operations related to DevOps Research and Assessment (DORA) key metrics +- name: environments + description: Operations related to environments +- name: error_tracking_client_keys + description: Operations related to error tracking client keys +- name: error_tracking_project_settings + description: Operations related to error tracking project settings +- name: feature_flags_user_lists + description: Operations related to accessing GitLab feature flag user lists +- name: feature_flags + description: Operations related to feature flags +- name: features + description: Operations related to managing Flipper-based feature flags +- name: freeze_periods + description: Operations related to deploy freeze periods +- name: generic_packages + description: Operations related to Generic packages +- name: geo + description: Operations related to Geo +- name: geo_nodes + description: Operations related Geo Nodes +- name: go_proxy + description: Operations related to Go Proxy +- name: group_export + description: Operations related to exporting groups +- name: group_import + description: Operations related to importing groups +- name: group_packages + description: Operations related to group packages +- name: helm_packages + description: Operations related to Helm packages +- name: integrations + description: Operations related to integrations +- name: issue_links + description: Operations related to issue links +- name: jira_connect_subscriptions + description: Operations related to JiraConnect subscriptions +- name: maven_packages + description: Operations related to Maven packages +- name: merge_requests + description: Operations related to merge requests +- name: metadata + description: Operations related to metadata of the GitLab instance +- name: metrics_user_starred_dashboards + description: Operations related to User-starred metrics dashboards +- name: ml_model_registry + description: Operations related to Model registry +- name: npm_packages + description: Operations related to NPM packages +- name: nuget_packages + description: Operations related to Nuget packages +- name: package_files + description: Operations about package files +- name: plan_limits + description: Operations related to plan limits +- name: project_export + description: Operations related to exporting projects +- name: project_hooks + description: Operations related to project hooks +- name: project_import + description: Operations related to importing projects +- name: project_import_bitbucket + description: Operations related to importing BitBucket projects +- name: project_import_github + description: Operations related to importing GitHub projects +- name: project_packages + description: Operations related to project packages +- name: projects + description: Operations related to projects +- name: protected environments + description: Operations related to protected environments +- name: pypi_packages + description: Operations related to PyPI packages +- name: release_links + description: Operations related to release assets (links) +- name: releases + description: Operations related to releases +- name: resource_milestone_events + description: Operations about resource milestone events +- name: rpm_packages + description: Operations related to RPM packages +- name: rubygem_packages + description: Operations related to RubyGems +- name: suggestions + description: Operations related to suggestions +- name: system_hooks + description: Operations related to system hooks +- name: terraform_state + description: Operations related to Terraform state files +- name: terraform_registry + description: Operations related to the Terraform module registry +- name: unleash_api + description: Operations related to Unleash API +paths: + /api/v4/groups/{id}/badges/{badge_id}: + get: + tags: + - badges + summary: Gets a badge of a group. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4GroupsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + description: The badge ID + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Gets a badge of a group. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + put: + tags: + - badges + summary: Updates a badge of a group. + description: This feature was introduced in GitLab 10.6. + operationId: putApiV4GroupsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + link_url: + type: string + description: URL of the badge link + image_url: + type: string + description: URL of the badge image + name: + type: string + description: Name for the badge + responses: + 200: + description: Updates a badge of a group. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + delete: + tags: + - badges + summary: Removes a badge from the group. + description: This feature was introduced in GitLab 10.6. + operationId: deleteApiV4GroupsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + description: The badge ID + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Removes a badge from the group. + /api/v4/groups/{id}/badges: + get: + tags: + - badges + summary: Gets a list of group badges viewable by the authenticated user. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4GroupsIdBadges + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + - name: name + in: query + description: Name for the badge + schema: + type: string + responses: + 200: + description: Gets a list of group badges viewable by the authenticated user. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_Badge' + post: + tags: + - badges + summary: Adds a badge to a group. + description: This feature was introduced in GitLab 10.6. + operationId: postApiV4GroupsIdBadges + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + required: + - image_url + - link_url + properties: + link_url: + type: string + description: URL of the badge link + image_url: + type: string + description: URL of the badge image + name: + type: string + description: Name for the badge + required: true + responses: + 201: + description: Adds a badge to a group. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + /api/v4/groups/{id}/badges/render: + get: + tags: + - badges + summary: Preview a badge from a group. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4GroupsIdBadgesRender + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user. + required: true + schema: + type: string + - name: link_url + in: query + description: URL of the badge link + required: true + schema: + type: string + - name: image_url + in: query + description: URL of the badge image + required: true + schema: + type: string + responses: + 200: + description: Preview a badge from a group. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BasicBadgeDetails' + /api/v4/groups/{id}/access_requests/{user_id}: + delete: + tags: + - access_requests + summary: Denies an access request for the given user. + description: This feature was introduced in GitLab 8.11. + operationId: deleteApiV4GroupsIdAccessRequestsUserId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user + required: true + schema: + type: string + - name: user_id + in: path + description: The user ID of the access requester + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Denies an access request for the given user. + /api/v4/groups/{id}/access_requests/{user_id}/approve: + put: + tags: + - access_requests + summary: Approves an access request for the given user. + description: This feature was introduced in GitLab 8.11. + operationId: putApiV4GroupsIdAccessRequestsUserIdApprove + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user + required: true + schema: + type: string + - name: user_id + in: path + description: The user ID of the access requester + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + access_level: + type: integer + description: 'A valid access level (defaults: `30`, the Developer + role)' + format: int32 + default: 30 + responses: + 200: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + successfull_response: + example: + id: 1 + username: raymond_smith + name: Raymond Smith + state: active + created_at: 2012-10-22T14:13:35Z + access_level: 20 + /api/v4/groups/{id}/access_requests: + get: + tags: + - access_requests + summary: Gets a list of access requests for a group. + description: This feature was introduced in GitLab 8.11. + operationId: getApiV4GroupsIdAccessRequests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user + required: true + schema: + type: string + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + responses: + 200: + description: Gets a list of access requests for a group. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + post: + tags: + - access_requests + summary: Requests access for the authenticated user to a group. + description: This feature was introduced in GitLab 8.11. + operationId: postApiV4GroupsIdAccessRequests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated + user + required: true + schema: + type: string + responses: + 200: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + successfull_response: + example: + id: 1 + username: raymond_smith + name: Raymond Smith + state: active + created_at: 2012-10-22T14:13:35Z + access_level: 20 + /api/v4/projects/{id}/repository/merged_branches: + delete: + tags: + - branches + description: Delete all merged branches + operationId: deleteApiV4ProjectsIdRepositoryMergedBranches + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + responses: + 202: + description: 202 Accepted + 404: + description: 404 Project Not Found + /api/v4/projects/{id}/repository/branches/{branch}: + get: + tags: + - branches + description: Get a single repository branch + operationId: getApiV4ProjectsIdRepositoryBranchesBranch + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: branch + in: path + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Get a single repository branch + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Branch' + 404: + description: Branch Not Found + delete: + tags: + - branches + description: Delete a branch + operationId: deleteApiV4ProjectsIdRepositoryBranchesBranch + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: branch + in: path + description: The name of the branch + required: true + schema: + type: string + responses: + 204: + description: Delete a branch + 404: + description: Branch Not Found + head: + tags: + - branches + description: Check if a branch exists + operationId: headApiV4ProjectsIdRepositoryBranchesBranch + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: branch + in: path + description: The name of the branch + required: true + schema: + type: string + responses: + 204: + description: No Content + 404: + description: Not Found + /api/v4/projects/{id}/repository/branches: + get: + tags: + - branches + description: Get a project repository branches + operationId: getApiV4ProjectsIdRepositoryBranches + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + - name: search + in: query + description: Return list of branches matching the search criteria + schema: + type: string + - name: regex + in: query + description: Return list of branches matching the regex + schema: + type: string + - name: sort + in: query + description: Return list of branches sorted by the given field + schema: + type: string + enum: + - name_asc + - updated_asc + - updated_desc + - name: page_token + in: query + description: Name of branch to start the pagination from + schema: + type: string + responses: + 200: + description: Get a project repository branches + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_Branch' + 404: + description: 404 Project Not Found + post: + tags: + - branches + description: Create branch + operationId: postApiV4ProjectsIdRepositoryBranches + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + required: + - branch + - ref + properties: + branch: + type: string + description: The name of the branch + ref: + type: string + description: Create branch from commit sha or existing branch + required: true + responses: + 201: + description: Create branch + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Branch' + 400: + description: Failed to create branch + /api/v4/projects/{id}/repository/branches/{branch}/unprotect: + put: + tags: + - branches + description: Unprotect a single branch + operationId: putApiV4ProjectsIdRepositoryBranchesBranchUnprotect + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: branch + in: path + description: The name of the branch + required: true + schema: + type: string + responses: + 200: + description: Unprotect a single branch + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Branch' + 404: + description: 404 Project Not Found + /api/v4/projects/{id}/repository/branches/{branch}/protect: + put: + tags: + - branches + description: Protect a single branch + operationId: putApiV4ProjectsIdRepositoryBranchesBranchProtect + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: branch + in: path + description: The name of the branch + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + properties: + developers_can_push: + type: boolean + description: Flag if developers can push to that branch + developers_can_merge: + type: boolean + description: Flag if developers can merge to that branch + responses: + 200: + description: Protect a single branch + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Branch' + 404: + description: 404 Branch Not Found + /api/v4/projects/{id}/badges/{badge_id}: + get: + tags: + - badges + summary: Gets a badge of a project. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4ProjectsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + description: The badge ID + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Gets a badge of a project. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + put: + tags: + - badges + summary: Updates a badge of a project. + description: This feature was introduced in GitLab 10.6. + operationId: putApiV4ProjectsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + link_url: + type: string + description: URL of the badge link + image_url: + type: string + description: URL of the badge image + name: + type: string + description: Name for the badge + responses: + 200: + description: Updates a badge of a project. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + delete: + tags: + - badges + summary: Removes a badge from the project. + description: This feature was introduced in GitLab 10.6. + operationId: deleteApiV4ProjectsIdBadgesBadgeId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + - name: badge_id + in: path + description: The badge ID + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Removes a badge from the project. + /api/v4/projects/{id}/badges: + get: + tags: + - badges + summary: Gets a list of project badges viewable by the authenticated user. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4ProjectsIdBadges + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + - name: name + in: query + description: Name for the badge + schema: + type: string + responses: + 200: + description: Gets a list of project badges viewable by the authenticated + user. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_Badge' + post: + tags: + - badges + summary: Adds a badge to a project. + description: This feature was introduced in GitLab 10.6. + operationId: postApiV4ProjectsIdBadges + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + required: + - image_url + - link_url + properties: + link_url: + type: string + description: URL of the badge link + image_url: + type: string + description: URL of the badge image + name: + type: string + description: Name for the badge + required: true + responses: + 201: + description: Adds a badge to a project. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Badge' + /api/v4/projects/{id}/badges/render: + get: + tags: + - badges + summary: Preview a badge from a project. + description: This feature was introduced in GitLab 10.6. + operationId: getApiV4ProjectsIdBadgesRender + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user. + required: true + schema: + type: string + - name: link_url + in: query + description: URL of the badge link + required: true + schema: + type: string + - name: image_url + in: query + description: URL of the badge image + required: true + schema: + type: string + responses: + 200: + description: Preview a badge from a project. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BasicBadgeDetails' + /api/v4/projects/{id}/access_requests/{user_id}: + delete: + tags: + - access_requests + summary: Denies an access request for the given user. + description: This feature was introduced in GitLab 8.11. + operationId: deleteApiV4ProjectsIdAccessRequestsUserId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user + required: true + schema: + type: string + - name: user_id + in: path + description: The user ID of the access requester + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Denies an access request for the given user. + /api/v4/projects/{id}/access_requests/{user_id}/approve: + put: + tags: + - access_requests + summary: Approves an access request for the given user. + description: This feature was introduced in GitLab 8.11. + operationId: putApiV4ProjectsIdAccessRequestsUserIdApprove + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user + required: true + schema: + type: string + - name: user_id + in: path + description: The user ID of the access requester + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + access_level: + type: integer + description: 'A valid access level (defaults: `30`, the Developer + role)' + format: int32 + default: 30 + responses: + 200: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + successfull_response: + example: + id: 1 + username: raymond_smith + name: Raymond Smith + state: active + created_at: 2012-10-22T14:13:35Z + access_level: 20 + /api/v4/projects/{id}/access_requests: + get: + tags: + - access_requests + summary: Gets a list of access requests for a project. + description: This feature was introduced in GitLab 8.11. + operationId: getApiV4ProjectsIdAccessRequests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user + required: true + schema: + type: string + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + responses: + 200: + description: Gets a list of access requests for a project. + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + post: + tags: + - access_requests + summary: Requests access for the authenticated user to a project. + description: This feature was introduced in GitLab 8.11. + operationId: postApiV4ProjectsIdAccessRequests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated + user + required: true + schema: + type: string + responses: + 200: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_AccessRequester' + successfull_response: + example: + id: 1 + username: raymond_smith + name: Raymond Smith + state: active + created_at: 2012-10-22T14:13:35Z + access_level: 20 + /api/v4/projects/{id}/alert_management_alerts/{alert_iid}/metric_images/{metric_image_id}: + put: + tags: + - alert_management + description: Update a metric image for an alert + operationId: putApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImagesMetricImageId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: alert_iid + in: path + description: The IID of the Alert + required: true + schema: + type: integer + format: int32 + - name: metric_image_id + in: path + description: The ID of metric image + required: true + schema: + type: integer + format: int32 + requestBody: + content: + multipart/form-data: + schema: + properties: + url: + type: string + description: The url to view more metric info + url_text: + type: string + description: A description of the image or URL + responses: + 200: + description: Update a metric image for an alert + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_MetricImage' + 403: + description: Forbidden + 422: + description: Unprocessable entity + delete: + tags: + - alert_management + description: Remove a metric image for an alert + operationId: deleteApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImagesMetricImageId + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: alert_iid + in: path + description: The IID of the Alert + required: true + schema: + type: integer + format: int32 + - name: metric_image_id + in: path + description: The ID of metric image + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Remove a metric image for an alert + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_MetricImage' + 403: + description: Forbidden + 422: + description: Unprocessable entity + /api/v4/projects/{id}/alert_management_alerts/{alert_iid}/metric_images: + get: + tags: + - alert_management + description: Metric Images for alert + operationId: getApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImages + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: alert_iid + in: path + description: The IID of the Alert + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Metric Images for alert + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_MetricImage' + 404: + description: Not found + post: + tags: + - alert_management + description: Upload a metric image for an alert + operationId: postApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImages + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: alert_iid + in: path + description: The IID of the Alert + required: true + schema: + type: integer + format: int32 + requestBody: + content: + multipart/form-data: + schema: + required: + - file + properties: + file: + type: string + description: The image file to be uploaded + format: binary + url: + type: string + description: The url to view more metric info + url_text: + type: string + description: A description of the image or URL + required: true + responses: + 200: + description: Upload a metric image for an alert + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_MetricImage' + 403: + description: Forbidden + /api/v4/projects/{id}/alert_management_alerts/{alert_iid}/metric_images/authorize: + post: + tags: + - alert_management + description: Workhorse authorize metric image file upload + operationId: postApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImagesAuthorize + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project + required: true + schema: + type: string + - name: alert_iid + in: path + description: The IID of the Alert + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Workhorse authorize metric image file upload + 403: + description: Forbidden + /api/v4/admin/batched_background_migrations/{id}: + get: + tags: + - batched_background_migrations + description: Retrieve a batched background migration + operationId: getApiV4AdminBatchedBackgroundMigrationsId + parameters: + - name: database + in: query + description: The name of the database + schema: + type: string + default: main + enum: + - main + - ci + - embedding + - main_clusterwide + - geo + - name: id + in: path + description: The batched background migration id + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Retrieve a batched background migration + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BatchedBackgroundMigration' + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + 404: + description: 404 Not found + /api/v4/admin/batched_background_migrations: + get: + tags: + - batched_background_migrations + description: Get the list of batched background migrations + operationId: getApiV4AdminBatchedBackgroundMigrations + parameters: + - name: database + in: query + description: The name of the database, the default `main` + schema: + type: string + default: main + enum: + - main + - ci + - embedding + - main_clusterwide + - geo + responses: + 200: + description: Get the list of batched background migrations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_BatchedBackgroundMigration' + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + /api/v4/admin/batched_background_migrations/{id}/resume: + put: + tags: + - batched_background_migrations + description: Resume a batched background migration + operationId: putApiV4AdminBatchedBackgroundMigrationsIdResume + parameters: + - name: id + in: path + description: The batched background migration id + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + database: + type: string + description: The name of the database + default: main + enum: + - main + - ci + - embedding + - main_clusterwide + - geo + responses: + 200: + description: Resume a batched background migration + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BatchedBackgroundMigration' + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + 404: + description: 404 Not found + 422: + description: You can resume only `paused` batched background migrations. + /api/v4/admin/batched_background_migrations/{id}/pause: + put: + tags: + - batched_background_migrations + description: Pause a batched background migration + operationId: putApiV4AdminBatchedBackgroundMigrationsIdPause + parameters: + - name: id + in: path + description: The batched background migration id + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + database: + type: string + description: The name of the database + default: main + enum: + - main + - ci + - embedding + - main_clusterwide + - geo + responses: + 200: + description: Pause a batched background migration + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BatchedBackgroundMigration' + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + 404: + description: 404 Not found + 422: + description: You can pause only `active` batched background migrations. + /api/v4/admin/ci/variables/{key}: + get: + tags: + - ci_variables + description: Get the details of a specific instance-level variable + operationId: getApiV4AdminCiVariablesKey + parameters: + - name: key + in: path + description: The key of a variable + required: true + schema: + type: string + responses: + 200: + description: Get the details of a specific instance-level variable + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Ci_Variable' + 404: + description: Instance Variable Not Found + put: + tags: + - ci_variables + description: Update an instance-level variable + operationId: putApiV4AdminCiVariablesKey + parameters: + - name: key + in: path + description: The key of a variable + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + properties: + value: + type: string + description: The value of a variable + protected: + type: boolean + description: Whether the variable is protected + masked: + type: boolean + description: Whether the variable is masked + raw: + type: boolean + description: Whether the variable will be expanded + variable_type: + type: string + description: 'The type of a variable. Available types are: env_var + (default) and file' + enum: + - env_var + - file + responses: + 200: + description: Update an instance-level variable + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Ci_Variable' + 404: + description: Instance Variable Not Found + delete: + tags: + - ci_variables + description: Delete an existing instance-level variable + operationId: deleteApiV4AdminCiVariablesKey + parameters: + - name: key + in: path + description: The key of a variable + required: true + schema: + type: string + responses: + 204: + description: Delete an existing instance-level variable + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Ci_Variable' + 404: + description: Instance Variable Not Found + /api/v4/admin/ci/variables: + get: + tags: + - ci_variables + description: List all instance-level variables + operationId: getApiV4AdminCiVariables + parameters: + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + responses: + 200: + description: List all instance-level variables + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Ci_Variable' + post: + tags: + - ci_variables + description: Create a new instance-level variable + operationId: postApiV4AdminCiVariables + requestBody: + content: + application/json: + schema: + required: + - key + - value + properties: + key: + type: string + description: The key of the variable. Max 255 characters + value: + type: string + description: The value of a variable + protected: + type: boolean + description: Whether the variable is protected + masked: + type: boolean + description: Whether the variable is masked + raw: + type: boolean + description: Whether the variable will be expanded + variable_type: + type: string + description: 'The type of a variable. Available types are: env_var + (default) and file' + enum: + - env_var + - file + required: true + responses: + 201: + description: Create a new instance-level variable + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Ci_Variable' + 400: + description: 400 Bad Request + /api/v4/admin/databases/{database_name}/dictionary/tables/{table_name}: + get: + tags: + - admin + description: Retrieve dictionary details + operationId: getApiV4AdminDatabasesDatabaseNameDictionaryTablesTableName + parameters: + - name: database_name + in: path + description: The database name + required: true + schema: + type: string + enum: + - main + - ci + - name: table_name + in: path + description: The table name + required: true + schema: + type: string + responses: + 200: + description: Retrieve dictionary details + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Dictionary_Table' + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + 404: + description: 404 Not found + /api/v4/admin/clusters/{cluster_id}: + get: + tags: + - clusters + summary: Get a single instance cluster + description: This feature was introduced in GitLab 13.2. Returns a single instance + cluster. + operationId: getApiV4AdminClustersClusterId + parameters: + - name: cluster_id + in: path + description: The cluster ID + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Get a single instance cluster + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Cluster' + 403: + description: Forbidden + 404: + description: Not found + put: + tags: + - clusters + summary: Edit instance cluster + description: This feature was introduced in GitLab 13.2. Updates an existing + instance cluster. + operationId: putApiV4AdminClustersClusterId + parameters: + - name: cluster_id + in: path + description: The cluster ID + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + name: + type: string + description: Cluster name + enabled: + type: boolean + description: Enable or disable Gitlab's connection to your Kubernetes + cluster + environment_scope: + type: string + description: The associated environment to the cluster + namespace_per_environment: + type: boolean + description: Deploy each environment to a separate Kubernetes namespace + default: true + domain: + type: string + description: Cluster base domain + management_project_id: + type: integer + description: The ID of the management project + format: int32 + managed: + type: boolean + description: Determines if GitLab will manage namespaces and service + accounts for this cluster + platform_kubernetes_attributes[api_url]: + type: string + description: URL to access the Kubernetes API + platform_kubernetes_attributes[token]: + type: string + description: Token to authenticate against Kubernetes + platform_kubernetes_attributes[ca_cert]: + type: string + description: TLS certificate (needed if API is using a self-signed + TLS certificate) + platform_kubernetes_attributes[namespace]: + type: string + description: Unique namespace related to Project + responses: + 200: + description: Edit instance cluster + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Cluster' + 400: + description: Validation error + 403: + description: Forbidden + 404: + description: Not found + delete: + tags: + - clusters + summary: Delete instance cluster + description: This feature was introduced in GitLab 13.2. Deletes an existing + instance cluster. Does not remove existing resources within the connected + Kubernetes cluster. + operationId: deleteApiV4AdminClustersClusterId + parameters: + - name: cluster_id + in: path + description: The cluster ID + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Delete instance cluster + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Cluster' + 403: + description: Forbidden + 404: + description: Not found + /api/v4/admin/clusters/add: + post: + tags: + - clusters + summary: Add existing instance cluster + description: This feature was introduced in GitLab 13.2. Adds an existing Kubernetes + instance cluster. + operationId: postApiV4AdminClustersAdd + requestBody: + content: + application/json: + schema: + required: + - name + - platform_kubernetes_attributes[api_url] + - platform_kubernetes_attributes[token] + properties: + name: + type: string + description: Cluster name + enabled: + type: boolean + description: Determines if cluster is active or not, defaults to + true + default: true + environment_scope: + type: string + description: The associated environment to the cluster + default: '*' + namespace_per_environment: + type: boolean + description: Deploy each environment to a separate Kubernetes namespace + default: true + domain: + type: string + description: Cluster base domain + management_project_id: + type: integer + description: The ID of the management project + format: int32 + managed: + type: boolean + description: Determines if GitLab will manage namespaces and service + accounts for this cluster, defaults to true + default: true + platform_kubernetes_attributes[api_url]: + type: string + description: URL to access the Kubernetes API + platform_kubernetes_attributes[token]: + type: string + description: Token to authenticate against Kubernetes + platform_kubernetes_attributes[ca_cert]: + type: string + description: TLS certificate (needed if API is using a self-signed + TLS certificate) + platform_kubernetes_attributes[namespace]: + type: string + description: Unique namespace related to Project + platform_kubernetes_attributes[authorization_type]: + type: string + description: Cluster authorization type, defaults to RBAC + default: rbac + enum: + - unknown_authorization + - rbac + - abac + required: true + responses: + 201: + description: Add existing instance cluster + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Cluster' + 400: + description: Validation error + 403: + description: Forbidden + 404: + description: Not found + /api/v4/admin/clusters: + get: + tags: + - clusters + summary: List instance clusters + description: This feature was introduced in GitLab 13.2. Returns a list of instance + clusters. + operationId: getApiV4AdminClusters + responses: + 200: + description: List instance clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_Cluster' + 403: + description: Forbidden + /api/v4/admin/migrations/{timestamp}/mark: + post: + tags: + - migrations + description: Mark the migration as successfully executed + operationId: postApiV4AdminMigrationsTimestampMark + parameters: + - name: timestamp + in: path + description: The migration version timestamp + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + database: + type: string + description: The name of the database + default: main + enum: + - main + - ci + - embedding + - main_clusterwide + - geo + responses: + 201: + description: 201 Created + 401: + description: 401 Unauthorized + 403: + description: 403 Forbidden + 404: + description: 404 Not found + 422: + description: You can mark only pending migrations + /api/v4/applications/{id}: + delete: + tags: + - applications + summary: Delete an application + description: Delete a specific application + operationId: deleteApiV4ApplicationsId + parameters: + - name: id + in: path + description: The ID of the application (not the application_id) + required: true + schema: + type: integer + format: int32 + responses: + 204: + description: Delete an application + /api/v4/applications: + get: + tags: + - applications + summary: Get applications + description: List all registered applications + operationId: getApiV4Applications + responses: + 200: + description: Get applications + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_Application' + post: + tags: + - applications + summary: Create a new application + description: This feature was introduced in GitLab 10.5 + operationId: postApiV4Applications + requestBody: + content: + application/json: + schema: + required: + - name + - redirect_uri + - scopes + properties: + name: + type: string + description: Name of the application. + redirect_uri: + type: string + description: Redirect URI of the application. + scopes: + type: string + description: |- + Scopes of the application. You can specify multiple scopes by separating\ + each scope using a space + confidential: + type: boolean + description: |- + The application is used where the client secret can be kept confidential. Native mobile apps \ + and Single Page Apps are considered non-confidential. Defaults to true if not supplied + default: true + required: true + responses: + 200: + description: Create a new application + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_ApplicationWithSecret' + /api/v4/avatar: + get: + tags: + - avatar + description: Return avatar url for a user + operationId: getApiV4Avatar + parameters: + - name: email + in: query + description: Public email address of the user + required: true + schema: + type: string + - name: size + in: query + description: Single pixel dimension for Gravatar images + schema: + type: integer + format: int32 + responses: + 200: + description: Return avatar url for a user + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Avatar' + /api/v4/broadcast_messages/{id}: + get: + tags: + - broadcast_messages + summary: Get a specific broadcast message + description: This feature was introduced in GitLab 8.12. + operationId: getApiV4BroadcastMessagesId + parameters: + - name: id + in: path + description: Broadcast message ID + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Get a specific broadcast message + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BroadcastMessage' + put: + tags: + - broadcast_messages + summary: Update a broadcast message + description: This feature was introduced in GitLab 8.12. + operationId: putApiV4BroadcastMessagesId + parameters: + - name: id + in: path + description: Broadcast message ID + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + properties: + message: + type: string + description: Message to display + starts_at: + type: string + description: Starting time + format: date-time + ends_at: + type: string + description: Ending time + format: date-time + color: + type: string + description: Background color + font: + type: string + description: Foreground color + target_access_levels: + type: array + description: Target user roles + items: + type: integer + format: int32 + enum: + - 10 + - 20 + - 30 + - 40 + - 50 + target_path: + type: string + description: Target path + broadcast_type: + type: string + description: Broadcast Type + enum: + - banner + - notification + dismissable: + type: boolean + description: Is dismissable + responses: + 200: + description: Update a broadcast message + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BroadcastMessage' + delete: + tags: + - broadcast_messages + summary: Delete a broadcast message + description: This feature was introduced in GitLab 8.12. + operationId: deleteApiV4BroadcastMessagesId + parameters: + - name: id + in: path + description: Broadcast message ID + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Delete a broadcast message + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BroadcastMessage' + /api/v4/broadcast_messages: + get: + tags: + - broadcast_messages + summary: Get all broadcast messages + description: This feature was introduced in GitLab 8.12. + operationId: getApiV4BroadcastMessages + parameters: + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + responses: + 200: + description: Get all broadcast messages + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BroadcastMessage' + post: + tags: + - broadcast_messages + summary: Create a broadcast message + description: This feature was introduced in GitLab 8.12. + operationId: postApiV4BroadcastMessages + requestBody: + content: + application/json: + schema: + required: + - message + properties: + message: + type: string + description: Message to display + starts_at: + type: string + description: Starting time + format: date-time + ends_at: + type: string + description: Ending time + format: date-time + color: + type: string + description: Background color + font: + type: string + description: Foreground color + target_access_levels: + type: array + description: Target user roles + items: + type: integer + format: int32 + enum: + - 10 + - 20 + - 30 + - 40 + - 50 + target_path: + type: string + description: Target path + broadcast_type: + type: string + description: Broadcast type. Defaults to banner + enum: + - banner + - notification + dismissable: + type: boolean + description: Is dismissable + required: true + responses: + 201: + description: Create a broadcast message + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BroadcastMessage' + /api/v4/bulk_imports/{import_id}/entities/{entity_id}: + get: + tags: + - bulk_imports + summary: Get GitLab Migration entity details + description: This feature was introduced in GitLab 14.1. + operationId: getApiV4BulkImportsImportIdEntitiesEntityId + parameters: + - name: import_id + in: path + description: The ID of user's GitLab Migration + required: true + schema: + type: integer + format: int32 + - name: entity_id + in: path + description: The ID of GitLab Migration entity + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Get GitLab Migration entity details + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BulkImports' + 401: + description: Unauthorized + 404: + description: Not found + 503: + description: Service unavailable + /api/v4/bulk_imports/{import_id}/entities: + get: + tags: + - bulk_imports + summary: List GitLab Migration entities + description: This feature was introduced in GitLab 14.1. + operationId: getApiV4BulkImportsImportIdEntities + parameters: + - name: import_id + in: path + description: The ID of user's GitLab Migration + required: true + schema: + type: integer + format: int32 + - name: status + in: query + description: Return import entities with specified status + schema: + type: string + enum: + - created + - started + - finished + - timeout + - failed + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + responses: + 200: + description: List GitLab Migration entities + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_BulkImports' + 401: + description: Unauthorized + 404: + description: Not found + 503: + description: Service unavailable + /api/v4/bulk_imports/{import_id}: + get: + tags: + - bulk_imports + summary: Get GitLab Migration details + description: This feature was introduced in GitLab 14.1. + operationId: getApiV4BulkImportsImportId + parameters: + - name: import_id + in: path + description: The ID of user's GitLab Migration + required: true + schema: + type: integer + format: int32 + responses: + 200: + description: Get GitLab Migration details + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BulkImport' + 401: + description: Unauthorized + 404: + description: Not found + 503: + description: Service unavailable + /api/v4/bulk_imports/entities: + get: + tags: + - bulk_imports + summary: List all GitLab Migrations' entities + description: This feature was introduced in GitLab 14.1. + operationId: getApiV4BulkImportsEntities + parameters: + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + - name: sort + in: query + description: Return GitLab Migrations sorted in created by `asc` or `desc` + order. + schema: + type: string + default: desc + enum: + - asc + - desc + - name: status + in: query + description: Return all GitLab Migrations' entities with specified status + schema: + type: string + enum: + - created + - started + - finished + - timeout + - failed + responses: + 200: + description: List all GitLab Migrations' entities + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_BulkImports' + 401: + description: Unauthorized + 404: + description: Not found + 503: + description: Service unavailable + /api/v4/bulk_imports: + get: + tags: + - bulk_imports + summary: List all GitLab Migrations + description: This feature was introduced in GitLab 14.1. + operationId: getApiV4BulkImports + parameters: + - name: page + in: query + description: Current page number + schema: + type: integer + format: int32 + default: 1 + - name: per_page + in: query + description: Number of items per page + schema: + type: integer + format: int32 + default: 20 + - name: sort + in: query + description: Return GitLab Migrations sorted in created by `asc` or `desc` + order. + schema: + type: string + default: desc + enum: + - asc + - desc + - name: status + in: query + description: Return GitLab Migrations with specified status + schema: + type: string + enum: + - created + - started + - finished + - timeout + - failed + responses: + 200: + description: List all GitLab Migrations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/API_Entities_BulkImport' + 401: + description: Unauthorized + 404: + description: Not found + 503: + description: Service unavailable + post: + tags: + - bulk_imports + summary: Start a new GitLab Migration + description: This feature was introduced in GitLab 14.2. + operationId: postApiV4BulkImports + requestBody: + content: + application/x-www-form-urlencoded: + schema: + required: + - configuration[access_token] + - configuration[url] + - entities[destination_namespace] + - entities[source_full_path] + - entities[source_type] + properties: + configuration[url]: + type: string + description: Source GitLab instance URL + configuration[access_token]: + type: string + description: Access token to the source GitLab instance + entities[source_type]: + type: array + description: Source entity type + items: + type: string + enum: + - group_entity + - project_entity + entities[source_full_path]: + type: array + description: Relative path of the source entity to import + items: + type: string + entities[destination_namespace]: + type: array + description: Destination namespace for the entity + items: + type: string + entities[destination_slug]: + type: array + description: Destination slug for the entity + items: + type: string + entities[destination_name]: + type: array + description: 'Deprecated: Use :destination_slug instead. Destination + slug for the entity' + items: + type: string + entities[migrate_projects]: + type: array + description: Indicates group migration should include nested projects + items: + type: boolean + required: true + responses: + 200: + description: Start a new GitLab Migration + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_BulkImport' + 400: + description: Bad request + 401: + description: Unauthorized + 404: + description: Not found + 422: + description: Unprocessable entity + 503: + description: Service unavailable + /api/v4/application/appearance: + get: + tags: + - application + description: Get the current appearance + operationId: getApiV4ApplicationAppearance + responses: + 200: + description: Get the current appearance + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Appearance' + put: + tags: + - application + description: Modify appearance + operationId: putApiV4ApplicationAppearance + requestBody: + content: + multipart/form-data: + schema: + properties: + title: + type: string + description: Instance title on the sign in / sign up page + description: + type: string + description: Markdown text shown on the sign in / sign up page + pwa_name: + type: string + description: Name of the Progressive Web App + pwa_short_name: + type: string + description: Optional, short name for Progressive Web App + pwa_description: + type: string + description: An explanation of what the Progressive Web App does + logo: + type: string + description: Instance image used on the sign in / sign up page + format: binary + pwa_icon: + type: string + description: Icon used for Progressive Web App + format: binary + header_logo: + type: string + description: Instance image used for the main navigation bar + format: binary + favicon: + type: string + description: Instance favicon in .ico/.png format + format: binary + new_project_guidelines: + type: string + description: Markdown text shown on the new project page + profile_image_guidelines: + type: string + description: Markdown text shown on the profile page below Public + Avatar + header_message: + type: string + description: Message within the system header bar + footer_message: + type: string + description: Message within the system footer bar + message_background_color: + type: string + description: Background color for the system header / footer bar + message_font_color: + type: string + description: Font color for the system header / footer bar + email_header_and_footer_enabled: + type: boolean + description: Add header and footer to all outgoing emails if enabled + responses: + 200: + description: Modify appearance + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Appearance' + /api/v4/application/plan_limits: + get: + tags: + - plan_limits + summary: Get current plan limits + description: List the current limits of a plan on the GitLab instance. + operationId: getApiV4ApplicationPlanLimits + parameters: + - name: plan_name + in: query + description: 'Name of the plan to get the limits from. Default: default.' + schema: + type: string + default: default + enum: + - default + - free + - bronze + - silver + - premium + - gold + - ultimate + - ultimate_trial + - premium_trial + - opensource + responses: + 200: + description: Get current plan limits + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_PlanLimit' + 401: + description: Unauthorized + 403: + description: Forbidden + put: + tags: + - plan_limits + summary: Change plan limits + description: Modify the limits of a plan on the GitLab instance. + operationId: putApiV4ApplicationPlanLimits + requestBody: + content: + application/json: + schema: + required: + - plan_name + properties: + plan_name: + type: string + description: Name of the plan to update + enum: + - default + - free + - bronze + - silver + - premium + - gold + - ultimate + - ultimate_trial + - premium_trial + - opensource + ci_pipeline_size: + type: integer + description: Maximum number of jobs in a single pipeline + format: int32 + ci_active_jobs: + type: integer + description: Total number of jobs in currently active pipelines + format: int32 + ci_project_subscriptions: + type: integer + description: Maximum number of pipeline subscriptions to and from + a project + format: int32 + ci_pipeline_schedules: + type: integer + description: Maximum number of pipeline schedules + format: int32 + ci_needs_size_limit: + type: integer + description: Maximum number of DAG dependencies that a job can have + format: int32 + ci_registered_group_runners: + type: integer + description: Maximum number of runners registered per group + format: int32 + ci_registered_project_runners: + type: integer + description: Maximum number of runners registered per project + format: int32 + conan_max_file_size: + type: integer + description: Maximum Conan package file size in bytes + format: int32 + enforcement_limit: + type: integer + description: Maximum storage size for the root namespace enforcement + in MiB + format: int32 + generic_packages_max_file_size: + type: integer + description: Maximum generic package file size in bytes + format: int32 + helm_max_file_size: + type: integer + description: Maximum Helm chart file size in bytes + format: int32 + maven_max_file_size: + type: integer + description: Maximum Maven package file size in bytes + format: int32 + notification_limit: + type: integer + description: Maximum storage size for the root namespace notifications + in MiB + format: int32 + npm_max_file_size: + type: integer + description: Maximum NPM package file size in bytes + format: int32 + nuget_max_file_size: + type: integer + description: Maximum NuGet package file size in bytes + format: int32 + pypi_max_file_size: + type: integer + description: Maximum PyPI package file size in bytes + format: int32 + terraform_module_max_file_size: + type: integer + description: Maximum Terraform Module package file size in bytes + format: int32 + storage_size_limit: + type: integer + description: Maximum storage size for the root namespace in MiB + format: int32 + pipeline_hierarchy_size: + type: integer + description: Maximum number of downstream pipelines in a pipeline's + hierarchy tree + format: int32 + required: true + responses: + 200: + description: Change plan limits + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_PlanLimit' + 400: + description: Bad request + 401: + description: Unauthorized + 403: + description: Forbidden + /api/v4/metadata: + get: + tags: + - metadata + summary: Retrieve metadata information for this GitLab instance + description: This feature was introduced in GitLab 15.2. + operationId: getApiV4Metadata + responses: + 200: + description: Retrieve metadata information for this GitLab instance + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Metadata' + 401: + description: Unauthorized + /api/v4/version: + get: + tags: + - metadata + summary: Retrieves version information for the GitLab instance + description: This feature was introduced in GitLab 8.13 and deprecated in 15.5. + We recommend you instead use the Metadata API. + operationId: getApiV4Version + responses: + 200: + description: Retrieves version information for the GitLab instance + content: + application/json: + schema: + $ref: '#/components/schemas/API_Entities_Metadata' + 401: + description: Unauthorized +components: + schemas: + API_Entities_Badge: + type: object + properties: + name: + type: string + link_url: + type: string + image_url: + type: string + rendered_link_url: + type: string + rendered_image_url: + type: string + id: + type: string + kind: + type: string + description: API_Entities_Badge model + API_Entities_BasicBadgeDetails: + type: object + properties: + name: + type: string + link_url: + type: string + image_url: + type: string + rendered_link_url: + type: string + rendered_image_url: + type: string + description: API_Entities_BasicBadgeDetails model + API_Entities_AccessRequester: + type: object + properties: + id: + type: integer + format: int32 + example: 1 + username: + type: string + example: admin + name: + type: string + example: Administrator + state: + type: string + example: active + avatar_url: + type: string + example: https://gravatar.com/avatar/1 + avatar_path: + type: string + example: /user/avatar/28/The-Big-Lebowski-400-400.png + custom_attributes: + type: array + items: + $ref: '#/components/schemas/API_Entities_CustomAttribute' + web_url: + type: string + example: https://gitlab.example.com/root + email: + type: string + requested_at: + type: string + description: API_Entities_AccessRequester model + API_Entities_CustomAttribute: + type: object + properties: + key: + type: string + example: foo + value: + type: string + example: bar + API_Entities_Branch: + type: object + properties: + name: + type: string + example: master + commit: + $ref: '#/components/schemas/API_Entities_Commit' + merged: + type: boolean + example: true + protected: + type: boolean + example: true + developers_can_push: + type: boolean + example: true + developers_can_merge: + type: boolean + example: true + can_push: + type: boolean + example: true + default: + type: boolean + example: true + web_url: + type: string + example: https://gitlab.example.com/Commit921/the-dude/-/tree/master + description: API_Entities_Branch model + API_Entities_Commit: + type: object + properties: + id: + type: string + example: 2695effb5807a22ff3d138d593fd856244e155e7 + short_id: + type: string + example: 2695effb + created_at: + type: string + format: date-time + example: 2017-07-26T11:08:53+02:00 + parent_ids: + type: array + items: + type: string + example: 2a4b78934375d7f53875269ffd4f45fd83a84ebe + title: + type: string + example: Initial commit + message: + type: string + example: Initial commit + author_name: + type: string + example: John Smith + author_email: + type: string + example: john@example.com + authored_date: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + committer_name: + type: string + example: Jack Smith + committer_email: + type: string + example: jack@example.com + committed_date: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + trailers: + type: object + properties: {} + example: '{ "Merged-By": "Jane Doe janedoe@gitlab.com" }' + web_url: + type: string + example: https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746 + API_Entities_MetricImage: + type: object + properties: + id: + type: integer + format: int32 + example: 23 + created_at: + type: string + format: date-time + example: 2020-11-13T00:06:18.084Z + filename: + type: string + example: file.png + file_path: + type: string + example: /uploads/-/system/alert_metric_image/file/23/file.png + url: + type: string + example: https://example.com/metric + url_text: + type: string + example: An example metric + description: API_Entities_MetricImage model + API_Entities_BatchedBackgroundMigration: + type: object + properties: + id: + type: string + example: "1234" + job_class_name: + type: string + example: CopyColumnUsingBackgroundMigrationJob + table_name: + type: string + example: events + status: + type: string + example: active + progress: + type: number + format: float + example: 50.0 + created_at: + type: string + format: date-time + example: 2022-11-28T16:26:39+02:00 + description: API_Entities_BatchedBackgroundMigration model + API_Entities_Ci_Variable: + type: object + properties: + variable_type: + type: string + example: env_var + key: + type: string + example: TEST_VARIABLE_1 + value: + type: string + example: TEST_1 + protected: + type: boolean + masked: + type: boolean + raw: + type: boolean + environment_scope: + type: string + example: '*' + description: API_Entities_Ci_Variable model + API_Entities_Dictionary_Table: + type: object + properties: + table_name: + type: string + example: users + feature_categories: + type: array + items: + type: string + example: database + description: API_Entities_Dictionary_Table model + API_Entities_Cluster: + type: object + properties: + id: + type: string + name: + type: string + created_at: + type: string + domain: + type: string + enabled: + type: string + managed: + type: string + provider_type: + type: string + platform_type: + type: string + environment_scope: + type: string + cluster_type: + type: string + namespace_per_environment: + type: string + user: + $ref: '#/components/schemas/API_Entities_UserBasic' + platform_kubernetes: + $ref: '#/components/schemas/API_Entities_Platform_Kubernetes' + provider_gcp: + $ref: '#/components/schemas/API_Entities_Provider_Gcp' + management_project: + $ref: '#/components/schemas/API_Entities_ProjectIdentity' + description: API_Entities_Cluster model + API_Entities_UserBasic: + type: object + properties: + id: + type: integer + format: int32 + example: 1 + username: + type: string + example: admin + name: + type: string + example: Administrator + state: + type: string + example: active + avatar_url: + type: string + example: https://gravatar.com/avatar/1 + avatar_path: + type: string + example: /user/avatar/28/The-Big-Lebowski-400-400.png + custom_attributes: + type: array + items: + $ref: '#/components/schemas/API_Entities_CustomAttribute' + web_url: + type: string + example: https://gitlab.example.com/root + email: + type: string + API_Entities_Platform_Kubernetes: + type: object + properties: + api_url: + type: string + namespace: + type: string + authorization_type: + type: string + ca_cert: + type: string + API_Entities_Provider_Gcp: + type: object + properties: + cluster_id: + type: string + status_name: + type: string + gcp_project_id: + type: string + zone: + type: string + machine_type: + type: string + num_nodes: + type: string + endpoint: + type: string + API_Entities_ProjectIdentity: + type: object + properties: + id: + type: integer + format: int32 + example: 1 + description: + type: string + example: desc + name: + type: string + example: project1 + name_with_namespace: + type: string + example: John Doe / project1 + path: + type: string + example: project1 + path_with_namespace: + type: string + example: namespace1/project1 + created_at: + type: string + format: date-time + example: 2020-05-07T04:27:17.016Z + API_Entities_Application: + type: object + properties: + id: + type: string + application_id: + type: string + example: 5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737 + application_name: + type: string + example: MyApplication + callback_url: + type: string + example: https://redirect.uri + confidential: + type: boolean + example: true + description: API_Entities_Application model + API_Entities_ApplicationWithSecret: + type: object + properties: + id: + type: string + application_id: + type: string + example: 5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737 + application_name: + type: string + example: MyApplication + callback_url: + type: string + example: https://redirect.uri + confidential: + type: boolean + example: true + secret: + type: string + example: ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34 + description: API_Entities_ApplicationWithSecret model + API_Entities_Avatar: + type: object + properties: + avatar_url: + type: string + description: API_Entities_Avatar model + API_Entities_BroadcastMessage: + type: object + properties: + id: + type: string + message: + type: string + starts_at: + type: string + ends_at: + type: string + color: + type: string + font: + type: string + target_access_levels: + type: string + target_path: + type: string + broadcast_type: + type: string + dismissable: + type: string + active: + type: string + description: API_Entities_BroadcastMessage model + API_Entities_BulkImports: + type: object + properties: + id: + type: integer + format: int32 + example: 1 + bulk_import_id: + type: integer + format: int32 + example: 1 + status: + type: string + example: created + enum: + - created + - started + - finished + - timeout + - failed + entity_type: + type: string + enum: + - group + - project + source_full_path: + type: string + example: source_group + destination_full_path: + type: string + example: some_group/source_project + destination_name: + type: string + example: destination_slug + destination_slug: + type: string + example: destination_slug + destination_namespace: + type: string + example: destination_path + parent_id: + type: integer + format: int32 + example: 1 + namespace_id: + type: integer + format: int32 + example: 1 + project_id: + type: integer + format: int32 + example: 1 + created_at: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + updated_at: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + failures: + type: array + items: + $ref: '#/components/schemas/API_Entities_BulkImports_EntityFailure' + migrate_projects: + type: boolean + example: true + description: API_Entities_BulkImports model + API_Entities_BulkImports_EntityFailure: + type: object + properties: + relation: + type: string + example: group + step: + type: string + example: extractor + exception_message: + type: string + example: error message + exception_class: + type: string + example: Exception + correlation_id_value: + type: string + example: dfcf583058ed4508e4c7c617bd7f0edd + created_at: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + pipeline_class: + type: string + example: BulkImports::Groups::Pipelines::GroupPipeline + pipeline_step: + type: string + example: extractor + API_Entities_BulkImport: + type: object + properties: + id: + type: integer + format: int32 + example: 1 + status: + type: string + example: finished + enum: + - created + - started + - finished + - timeout + - failed + source_type: + type: string + example: gitlab + created_at: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + updated_at: + type: string + format: date-time + example: 2012-05-28T04:42:42-07:00 + description: API_Entities_BulkImport model + API_Entities_Appearance: + type: object + properties: + title: + type: string + description: + type: string + pwa_name: + type: string + pwa_short_name: + type: string + pwa_description: + type: string + logo: + type: string + pwa_icon: + type: string + header_logo: + type: string + favicon: + type: string + new_project_guidelines: + type: string + profile_image_guidelines: + type: string + header_message: + type: string + footer_message: + type: string + message_background_color: + type: string + message_font_color: + type: string + email_header_and_footer_enabled: + type: string + description: API_Entities_Appearance model + API_Entities_PlanLimit: + type: object + properties: + ci_pipeline_size: + type: integer + format: int32 + example: 0 + ci_active_jobs: + type: integer + format: int32 + example: 0 + ci_project_subscriptions: + type: integer + format: int32 + example: 2 + ci_pipeline_schedules: + type: integer + format: int32 + example: 10 + ci_needs_size_limit: + type: integer + format: int32 + example: 50 + ci_registered_group_runners: + type: integer + format: int32 + example: 1000 + ci_registered_project_runners: + type: integer + format: int32 + example: 1000 + conan_max_file_size: + type: integer + format: int32 + example: 3221225472 + enforcement_limit: + type: integer + format: int32 + example: 15000 + generic_packages_max_file_size: + type: integer + format: int32 + example: 5368709120 + helm_max_file_size: + type: integer + format: int32 + example: 5242880 + limits_history: + type: object + properties: {} + example: |- + {"enforcement_limit"=>[{"timestamp"=>1686909124, "user_id"=>1, "username"=>"x", "value"=>5}], + "notification_limit"=>[{"timestamp"=>1686909124, "user_id"=>2, "username"=>"y", "value"=>7}]} + maven_max_file_size: + type: integer + format: int32 + example: 3221225472 + notification_limit: + type: integer + format: int32 + example: 15000 + npm_max_file_size: + type: integer + format: int32 + example: 524288000 + nuget_max_file_size: + type: integer + format: int32 + example: 524288000 + pipeline_hierarchy_size: + type: integer + format: int32 + example: 1000 + pypi_max_file_size: + type: integer + format: int32 + example: 3221225472 + terraform_module_max_file_size: + type: integer + format: int32 + example: 1073741824 + storage_size_limit: + type: integer + format: int32 + example: 15000 + description: API_Entities_PlanLimit model + API_Entities_Metadata: + type: object + properties: + version: + type: string + example: 15.2-pre + revision: + type: string + example: c401a659d0c + kas: + type: object + properties: + enabled: + type: boolean + externalUrl: + type: string + example: grpc://gitlab.example.com:8150 + version: + type: string + example: 15.0.0 + enterprise: + type: boolean + description: API_Entities_Metadata model + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: Private-Token