Skip to content

feat: Add support for Protected Environments #2084

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions docs/api-objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ API examples
gl_objects/projects
gl_objects/project_access_tokens
gl_objects/protected_branches
gl_objects/protected_environments
gl_objects/releases
gl_objects/runners
gl_objects/remote_mirrors
Expand Down
4 changes: 3 additions & 1 deletion docs/gl_objects/environments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Delete an environment for a project::
# or
environment.delete()

Stop an environments::
Stop an environment::

environment.stop()

To manage protected environments, see :doc:`/gl_objects/protected_environments`.
45 changes: 45 additions & 0 deletions docs/gl_objects/protected_environments.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
######################
Protected environments
######################

You can list and manage protected environments in a project.

References
----------

* v4 API:

+ :class:`gitlab.v4.objects.ProjectProtectedEnvironment`
+ :class:`gitlab.v4.objects.ProjectProtectedEnvironmentManager`
+ :attr:`gitlab.v4.objects.Project.protected_environment`

* GitLab API: https://docs.gitlab.com/ee/api/protected_environments.html

Examples
--------

Get the list of protected environments for a project::

p_environments = project.protected_environments.list()

Get a single protected environment::

p_environments = project.protected_environments.get('production')

Protect an existing environment::

p_environment = project.protected_environments.create(
{
'name': 'production',
'deploy_access_levels': [
{'access_level': 40}
],
}
)


Unprotect a protected environment::

p_environment = project.protected_environments.delete('production')
# or
p_environment.delete()
29 changes: 29 additions & 0 deletions gitlab/v4/objects/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
__all__ = [
"ProjectEnvironment",
"ProjectEnvironmentManager",
"ProjectProtectedEnvironment",
"ProjectProtectedEnvironmentManager",
]


Expand Down Expand Up @@ -55,3 +57,30 @@ def get(
self, id: Union[str, int], lazy: bool = False, **kwargs: Any
) -> ProjectEnvironment:
return cast(ProjectEnvironment, super().get(id=id, lazy=lazy, **kwargs))


class ProjectProtectedEnvironment(ObjectDeleteMixin, RESTObject):
_id_attr = "name"
_repr_attr = "name"


class ProjectProtectedEnvironmentManager(
RetrieveMixin, CreateMixin, DeleteMixin, RESTManager
):
_path = "/projects/{project_id}/protected_environments"
_obj_cls = ProjectProtectedEnvironment
_from_parent_attrs = {"project_id": "id"}
_create_attrs = RequiredOptional(
required=(
"name",
"deploy_access_levels",
),
optional=("required_approval_count", "approval_rules"),
)

def get(
self, id: Union[str, int], lazy: bool = False, **kwargs: Any
) -> ProjectProtectedEnvironment:
return cast(
ProjectProtectedEnvironment, super().get(id=id, lazy=lazy, **kwargs)
)
6 changes: 5 additions & 1 deletion gitlab/v4/objects/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
from .deploy_keys import ProjectKeyManager # noqa: F401
from .deploy_tokens import ProjectDeployTokenManager # noqa: F401
from .deployments import ProjectDeploymentManager # noqa: F401
from .environments import ProjectEnvironmentManager # noqa: F401
from .environments import ( # noqa: F401
ProjectEnvironmentManager,
ProjectProtectedEnvironmentManager,
)
from .events import ProjectEventManager # noqa: F401
from .export_import import ProjectExportManager, ProjectImportManager # noqa: F401
from .files import ProjectFileManager # noqa: F401
Expand Down Expand Up @@ -175,6 +178,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
pagesdomains: ProjectPagesDomainManager
pipelines: ProjectPipelineManager
pipelineschedules: ProjectPipelineScheduleManager
protected_environments: ProjectProtectedEnvironmentManager
protectedbranches: ProjectProtectedBranchManager
protectedtags: ProjectProtectedTagManager
pushrules: ProjectPushRulesManager
Expand Down
27 changes: 26 additions & 1 deletion tests/unit/objects/test_environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytest
import responses

from gitlab.v4.objects import ProjectEnvironment
from gitlab.v4.objects import ProjectEnvironment, ProjectProtectedEnvironment


@pytest.fixture
Expand All @@ -22,9 +22,34 @@ def resp_get_environment():
yield rsps


@pytest.fixture
def resp_get_protected_environment():
content = {
"name": "protected_environment_name",
"last_deployment": "my birthday",
}

with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/protected_environments/2",
json=content,
content_type="application/json",
status=200,
)
yield rsps


def test_project_environments(project, resp_get_environment):
environment = project.environments.get(1)
assert isinstance(environment, ProjectEnvironment)
assert environment.id == 1
assert environment.last_deployment == "sometime"
assert environment.name == "environment_name"


def test_project_protected_environments(project, resp_get_protected_environment):
protected_environment = project.protected_environments.get(2)
assert isinstance(protected_environment, ProjectProtectedEnvironment)
assert protected_environment.last_deployment == "my birthday"
assert protected_environment.name == "protected_environment_name"