From 64308b41dda7ee85bc3f88964439d33684089d6e Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 12:11:01 +0900 Subject: [PATCH 01/11] feat(BA-5119): add Strawberry GQL node type for ContainerRegistry Add ContainerRegistryGQL and ContainerRegistryTypeGQL types for the GraphQL API. Register ContainerRegistryGQL in the EntityNode union and resolve it in EntityRefGQL.entity() via container_registry_loader. Co-Authored-By: Claude Opus 4.6 --- .../api/gql/container_registry/__init__.py | 11 +++ .../api/gql/container_registry/types.py | 89 +++++++++++++++++++ .../manager/api/gql/rbac/types/entity.py | 9 +- .../manager/api/gql/rbac/types/entity_node.py | 2 + 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/ai/backend/manager/api/gql/container_registry/__init__.py create mode 100644 src/ai/backend/manager/api/gql/container_registry/types.py diff --git a/src/ai/backend/manager/api/gql/container_registry/__init__.py b/src/ai/backend/manager/api/gql/container_registry/__init__.py new file mode 100644 index 00000000000..fd6fa27f7cd --- /dev/null +++ b/src/ai/backend/manager/api/gql/container_registry/__init__.py @@ -0,0 +1,11 @@ +"""GraphQL container registry module.""" + +from .types import ( + ContainerRegistryGQL, + ContainerRegistryTypeGQL, +) + +__all__ = ( + "ContainerRegistryGQL", + "ContainerRegistryTypeGQL", +) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py new file mode 100644 index 00000000000..1bd378e3cd1 --- /dev/null +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -0,0 +1,89 @@ +"""GraphQL types for container registry.""" + +from __future__ import annotations + +from collections.abc import Iterable +from enum import StrEnum +from typing import Self +from uuid import UUID + +import strawberry +from strawberry import Info +from strawberry.relay import Node, NodeID + +from ai.backend.common.container_registry import ContainerRegistryType +from ai.backend.manager.api.gql.types import StrawberryGQLContext +from ai.backend.manager.data.container_registry.types import ContainerRegistryData +from ai.backend.manager.defs import PASSWORD_PLACEHOLDER + + +@strawberry.enum(description="Added in 26.3.0. Container registry type.") +class ContainerRegistryTypeGQL(StrEnum): + DOCKER = "docker" + HARBOR = "harbor" + HARBOR2 = "harbor2" + GITHUB = "github" + GITLAB = "gitlab" + ECR = "ecr" + ECR_PUB = "ecr-public" + LOCAL = "local" + OCP = "ocp" + + @classmethod + def from_enum(cls, value: ContainerRegistryType) -> ContainerRegistryTypeGQL: + return cls(value.value) + + +@strawberry.type( + name="ContainerRegistry", + description="Added in 26.3.0. Container registry node.", +) +class ContainerRegistryGQL(Node): + id: NodeID[str] = strawberry.field( + description="Relay-style global node identifier for the container registry" + ) + url: str = strawberry.field(description="URL of the container registry") + registry_name: str = strawberry.field(description="Name of the container registry") + type: ContainerRegistryTypeGQL = strawberry.field(description="Type of the container registry") + project: str | None = strawberry.field( + description="Project or namespace within the registry", default=None + ) + username: str | None = strawberry.field( + description="Username for registry authentication", default=None + ) + password: str | None = strawberry.field( + description="Masked password for registry authentication", default=None + ) + ssl_verify: bool | None = strawberry.field( + description="Whether SSL verification is enabled", default=None + ) + is_global: bool | None = strawberry.field( + description="Whether this registry is globally accessible", default=None + ) + + @classmethod + async def resolve_nodes( # type: ignore[override] # Strawberry Node uses AwaitableOrValue overloads incompatible with async def + cls, + *, + info: Info[StrawberryGQLContext], + node_ids: Iterable[str], + required: bool = False, + ) -> Iterable[Self | None]: + results = await info.context.data_loaders.container_registry_loader.load_many([ + UUID(nid) for nid in node_ids + ]) + return [cls.from_data(data) if data is not None else None for data in results] + + @classmethod + def from_data(cls, data: ContainerRegistryData) -> Self: + return cls( + id=str(data.id), + url=data.url, + registry_name=data.registry_name, + type=ContainerRegistryTypeGQL.from_enum(data.type), + project=data.project, + username=data.username, + password=PASSWORD_PLACEHOLDER if data.password else None, + ssl_verify=data.ssl_verify, + is_global=data.is_global, + ) diff --git a/src/ai/backend/manager/api/gql/rbac/types/entity.py b/src/ai/backend/manager/api/gql/rbac/types/entity.py index 4969daf7994..08fff1758a6 100644 --- a/src/ai/backend/manager/api/gql/rbac/types/entity.py +++ b/src/ai/backend/manager/api/gql/rbac/types/entity.py @@ -65,6 +65,7 @@ async def entity( ) -> EntityNode | None: from ai.backend.common.types import ImageID from ai.backend.manager.api.gql.artifact.types import ArtifactRevision + from ai.backend.manager.api.gql.container_registry.types import ContainerRegistryGQL from ai.backend.manager.api.gql.deployment.types.deployment import ModelDeployment from ai.backend.manager.api.gql.domain_v2.types.node import DomainV2GQL from ai.backend.manager.api.gql.image.types import ImageV2GQL @@ -138,12 +139,18 @@ async def entity( if rev_data is None: return None return ArtifactRevision.from_dataclass(rev_data) + case RBACElementType.CONTAINER_REGISTRY: + cr_data = await data_loaders.container_registry_loader.load( + uuid.UUID(self.entity_id) + ) + if cr_data is None: + return None + return ContainerRegistryGQL.from_data(cr_data) case ( RBACElementType.SESSION | RBACElementType.VFOLDER | RBACElementType.KEYPAIR | RBACElementType.NETWORK - | RBACElementType.CONTAINER_REGISTRY | RBACElementType.STORAGE_HOST | RBACElementType.ARTIFACT | RBACElementType.ARTIFACT_REGISTRY diff --git a/src/ai/backend/manager/api/gql/rbac/types/entity_node.py b/src/ai/backend/manager/api/gql/rbac/types/entity_node.py index f2c98403b8e..95e8936c785 100644 --- a/src/ai/backend/manager/api/gql/rbac/types/entity_node.py +++ b/src/ai/backend/manager/api/gql/rbac/types/entity_node.py @@ -13,6 +13,7 @@ from ai.backend.manager.api.gql.app_config import AppConfig from ai.backend.manager.api.gql.artifact.types import Artifact, ArtifactRevision from ai.backend.manager.api.gql.artifact_registry import ArtifactRegistry +from ai.backend.manager.api.gql.container_registry.types import ContainerRegistryGQL from ai.backend.manager.api.gql.deployment.types.deployment import ModelDeployment from ai.backend.manager.api.gql.domain_v2.types.node import DomainV2GQL from ai.backend.manager.api.gql.image.types import ImageV2GQL @@ -45,6 +46,7 @@ | NotificationRule | ModelDeployment | ResourceGroupGQL + | ContainerRegistryGQL | ArtifactRevision | RoleGQL, strawberry.union("EntityNode"), From dd58fad552140859cf0a92483bdb8e586e3b1472 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 12:11:45 +0900 Subject: [PATCH 02/11] changelog: add news fragment for PR #10093 --- changes/10093.feature.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/10093.feature.md diff --git a/changes/10093.feature.md b/changes/10093.feature.md new file mode 100644 index 00000000000..3b9edab77d7 --- /dev/null +++ b/changes/10093.feature.md @@ -0,0 +1 @@ +Add Strawberry GraphQL node type for ContainerRegistry to support RBAC entity resolution From c6a69bf9ab27a67453035bb07901682b5317dbce Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 12:19:19 +0900 Subject: [PATCH 03/11] fix(BA-5119): set enum name and fix password masking condition Add name="ContainerRegistryType" to the strawberry enum decorator and use `is not None` for password masking to handle empty strings. Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/container_registry/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py index 1bd378e3cd1..a4756c9a1b5 100644 --- a/src/ai/backend/manager/api/gql/container_registry/types.py +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -17,7 +17,7 @@ from ai.backend.manager.defs import PASSWORD_PLACEHOLDER -@strawberry.enum(description="Added in 26.3.0. Container registry type.") +@strawberry.enum(name="ContainerRegistryType", description="Added in 26.3.0. Container registry type.") class ContainerRegistryTypeGQL(StrEnum): DOCKER = "docker" HARBOR = "harbor" @@ -83,7 +83,7 @@ def from_data(cls, data: ContainerRegistryData) -> Self: type=ContainerRegistryTypeGQL.from_enum(data.type), project=data.project, username=data.username, - password=PASSWORD_PLACEHOLDER if data.password else None, + password=PASSWORD_PLACEHOLDER if data.password is not None else None, ssl_verify=data.ssl_verify, is_global=data.is_global, ) From 646a9abff680a6e30b889b9662845063cb9ff68b Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 12:45:14 +0900 Subject: [PATCH 04/11] chore(BA-5119): apply ruff formatting Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/container_registry/types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py index a4756c9a1b5..b09ea80a6c0 100644 --- a/src/ai/backend/manager/api/gql/container_registry/types.py +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -17,7 +17,9 @@ from ai.backend.manager.defs import PASSWORD_PLACEHOLDER -@strawberry.enum(name="ContainerRegistryType", description="Added in 26.3.0. Container registry type.") +@strawberry.enum( + name="ContainerRegistryType", description="Added in 26.3.0. Container registry type." +) class ContainerRegistryTypeGQL(StrEnum): DOCKER = "docker" HARBOR = "harbor" From 943edd41b6ae53b9a2cb106cafd1be6fc729a9e2 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 12:47:32 +0900 Subject: [PATCH 05/11] fix(BA-5119): rename GQL type to ContainerRegistryV2 to avoid supergraph conflict The legacy Graphene schema already defines a ContainerRegistry type. Use ContainerRegistryV2 to avoid INVALID_FIELD_SHARING in federation. Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/container_registry/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py index b09ea80a6c0..7101d9eac8c 100644 --- a/src/ai/backend/manager/api/gql/container_registry/types.py +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -37,7 +37,7 @@ def from_enum(cls, value: ContainerRegistryType) -> ContainerRegistryTypeGQL: @strawberry.type( - name="ContainerRegistry", + name="ContainerRegistryV2", description="Added in 26.3.0. Container registry node.", ) class ContainerRegistryGQL(Node): From ae58e9bbeb28706ffa8cb9cc38486dd96709e9b2 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 03:50:54 +0000 Subject: [PATCH 06/11] chore: update api schema dump Co-authored-by: octodog --- .../graphql-reference/supergraph.graphql | 51 ++++++++++++++++++- .../graphql-reference/v2-schema.graphql | 45 +++++++++++++++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/docs/manager/graphql-reference/supergraph.graphql b/docs/manager/graphql-reference/supergraph.graphql index 1ca1d447765..9eb8576811f 100644 --- a/docs/manager/graphql-reference/supergraph.graphql +++ b/docs/manager/graphql-reference/supergraph.graphql @@ -2391,10 +2391,58 @@ input ContainerRegistryScope scalar ContainerRegistryScopeField @join__type(graph: GRAPHENE) +"""Added in 26.3.0. Container registry type.""" +enum ContainerRegistryType + @join__type(graph: STRAWBERRY) +{ + DOCKER @join__enumValue(graph: STRAWBERRY) + HARBOR @join__enumValue(graph: STRAWBERRY) + HARBOR2 @join__enumValue(graph: STRAWBERRY) + GITHUB @join__enumValue(graph: STRAWBERRY) + GITLAB @join__enumValue(graph: STRAWBERRY) + ECR @join__enumValue(graph: STRAWBERRY) + ECR_PUB @join__enumValue(graph: STRAWBERRY) + LOCAL @join__enumValue(graph: STRAWBERRY) + OCP @join__enumValue(graph: STRAWBERRY) +} + """Added in 24.09.0.""" scalar ContainerRegistryTypeField @join__type(graph: GRAPHENE) +"""Added in 26.3.0. Container registry node.""" +type ContainerRegistryV2 implements Node + @join__implements(graph: STRAWBERRY, interface: "Node") + @join__type(graph: STRAWBERRY) +{ + """The Globally Unique ID of this object""" + id: ID! + + """URL of the container registry""" + url: String! + + """Name of the container registry""" + registryName: String! + + """Type of the container registry""" + type: ContainerRegistryType! + + """Project or namespace within the registry""" + project: String + + """Username for registry authentication""" + username: String + + """Masked password for registry authentication""" + password: String + + """Whether SSL verification is enabled""" + sslVerify: Boolean + + """Whether this registry is globally accessible""" + isGlobal: Boolean +} + """Added in 25.6.0.""" type ContainerUtilizationMetric @join__type(graph: GRAPHENE) @@ -4595,9 +4643,10 @@ union EntityNode @join__unionMember(graph: STRAWBERRY, member: "NotificationRule") @join__unionMember(graph: STRAWBERRY, member: "ModelDeployment") @join__unionMember(graph: STRAWBERRY, member: "ResourceGroup") + @join__unionMember(graph: STRAWBERRY, member: "ContainerRegistryV2") @join__unionMember(graph: STRAWBERRY, member: "ArtifactRevision") @join__unionMember(graph: STRAWBERRY, member: "Role") - = UserV2 | ProjectV2 | DomainV2 | VirtualFolderNode | ImageV2 | ComputeSessionNode | Artifact | ArtifactRegistry | AppConfig | NotificationChannel | NotificationRule | ModelDeployment | ResourceGroup | ArtifactRevision | Role + = UserV2 | ProjectV2 | DomainV2 | VirtualFolderNode | ImageV2 | ComputeSessionNode | Artifact | ArtifactRegistry | AppConfig | NotificationChannel | NotificationRule | ModelDeployment | ResourceGroup | ContainerRegistryV2 | ArtifactRevision | Role """Added in 26.3.0. Order by specification for entity associations""" input EntityOrderBy diff --git a/docs/manager/graphql-reference/v2-schema.graphql b/docs/manager/graphql-reference/v2-schema.graphql index 0d6c4e6e35d..9ce613856c7 100644 --- a/docs/manager/graphql-reference/v2-schema.graphql +++ b/docs/manager/graphql-reference/v2-schema.graphql @@ -1415,6 +1415,49 @@ input ContainerRegistryScope { registryId: UUID! } +"""Added in 26.3.0. Container registry type.""" +enum ContainerRegistryType { + DOCKER + HARBOR + HARBOR2 + GITHUB + GITLAB + ECR + ECR_PUB + LOCAL + OCP +} + +"""Added in 26.3.0. Container registry node.""" +type ContainerRegistryV2 implements Node { + """The Globally Unique ID of this object""" + id: ID! + + """URL of the container registry""" + url: String! + + """Name of the container registry""" + registryName: String! + + """Type of the container registry""" + type: ContainerRegistryType! + + """Project or namespace within the registry""" + project: String + + """Username for registry authentication""" + username: String + + """Masked password for registry authentication""" + password: String + + """Whether SSL verification is enabled""" + sslVerify: Boolean + + """Whether this registry is globally accessible""" + isGlobal: Boolean +} + input CreateAccessTokenInput { """ Added in 25.16.0: The ID of the model deployment for which the access token is created. @@ -2631,7 +2674,7 @@ input EntityFilter { NOT: [EntityFilter!] = null } -union EntityNode = UserV2 | ProjectV2 | DomainV2 | VirtualFolderNode | ImageV2 | ComputeSessionNode | Artifact | ArtifactRegistry | AppConfig | NotificationChannel | NotificationRule | ModelDeployment | ResourceGroup | ArtifactRevision | Role +union EntityNode = UserV2 | ProjectV2 | DomainV2 | VirtualFolderNode | ImageV2 | ComputeSessionNode | Artifact | ArtifactRegistry | AppConfig | NotificationChannel | NotificationRule | ModelDeployment | ResourceGroup | ContainerRegistryV2 | ArtifactRevision | Role """Added in 26.3.0. Order by specification for entity associations""" input EntityOrderBy { From c1e9aa13ecff5464064575dc684c75a1f2789494 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Mon, 16 Mar 2026 13:45:21 +0900 Subject: [PATCH 07/11] test(BA-5119): add enum sync guard for ContainerRegistryTypeGQL Ensures ContainerRegistryTypeGQL stays in sync with the internal ContainerRegistryType enum to catch drift early. Co-Authored-By: Claude Opus 4.6 --- .../gql/test_container_registry_type_sync.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/unit/manager/api/gql/test_container_registry_type_sync.py diff --git a/tests/unit/manager/api/gql/test_container_registry_type_sync.py b/tests/unit/manager/api/gql/test_container_registry_type_sync.py new file mode 100644 index 00000000000..77f29e4806d --- /dev/null +++ b/tests/unit/manager/api/gql/test_container_registry_type_sync.py @@ -0,0 +1,26 @@ +"""Sync guard: ContainerRegistryTypeGQL must cover all ContainerRegistryType members. + +Prevents enum drift between the internal ContainerRegistryType and its GraphQL +mirror from silently reaching production as a runtime ValueError. +""" + +from __future__ import annotations + +from ai.backend.common.container_registry import ContainerRegistryType +from ai.backend.manager.api.gql.container_registry.types import ContainerRegistryTypeGQL + + +class TestContainerRegistryTypeEnumSync: + def test_gql_enum_covers_all_internal_members(self) -> None: + internal_values = {member.value for member in ContainerRegistryType} + gql_values = {member.value for member in ContainerRegistryTypeGQL} + missing = internal_values - gql_values + assert not missing, ( + f"ContainerRegistryTypeGQL is missing members present in ContainerRegistryType: {missing}. " + f"Add them to ContainerRegistryTypeGQL to keep the enums in sync." + ) + + def test_from_enum_roundtrip_for_all_members(self) -> None: + for member in ContainerRegistryType: + gql_member = ContainerRegistryTypeGQL.from_enum(member) + assert gql_member.value == member.value From 2041cb65f20879acb5c3297ff333deb061a4d3e6 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Tue, 17 Mar 2026 14:06:47 +0900 Subject: [PATCH 08/11] feat(BA-5119): add extra field to ContainerRegistryGQL node Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/container_registry/types.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py index 7101d9eac8c..95ae0ae5395 100644 --- a/src/ai/backend/manager/api/gql/container_registry/types.py +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -10,6 +10,7 @@ import strawberry from strawberry import Info from strawberry.relay import Node, NodeID +from strawberry.scalars import JSON from ai.backend.common.container_registry import ContainerRegistryType from ai.backend.manager.api.gql.types import StrawberryGQLContext @@ -62,6 +63,9 @@ class ContainerRegistryGQL(Node): is_global: bool | None = strawberry.field( description="Whether this registry is globally accessible", default=None ) + extra: JSON | None = strawberry.field( + description="Extra metadata for the container registry", default=None + ) @classmethod async def resolve_nodes( # type: ignore[override] # Strawberry Node uses AwaitableOrValue overloads incompatible with async def @@ -88,4 +92,5 @@ def from_data(cls, data: ContainerRegistryData) -> Self: password=PASSWORD_PLACEHOLDER if data.password is not None else None, ssl_verify=data.ssl_verify, is_global=data.is_global, + extra=data.extra, ) From 5141c048bb3682c2cb48574ee1a520d3810ea806 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Tue, 17 Mar 2026 14:20:31 +0900 Subject: [PATCH 09/11] feat(BA-5119): add CONTAINER_REGISTRY case to PermissionGQL.scope() resolver Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/rbac/types/permission.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ai/backend/manager/api/gql/rbac/types/permission.py b/src/ai/backend/manager/api/gql/rbac/types/permission.py index 1f1d46ae181..8729b255040 100644 --- a/src/ai/backend/manager/api/gql/rbac/types/permission.py +++ b/src/ai/backend/manager/api/gql/rbac/types/permission.py @@ -187,6 +187,7 @@ async def scope( info: Info[StrawberryGQLContext], ) -> EntityNode | None: from ai.backend.manager.api.gql.artifact.types import ArtifactRevision + from ai.backend.manager.api.gql.container_registry.types import ContainerRegistryGQL from ai.backend.manager.api.gql.deployment.types.deployment import ModelDeployment from ai.backend.manager.api.gql.domain_v2.types.node import DomainV2GQL from ai.backend.manager.api.gql.project_v2.types.node import ProjectV2GQL @@ -234,13 +235,19 @@ async def scope( if rev_data is None: return None return ArtifactRevision.from_dataclass(rev_data) + case RBACElementType.CONTAINER_REGISTRY: + cr_data = await data_loaders.container_registry_loader.load( + uuid.UUID(self.scope_id) + ) + if cr_data is None: + return None + return ContainerRegistryGQL.from_data(cr_data) case ( RBACElementType.SESSION | RBACElementType.VFOLDER | RBACElementType.KEYPAIR | RBACElementType.NOTIFICATION_CHANNEL | RBACElementType.NETWORK - | RBACElementType.CONTAINER_REGISTRY | RBACElementType.STORAGE_HOST | RBACElementType.IMAGE | RBACElementType.ARTIFACT From 4ab2123592f45bb5ee8d0a5f9c259e054bcd7fe0 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Tue, 17 Mar 2026 14:46:21 +0900 Subject: [PATCH 10/11] chore(BA-5119): update version annotation to 26.4.0 for ContainerRegistry GQL types Co-Authored-By: Claude Opus 4.6 --- src/ai/backend/manager/api/gql/container_registry/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ai/backend/manager/api/gql/container_registry/types.py b/src/ai/backend/manager/api/gql/container_registry/types.py index 95ae0ae5395..a10f0ab569c 100644 --- a/src/ai/backend/manager/api/gql/container_registry/types.py +++ b/src/ai/backend/manager/api/gql/container_registry/types.py @@ -19,7 +19,7 @@ @strawberry.enum( - name="ContainerRegistryType", description="Added in 26.3.0. Container registry type." + name="ContainerRegistryType", description="Added in 26.4.0. Container registry type." ) class ContainerRegistryTypeGQL(StrEnum): DOCKER = "docker" @@ -39,7 +39,7 @@ def from_enum(cls, value: ContainerRegistryType) -> ContainerRegistryTypeGQL: @strawberry.type( name="ContainerRegistryV2", - description="Added in 26.3.0. Container registry node.", + description="Added in 26.4.0. Container registry node.", ) class ContainerRegistryGQL(Node): id: NodeID[str] = strawberry.field( From 3804ebef763bab2fed5f5d9bbe4f1841c0bfc784 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Tue, 17 Mar 2026 05:50:01 +0000 Subject: [PATCH 11/11] chore: update api schema dump Co-authored-by: octodog --- docs/manager/graphql-reference/supergraph.graphql | 7 +++++-- docs/manager/graphql-reference/v2-schema.graphql | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/manager/graphql-reference/supergraph.graphql b/docs/manager/graphql-reference/supergraph.graphql index 9eb8576811f..cf64ea1ddc0 100644 --- a/docs/manager/graphql-reference/supergraph.graphql +++ b/docs/manager/graphql-reference/supergraph.graphql @@ -2391,7 +2391,7 @@ input ContainerRegistryScope scalar ContainerRegistryScopeField @join__type(graph: GRAPHENE) -"""Added in 26.3.0. Container registry type.""" +"""Added in 26.4.0. Container registry type.""" enum ContainerRegistryType @join__type(graph: STRAWBERRY) { @@ -2410,7 +2410,7 @@ enum ContainerRegistryType scalar ContainerRegistryTypeField @join__type(graph: GRAPHENE) -"""Added in 26.3.0. Container registry node.""" +"""Added in 26.4.0. Container registry node.""" type ContainerRegistryV2 implements Node @join__implements(graph: STRAWBERRY, interface: "Node") @join__type(graph: STRAWBERRY) @@ -2441,6 +2441,9 @@ type ContainerRegistryV2 implements Node """Whether this registry is globally accessible""" isGlobal: Boolean + + """Extra metadata for the container registry""" + extra: JSON } """Added in 25.6.0.""" diff --git a/docs/manager/graphql-reference/v2-schema.graphql b/docs/manager/graphql-reference/v2-schema.graphql index 9ce613856c7..a3cc9a3d833 100644 --- a/docs/manager/graphql-reference/v2-schema.graphql +++ b/docs/manager/graphql-reference/v2-schema.graphql @@ -1415,7 +1415,7 @@ input ContainerRegistryScope { registryId: UUID! } -"""Added in 26.3.0. Container registry type.""" +"""Added in 26.4.0. Container registry type.""" enum ContainerRegistryType { DOCKER HARBOR @@ -1428,7 +1428,7 @@ enum ContainerRegistryType { OCP } -"""Added in 26.3.0. Container registry node.""" +"""Added in 26.4.0. Container registry node.""" type ContainerRegistryV2 implements Node { """The Globally Unique ID of this object""" id: ID! @@ -1456,6 +1456,9 @@ type ContainerRegistryV2 implements Node { """Whether this registry is globally accessible""" isGlobal: Boolean + + """Extra metadata for the container registry""" + extra: JSON } input CreateAccessTokenInput {