Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Service account improvements#3109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
zapp42 wants to merge6 commits intopython-gitlab:main
base:main
Choose a base branch
Loading
fromzapp42:service-account-improvements
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionsgitlab/client.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,6 +214,8 @@ def __init__(
"""See :class:`~gitlab.v4.objects.TopicManager`"""
self.statistics = objects.ApplicationStatisticsManager(self)
"""See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`"""
self.service_accounts = objects.ServiceAccountManager(self)
"""See :class:`~gitlab.v4.objects.ServiceAccountManager`"""

def __enter__(self) -> Gitlab:
return self
Expand Down
49 changes: 45 additions & 4 deletionsgitlab/v4/objects/service_accounts.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,55 @@
from gitlab.base import RESTObject
from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin
from gitlab.types import RequiredOptional
from gitlab.mixins import (
CreateMixin,
DeleteMixin,
ListMixin,
ObjectDeleteMixin,
ObjectRotateMixin,
RotateMixin,
)
from gitlab.types import ArrayAttribute, RequiredOptional

__all__ = ["GroupServiceAccount", "GroupServiceAccountManager"]
__all__ = [
"ServiceAccount",
"ServiceAccountManager",
"GroupServiceAccount",
"GroupServiceAccountManager",
"GroupServiceAccountAccessToken",
"GroupServiceAccountAccessTokenManager",
]


class GroupServiceAccount(ObjectDeleteMixin, RESTObject):
class GroupServiceAccountAccessToken(ObjectRotateMixin, RESTObject):
pass


class GroupServiceAccountAccessTokenManager(
CreateMixin[GroupServiceAccountAccessToken],
RotateMixin[GroupServiceAccountAccessToken],
):
_path = "/groups/{group_id}/service_accounts/{user_id}/personal_access_tokens"
_obj_cls = GroupServiceAccountAccessToken
_from_parent_attrs = {"group_id": "group_id", "user_id": "id"}
_create_attrs = RequiredOptional(
required=("name", "scopes"), optional=("expires_at",)
)
_types = {"scopes": ArrayAttribute}


class ServiceAccount(RESTObject):
pass


class ServiceAccountManager(CreateMixin[ServiceAccount], ListMixin[ServiceAccount]):
Comment on lines +39 to +43
Copy link
Preview

CopilotAIJun 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

ServiceAccount currently has no delete support; add ObjectDeleteMixin to the class and DeleteMixin to ServiceAccountManager so that instance-level service accounts can be deleted.

Suggested change
classServiceAccount(RESTObject):
pass
classServiceAccountManager(CreateMixin[ServiceAccount],ListMixin[ServiceAccount]):
classServiceAccount(ObjectDeleteMixin,RESTObject):
pass
classServiceAccountManager(CreateMixin[ServiceAccount],DeleteMixin[ServiceAccount],ListMixin[ServiceAccount]):

Copilot uses AI. Check for mistakes.

_path = "/service_accounts"
_obj_cls = ServiceAccount
_create_attrs = RequiredOptional(optional=("name", "username", "email"))


class GroupServiceAccount(ObjectDeleteMixin, RESTObject):
access_tokens: GroupServiceAccountAccessTokenManager


class GroupServiceAccountManager(
CreateMixin[GroupServiceAccount],
DeleteMixin[GroupServiceAccount],
Expand Down
72 changes: 72 additions & 0 deletionstests/unit/objects/test_groups.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -84,10 +84,23 @@
}

service_account_content = {
"id": 42,
"name": "gitlab-service-account",
"username": "gitlab-service-account",
}

service_account_access_token_content = {
"id": 1,
"name": "service_account_access_token",
"revoked": False,
"scopes": ["api"],
"user_id": 42,
"last_used": None,
"active": True,
"expires_at": None,
"token": "abcdefg12345",
}


@pytest.fixture
def resp_groups():
Expand DownExpand Up@@ -343,6 +356,44 @@ def resp_create_group_service_account():
yield rsps


@pytest.fixture
def resp_delete_group_service_account():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/groups/1/service_accounts",
json=service_account_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.DELETE,
url="http://localhost/api/v4/groups/1/service_accounts/42",
status=204,
)
yield rsps


@pytest.fixture
def resp_create_group_service_account_access_token():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/groups/1/service_accounts",
json=service_account_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/groups/1/service_accounts/42/personal_access_tokens",
json=service_account_access_token_content,
content_type="application/json",
status=200,
)
yield rsps


def test_get_group(gl, resp_groups):
data = gl.groups.get(1)
assert isinstance(data, gitlab.v4.objects.Group)
Expand DownExpand Up@@ -489,3 +540,24 @@ def test_create_group_service_account(group, resp_create_group_service_account):
)
assert service_account.name == "gitlab-service-account"
assert service_account.username == "gitlab-service-account"


def test_delete_group_service_account(group, resp_delete_group_service_account):
service_account = group.service_accounts.create(
{"name": "gitlab-service-account", "username": "gitlab-service-account"}
)
service_account.delete()


def test_create_group_service_account_access_token(
group, resp_create_group_service_account_access_token
):
service_account = group.service_accounts.create(
{"name": "gitlab-service-account", "username": "gitlab-service-account"}
)
access_token = service_account.access_tokens.create(
{"name": "service_account_access_token", "scopes": ["api"]}
)
assert service_account.id == 42
assert access_token.name == "service_account_access_token"
assert access_token.scopes == ["api"]
76 changes: 76 additions & 0 deletionstests/unit/objects/test_service_accounts.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""
GitLab API: https://docs.gitlab.com/ee/api/user_service_accounts.html
"""

import pytest
import responses

create_service_account_defaults_content = {
"id": 57,
"username": "service_account_6018816a18e515214e0c34c2b33523fc",
"name": "Service account user",
"email": "service_account_6018816a18e515214e0c34c2b33523fc@noreply.gitlab.example.com",
}


create_service_account_content = {
"id": 42,
"username": "my_service_account",
"name": "My Service account user",
"email": "servicebot@example.com",
}


@pytest.fixture
def resp_create_service_account_defaults():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/service_accounts",
json=create_service_account_defaults_content,
content_type="application/json",
status=200,
)

yield rsps


@pytest.fixture
def resp_create_service_account():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/service_accounts",
json=create_service_account_content,
content_type="application/json",
status=200,
)

yield rsps


def test_create_service_account_defaults(gl, resp_create_service_account_defaults):
service_account = gl.service_accounts.create()
assert service_account.id == 57
assert (
service_account.username == "service_account_6018816a18e515214e0c34c2b33523fc"
)
assert service_account.name == "Service account user"
assert (
service_account.email
== "service_account_6018816a18e515214e0c34c2b33523fc@noreply.gitlab.example.com"
)


def test_create_service_account(gl, resp_create_service_account):
service_account = gl.service_accounts.create(
{
"name": "My Service account user",
"username": "my_service_account",
"email": "servicebot@example.com",
}
)
assert service_account.id == 42
assert service_account.username == "my_service_account"
assert service_account.name == "My Service account user"
assert service_account.email == "servicebot@example.com"

[8]ページ先頭

©2009-2025 Movatter.jp