From 48726fde9b3c2424310ff590b366b9fdefa4a146 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:12:34 +0000 Subject: [PATCH 01/18] chore(deps): update all non-major dependencies --- .github/workflows/docs.yml | 2 +- .github/workflows/test.yml | 6 +++--- .pre-commit-config.yaml | 2 +- requirements-docker.txt | 2 +- requirements-lint.txt | 4 ++-- requirements-test.txt | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index dd483fcad..42b8fc33d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -34,7 +34,7 @@ jobs: TOXENV: docs run: tox - name: Archive generated docs - uses: actions/upload-artifact@v4.1.0 + uses: actions/upload-artifact@v4.3.0 with: name: html-docs path: build/sphinx/html/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 653ae6e9b..e3086c31d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,7 @@ jobs: TOXENV: ${{ matrix.toxenv }} run: tox -- --override-ini='log_cli=True' - name: Upload codecov coverage - uses: codecov/codecov-action@v3.1.4 + uses: codecov/codecov-action@v3.1.5 with: files: ./coverage.xml flags: ${{ matrix.toxenv }} @@ -100,7 +100,7 @@ jobs: TOXENV: cover run: tox - name: Upload codecov coverage - uses: codecov/codecov-action@v3.1.4 + uses: codecov/codecov-action@v3.1.5 with: files: ./coverage.xml flags: unit @@ -119,7 +119,7 @@ jobs: pip install -r requirements-test.txt - name: Build package run: python -m build -o dist/ - - uses: actions/upload-artifact@v4.1.0 + - uses: actions/upload-artifact@v4.3.0 with: name: dist path: dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18815e12e..2c8f048e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,6 +47,6 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/maxbrunet/pre-commit-renovate - rev: 37.131.0 + rev: 37.153.0 hooks: - id: renovate-config-validator diff --git a/requirements-docker.txt b/requirements-docker.txt index bfe8511e9..5c52e5d06 100644 --- a/requirements-docker.txt +++ b/requirements-docker.txt @@ -1,3 +1,3 @@ -r requirements.txt -r requirements-test.txt -pytest-docker==2.0.1 +pytest-docker==2.1.0 diff --git a/requirements-lint.txt b/requirements-lint.txt index a0b01f0e4..eb1a9f46c 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -9,5 +9,5 @@ pylint==3.0.3 pytest==7.4.4 responses==0.24.1 types-PyYAML==6.0.12.12 -types-requests==2.31.0.20240106 -types-setuptools==69.0.0.20240106 +types-requests==2.31.0.20240125 +types-setuptools==69.0.0.20240125 diff --git a/requirements-test.txt b/requirements-test.txt index fa37a796b..f3b474f19 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,6 +1,6 @@ -r requirements.txt build==1.0.3 -coverage==7.4.0 +coverage==7.4.1 pytest-console-scripts==1.4.1 pytest-cov==4.1.0 pytest-github-actions-annotate-failures==0.2.0 From f59aee3ddcfaeeb29fcfab4cc6768dff6b5558cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 03:38:26 +0000 Subject: [PATCH 02/18] chore(deps): update dependency black to v24 --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index eb1a9f46c..e3064b975 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1,6 +1,6 @@ -r requirements.txt argcomplete==2.0.0 -black==23.12.1 +black==24.1.1 commitizen==3.13.0 flake8==7.0.0 isort==5.13.2 From 4e68d32c77ed587ab42d229d9f44c3bc40d1d0e5 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Mon, 29 Jan 2024 13:09:36 +0100 Subject: [PATCH 03/18] chore: adapt style for black v24 --- gitlab/_backends/protocol.py | 6 ++---- gitlab/client.py | 1 - gitlab/v4/objects/artifacts.py | 1 + gitlab/v4/objects/audit_events.py | 1 + gitlab/v4/objects/deployments.py | 1 + gitlab/v4/objects/features.py | 1 + gitlab/v4/objects/merge_requests.py | 1 + gitlab/v4/objects/projects.py | 1 + gitlab/v4/objects/repositories.py | 1 + gitlab/v4/objects/secure_files.py | 1 + gitlab/v4/objects/users.py | 1 + gitlab/v4/objects/variables.py | 1 + tests/functional/api/test_keys.py | 1 + tests/functional/api/test_packages.py | 1 + tests/functional/api/test_users.py | 1 + tests/functional/fixtures/docker.py | 1 + tests/unit/meta/test_ensure_type_hints.py | 1 + tests/unit/meta/test_imports.py | 1 + tests/unit/meta/test_mro.py | 10 ++++------ tests/unit/objects/test_badges.py | 1 + tests/unit/objects/test_bridges.py | 1 + tests/unit/objects/test_deploy_tokens.py | 1 + tests/unit/objects/test_deployments.py | 1 + tests/unit/objects/test_draft_notes.py | 1 + tests/unit/objects/test_environments.py | 1 + tests/unit/objects/test_issues.py | 1 + tests/unit/objects/test_jobs.py | 1 + tests/unit/objects/test_keys.py | 1 + tests/unit/objects/test_members.py | 1 + tests/unit/objects/test_merge_request_pipelines.py | 1 + tests/unit/objects/test_merge_requests.py | 1 + tests/unit/objects/test_merge_trains.py | 1 + tests/unit/objects/test_packages.py | 1 + tests/unit/objects/test_pipeline_schedules.py | 1 + tests/unit/objects/test_pipelines.py | 1 + tests/unit/objects/test_project_import_export.py | 1 + .../objects/test_project_merge_request_approvals.py | 6 +++--- tests/unit/objects/test_project_statistics.py | 1 + tests/unit/objects/test_registry_repositories.py | 1 + tests/unit/objects/test_releases.py | 1 + tests/unit/objects/test_repositories.py | 1 + tests/unit/objects/test_resource_groups.py | 1 + tests/unit/objects/test_submodules.py | 1 + tests/unit/objects/test_todos.py | 1 + tests/unit/objects/test_topics.py | 1 + tests/unit/objects/test_users.py | 1 + tox.ini | 4 +++- 47 files changed, 54 insertions(+), 15 deletions(-) diff --git a/gitlab/_backends/protocol.py b/gitlab/_backends/protocol.py index f89740b25..72cee226d 100644 --- a/gitlab/_backends/protocol.py +++ b/gitlab/_backends/protocol.py @@ -13,8 +13,7 @@ class BackendResponse(Protocol): @abc.abstractmethod - def __init__(self, response: requests.Response) -> None: - ... + def __init__(self, response: requests.Response) -> None: ... class Backend(Protocol): @@ -30,5 +29,4 @@ def http_request( verify: Optional[Union[bool, str]], stream: Optional[bool], **kwargs: Any, - ) -> BackendResponse: - ... + ) -> BackendResponse: ... diff --git a/gitlab/client.py b/gitlab/client.py index 1f55dcfad..f91aadb4e 100644 --- a/gitlab/client.py +++ b/gitlab/client.py @@ -40,7 +40,6 @@ class Gitlab: - """Represents a GitLab server connection. Args: diff --git a/gitlab/v4/objects/artifacts.py b/gitlab/v4/objects/artifacts.py index 330f8aef3..26816167c 100644 --- a/gitlab/v4/objects/artifacts.py +++ b/gitlab/v4/objects/artifacts.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/job_artifacts.html """ + from typing import Any, Callable, Iterator, Optional, TYPE_CHECKING, Union import requests diff --git a/gitlab/v4/objects/audit_events.py b/gitlab/v4/objects/audit_events.py index 649dc9dd3..fb7c3ffe4 100644 --- a/gitlab/v4/objects/audit_events.py +++ b/gitlab/v4/objects/audit_events.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/audit_events.html """ + from typing import Any, cast, Union from gitlab.base import RESTManager, RESTObject diff --git a/gitlab/v4/objects/deployments.py b/gitlab/v4/objects/deployments.py index 145273b52..3f41df365 100644 --- a/gitlab/v4/objects/deployments.py +++ b/gitlab/v4/objects/deployments.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/deployments.html """ + from typing import Any, cast, Dict, Optional, TYPE_CHECKING, Union from gitlab import cli diff --git a/gitlab/v4/objects/features.py b/gitlab/v4/objects/features.py index 1631a2651..f68c10e8d 100644 --- a/gitlab/v4/objects/features.py +++ b/gitlab/v4/objects/features.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/features.html """ + from typing import Any, Optional, TYPE_CHECKING, Union from gitlab import exceptions as exc diff --git a/gitlab/v4/objects/merge_requests.py b/gitlab/v4/objects/merge_requests.py index aa106763c..4e4e1a959 100644 --- a/gitlab/v4/objects/merge_requests.py +++ b/gitlab/v4/objects/merge_requests.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ee/api/merge_requests.html https://docs.gitlab.com/ee/api/merge_request_approvals.html """ + from typing import Any, cast, Dict, Optional, TYPE_CHECKING, Union import requests diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py index e342e81e7..ca9f26a92 100644 --- a/gitlab/v4/objects/projects.py +++ b/gitlab/v4/objects/projects.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/projects.html """ + from typing import ( Any, Callable, diff --git a/gitlab/v4/objects/repositories.py b/gitlab/v4/objects/repositories.py index 9c0cd9a37..d97e098d8 100644 --- a/gitlab/v4/objects/repositories.py +++ b/gitlab/v4/objects/repositories.py @@ -3,6 +3,7 @@ Currently this module only contains repository-related methods for projects. """ + from typing import Any, Callable, Dict, Iterator, List, Optional, TYPE_CHECKING, Union import requests diff --git a/gitlab/v4/objects/secure_files.py b/gitlab/v4/objects/secure_files.py index a7da5ea0d..11b387365 100644 --- a/gitlab/v4/objects/secure_files.py +++ b/gitlab/v4/objects/secure_files.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/secure_files.html """ + from typing import Any, Callable, cast, Iterator, Optional, TYPE_CHECKING, Union import requests diff --git a/gitlab/v4/objects/users.py b/gitlab/v4/objects/users.py index fe93e4a68..8e610fc30 100644 --- a/gitlab/v4/objects/users.py +++ b/gitlab/v4/objects/users.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ee/api/users.html https://docs.gitlab.com/ee/api/projects.html#list-projects-starred-by-a-user """ + from typing import Any, cast, Dict, List, Optional, Union import requests diff --git a/gitlab/v4/objects/variables.py b/gitlab/v4/objects/variables.py index 62ea872de..4cfbeb460 100644 --- a/gitlab/v4/objects/variables.py +++ b/gitlab/v4/objects/variables.py @@ -4,6 +4,7 @@ https://docs.gitlab.com/ee/api/project_level_variables.html https://docs.gitlab.com/ee/api/group_level_variables.html """ + from typing import Any, cast, Union from gitlab.base import RESTManager, RESTObject diff --git a/tests/functional/api/test_keys.py b/tests/functional/api/test_keys.py index a674bfcd1..359649bef 100644 --- a/tests/functional/api/test_keys.py +++ b/tests/functional/api/test_keys.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ce/api/keys.html """ + import base64 import hashlib diff --git a/tests/functional/api/test_packages.py b/tests/functional/api/test_packages.py index c16fb12e8..1995da817 100644 --- a/tests/functional/api/test_packages.py +++ b/tests/functional/api/test_packages.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ce/api/packages.html https://docs.gitlab.com/ee/user/packages/generic_packages """ + from collections.abc import Iterator from gitlab.v4.objects import GenericPackage diff --git a/tests/functional/api/test_users.py b/tests/functional/api/test_users.py index 3209e65c8..9c300365b 100644 --- a/tests/functional/api/test_users.py +++ b/tests/functional/api/test_users.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ee/api/users.html https://docs.gitlab.com/ee/api/users.html#delete-authentication-identity-from-user """ + import requests diff --git a/tests/functional/fixtures/docker.py b/tests/functional/fixtures/docker.py index c712487e9..26bc440b5 100644 --- a/tests/functional/fixtures/docker.py +++ b/tests/functional/fixtures/docker.py @@ -2,6 +2,7 @@ pytest-docker fixture overrides. See https://github.com/avast/pytest-docker#available-fixtures. """ + import pytest diff --git a/tests/unit/meta/test_ensure_type_hints.py b/tests/unit/meta/test_ensure_type_hints.py index b5ec14c3a..0a29db03e 100644 --- a/tests/unit/meta/test_ensure_type_hints.py +++ b/tests/unit/meta/test_ensure_type_hints.py @@ -4,6 +4,7 @@ Original notes by John L. Villalovos """ + import dataclasses import functools import inspect diff --git a/tests/unit/meta/test_imports.py b/tests/unit/meta/test_imports.py index 326e06cec..1f038146d 100644 --- a/tests/unit/meta/test_imports.py +++ b/tests/unit/meta/test_imports.py @@ -3,6 +3,7 @@ `gitlab/v4/objects/__init__.py` """ + import pkgutil from typing import Set diff --git a/tests/unit/meta/test_mro.py b/tests/unit/meta/test_mro.py index 4a6e65204..d7dd0046f 100644 --- a/tests/unit/meta/test_mro.py +++ b/tests/unit/meta/test_mro.py @@ -42,6 +42,7 @@ class Wrongv4Object(RESTObject, Mixin): Almost all classes in gitlab/v4/objects/*py were already correct before this check was added. """ + import inspect import pytest @@ -53,11 +54,9 @@ def test_show_issue() -> None: """Test case to demonstrate the TypeError that occurs""" class RESTObject: - def __init__(self, manager: str, attrs: int) -> None: - ... + def __init__(self, manager: str, attrs: int) -> None: ... - class Mixin(RESTObject): - ... + class Mixin(RESTObject): ... with pytest.raises(TypeError) as exc_info: # Wrong ordering here @@ -72,8 +71,7 @@ class Wrongv4Object(RESTObject, Mixin): # type: ignore assert "MRO" in exc_info.exconly() # Correctly ordered class, no exception - class Correctv4Object(Mixin, RESTObject): - ... + class Correctv4Object(Mixin, RESTObject): ... def test_mros() -> None: diff --git a/tests/unit/objects/test_badges.py b/tests/unit/objects/test_badges.py index 6d0efb9bf..90fe11872 100644 --- a/tests/unit/objects/test_badges.py +++ b/tests/unit/objects/test_badges.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/project_badges.html GitLab API: https://docs.gitlab.com/ee/api/group_badges.html """ + import re import pytest diff --git a/tests/unit/objects/test_bridges.py b/tests/unit/objects/test_bridges.py index 5259b8c4e..1d4dceec8 100644 --- a/tests/unit/objects/test_bridges.py +++ b/tests/unit/objects/test_bridges.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-bridges """ + import pytest import responses diff --git a/tests/unit/objects/test_deploy_tokens.py b/tests/unit/objects/test_deploy_tokens.py index 66a79fa1d..e1ef4ed2d 100644 --- a/tests/unit/objects/test_deploy_tokens.py +++ b/tests/unit/objects/test_deploy_tokens.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/deploy_tokens.html """ + import pytest import responses diff --git a/tests/unit/objects/test_deployments.py b/tests/unit/objects/test_deployments.py index e7099f271..dda982bd4 100644 --- a/tests/unit/objects/test_deployments.py +++ b/tests/unit/objects/test_deployments.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/deployments.html """ + import pytest import responses diff --git a/tests/unit/objects/test_draft_notes.py b/tests/unit/objects/test_draft_notes.py index d37cfc004..5f907b54f 100644 --- a/tests/unit/objects/test_draft_notes.py +++ b/tests/unit/objects/test_draft_notes.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/draft_notes.html """ + from copy import deepcopy import pytest diff --git a/tests/unit/objects/test_environments.py b/tests/unit/objects/test_environments.py index 5501471db..baefae26e 100644 --- a/tests/unit/objects/test_environments.py +++ b/tests/unit/objects/test_environments.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/environments.html """ + import pytest import responses diff --git a/tests/unit/objects/test_issues.py b/tests/unit/objects/test_issues.py index 8d202fa6f..02799b580 100644 --- a/tests/unit/objects/test_issues.py +++ b/tests/unit/objects/test_issues.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/issues.html """ + import re import pytest diff --git a/tests/unit/objects/test_jobs.py b/tests/unit/objects/test_jobs.py index 9454f3660..40036b91f 100644 --- a/tests/unit/objects/test_jobs.py +++ b/tests/unit/objects/test_jobs.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/jobs.html """ + import pytest import responses diff --git a/tests/unit/objects/test_keys.py b/tests/unit/objects/test_keys.py index 187a309e3..fb145846c 100644 --- a/tests/unit/objects/test_keys.py +++ b/tests/unit/objects/test_keys.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/keys.html """ + import pytest import responses diff --git a/tests/unit/objects/test_members.py b/tests/unit/objects/test_members.py index ca71478a6..8ef3dff07 100644 --- a/tests/unit/objects/test_members.py +++ b/tests/unit/objects/test_members.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/members.html """ + import pytest import responses diff --git a/tests/unit/objects/test_merge_request_pipelines.py b/tests/unit/objects/test_merge_request_pipelines.py index 1d2fbf128..4a85fdc41 100644 --- a/tests/unit/objects/test_merge_request_pipelines.py +++ b/tests/unit/objects/test_merge_request_pipelines.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/merge_requests.html#list-mr-pipelines """ + import pytest import responses diff --git a/tests/unit/objects/test_merge_requests.py b/tests/unit/objects/test_merge_requests.py index 5fa436445..6f8a6a7de 100644 --- a/tests/unit/objects/test_merge_requests.py +++ b/tests/unit/objects/test_merge_requests.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ce/api/merge_requests.html https://docs.gitlab.com/ee/api/deployments.html#list-of-merge-requests-associated-with-a-deployment """ + import re import pytest diff --git a/tests/unit/objects/test_merge_trains.py b/tests/unit/objects/test_merge_trains.py index a45718e2b..f58d04422 100644 --- a/tests/unit/objects/test_merge_trains.py +++ b/tests/unit/objects/test_merge_trains.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/merge_trains.html """ + import pytest import responses diff --git a/tests/unit/objects/test_packages.py b/tests/unit/objects/test_packages.py index 026a70a4c..de3353829 100644 --- a/tests/unit/objects/test_packages.py +++ b/tests/unit/objects/test_packages.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/packages.html """ + import re import pytest diff --git a/tests/unit/objects/test_pipeline_schedules.py b/tests/unit/objects/test_pipeline_schedules.py index 8b8dab893..3a27becb1 100644 --- a/tests/unit/objects/test_pipeline_schedules.py +++ b/tests/unit/objects/test_pipeline_schedules.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/pipeline_schedules.html """ + import pytest import responses diff --git a/tests/unit/objects/test_pipelines.py b/tests/unit/objects/test_pipelines.py index e4d2b9e7f..c531b9f4e 100644 --- a/tests/unit/objects/test_pipelines.py +++ b/tests/unit/objects/test_pipelines.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/pipelines.html """ + import pytest import responses diff --git a/tests/unit/objects/test_project_import_export.py b/tests/unit/objects/test_project_import_export.py index bfe976fe8..3d5cb9207 100644 --- a/tests/unit/objects/test_project_import_export.py +++ b/tests/unit/objects/test_project_import_export.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/project_import_export.html """ + import pytest import responses diff --git a/tests/unit/objects/test_project_merge_request_approvals.py b/tests/unit/objects/test_project_merge_request_approvals.py index d60a8c9c7..7d63db519 100644 --- a/tests/unit/objects/test_project_merge_request_approvals.py +++ b/tests/unit/objects/test_project_merge_request_approvals.py @@ -133,9 +133,9 @@ def resp_mr_approval_rules(): mr_ars_content[0]["eligible_approvers"][0] ] - updated_mr_ars_content[ - "approvals_required" - ] = updated_approval_rule_approvals_required + updated_mr_ars_content["approvals_required"] = ( + updated_approval_rule_approvals_required + ) rsps.add( method=responses.PUT, diff --git a/tests/unit/objects/test_project_statistics.py b/tests/unit/objects/test_project_statistics.py index 50d9a6d79..2644102ab 100644 --- a/tests/unit/objects/test_project_statistics.py +++ b/tests/unit/objects/test_project_statistics.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/project_statistics.html """ + import pytest import responses diff --git a/tests/unit/objects/test_registry_repositories.py b/tests/unit/objects/test_registry_repositories.py index 9fe1adf36..5b88a0682 100644 --- a/tests/unit/objects/test_registry_repositories.py +++ b/tests/unit/objects/test_registry_repositories.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ee/api/container_registry.html """ + import re import pytest diff --git a/tests/unit/objects/test_releases.py b/tests/unit/objects/test_releases.py index 0a503094d..638377566 100644 --- a/tests/unit/objects/test_releases.py +++ b/tests/unit/objects/test_releases.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ee/api/releases/index.html https://docs.gitlab.com/ee/api/releases/links.html """ + import re import pytest diff --git a/tests/unit/objects/test_repositories.py b/tests/unit/objects/test_repositories.py index ff2bc2335..f11bd64e4 100644 --- a/tests/unit/objects/test_repositories.py +++ b/tests/unit/objects/test_repositories.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ee/api/repositories.html https://docs.gitlab.com/ee/api/repository_files.html """ + from urllib.parse import quote import pytest diff --git a/tests/unit/objects/test_resource_groups.py b/tests/unit/objects/test_resource_groups.py index dd579ac11..1b5309785 100644 --- a/tests/unit/objects/test_resource_groups.py +++ b/tests/unit/objects/test_resource_groups.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/resource_groups.html """ + import pytest import responses diff --git a/tests/unit/objects/test_submodules.py b/tests/unit/objects/test_submodules.py index fc95aa33d..ed6804d50 100644 --- a/tests/unit/objects/test_submodules.py +++ b/tests/unit/objects/test_submodules.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/repository_submodules.html """ + import pytest import responses diff --git a/tests/unit/objects/test_todos.py b/tests/unit/objects/test_todos.py index 44f54a960..9e0c346cd 100644 --- a/tests/unit/objects/test_todos.py +++ b/tests/unit/objects/test_todos.py @@ -1,6 +1,7 @@ """ GitLab API: https://docs.gitlab.com/ce/api/todos.html """ + import pytest import responses diff --git a/tests/unit/objects/test_topics.py b/tests/unit/objects/test_topics.py index 8e3766e2b..dc4b92162 100644 --- a/tests/unit/objects/test_topics.py +++ b/tests/unit/objects/test_topics.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ce/api/topics.html """ + import pytest import responses diff --git a/tests/unit/objects/test_users.py b/tests/unit/objects/test_users.py index 0bbcc7637..c120581fe 100644 --- a/tests/unit/objects/test_users.py +++ b/tests/unit/objects/test_users.py @@ -3,6 +3,7 @@ https://docs.gitlab.com/ce/api/users.html https://docs.gitlab.com/ee/api/projects.html#list-projects-starred-by-a-user """ + import pytest import responses diff --git a/tox.ini b/tox.ini index ffbb88a72..316c31aa3 100644 --- a/tox.ini +++ b/tox.ini @@ -80,8 +80,10 @@ max-line-length = 88 # We ignore the following because we use black to handle code-formatting # E203: Whitespace before ':' # E501: Line too long +# E701: multiple statements on one line (colon) +# E704: multiple statements on one line (def) # W503: Line break occurred before a binary operator -ignore = E203,E501,W503 +extend-ignore = E203,E501,E701,E704,W503 per-file-ignores = gitlab/v4/objects/__init__.py:F401,F403 From 7ec3189d6eacdb55925e8be886a44d7ee09eb9ca Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 29 Jan 2024 17:12:34 +0100 Subject: [PATCH 04/18] fix(cli): allow exclusive arguments as optional (#2770) * fix(cli): allow exclusive arguments as optional The CLI takes its arguments from the RequiredOptional, which has three fields: required, optional, and exclusive. In practice, the exclusive options are not defined as either required or optional, and would not be allowed in the CLI. This changes that, so that exclusive options are also added to the argument parser. * fix(cli): inform argument parser that options are mutually exclusive * fix(cli): use correct exclusive options, add unit test Closes #2769 --- gitlab/v4/cli.py | 9 +++++++ tests/unit/test_cli.py | 61 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/gitlab/v4/cli.py b/gitlab/v4/cli.py index 4bfa5ea93..c6159bc26 100644 --- a/gitlab/v4/cli.py +++ b/gitlab/v4/cli.py @@ -262,6 +262,10 @@ def _populate_sub_parser_by_class( sub_parser_action.add_argument( f"--{x.replace('_', '-')}", required=False ) + if mgr_cls._create_attrs.exclusive: + group = sub_parser_action.add_mutually_exclusive_group() + for x in mgr_cls._create_attrs.exclusive: + group.add_argument(f"--{x.replace('_', '-')}") if action_name == "update": if cls._id_attr is not None: @@ -280,6 +284,11 @@ def _populate_sub_parser_by_class( f"--{x.replace('_', '-')}", required=False ) + if mgr_cls._update_attrs.exclusive: + group = sub_parser_action.add_mutually_exclusive_group() + for x in mgr_cls._update_attrs.exclusive: + group.add_argument(f"--{x.replace('_', '-')}") + if cls.__name__ in cli.custom_actions: name = cls.__name__ for action_name in cli.custom_actions[name]: diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index e40440ed6..eaa3908b5 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -11,6 +11,8 @@ import gitlab.base from gitlab import cli from gitlab.exceptions import GitlabError +from gitlab.mixins import CreateMixin, UpdateMixin +from gitlab.types import RequiredOptional from gitlab.v4 import cli as v4_cli @@ -157,6 +159,65 @@ def test_v4_parser(): assert actions["--name"].required +def test_extend_parser(): + class ExceptionArgParser(argparse.ArgumentParser): + def error(self, message): + "Raise error instead of exiting on invalid arguments, to make testing easier" + raise ValueError(message) + + class Fake: + _id_attr = None + + class FakeManager(gitlab.base.RESTManager, CreateMixin, UpdateMixin): + _obj_cls = Fake + _create_attrs = RequiredOptional( + required=("create",), + optional=("opt_create",), + exclusive=("create_a", "create_b"), + ) + _update_attrs = RequiredOptional( + required=("update",), + optional=("opt_update",), + exclusive=("update_a", "update_b"), + ) + + parser = ExceptionArgParser() + with mock.patch.dict( + "gitlab.v4.objects.__dict__", {"FakeManager": FakeManager}, clear=True + ): + v4_cli.extend_parser(parser) + + assert parser.parse_args(["fake", "create", "--create", "1"]) + assert parser.parse_args(["fake", "create", "--create", "1", "--opt-create", "1"]) + assert parser.parse_args(["fake", "create", "--create", "1", "--create-a", "1"]) + assert parser.parse_args(["fake", "create", "--create", "1", "--create-b", "1"]) + + with pytest.raises(ValueError): + # missing required "create" + parser.parse_args(["fake", "create", "--opt_create", "1"]) + + with pytest.raises(ValueError): + # both exclusive options + parser.parse_args( + ["fake", "create", "--create", "1", "--create-a", "1", "--create-b", "1"] + ) + + assert parser.parse_args(["fake", "update", "--update", "1"]) + assert parser.parse_args(["fake", "update", "--update", "1", "--opt-update", "1"]) + assert parser.parse_args(["fake", "update", "--update", "1", "--update-a", "1"]) + assert parser.parse_args(["fake", "update", "--update", "1", "--update-b", "1"]) + + with pytest.raises(ValueError): + # missing required "update" + parser.parse_args(["fake", "update", "--opt_update", "1"]) + + with pytest.raises(ValueError): + # both exclusive options + parser.parse_args( + ["fake", "update", "--update", "1", "--update-a", "1", "--update-b", "1"] + ) + + @pytest.mark.skipif(sys.version_info < (3, 8), reason="added in 3.8") def test_legacy_display_without_fields_warns(fake_object_no_id): printer = v4_cli.LegacyPrinter() From d2be1f7608acadcc2682afd82d16d3706b7f7461 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 01:11:31 +0000 Subject: [PATCH 05/18] chore(deps): update codecov/codecov-action action to v4 --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3086c31d..b4f3d8ebb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,7 @@ jobs: TOXENV: ${{ matrix.toxenv }} run: tox -- --override-ini='log_cli=True' - name: Upload codecov coverage - uses: codecov/codecov-action@v3.1.5 + uses: codecov/codecov-action@v4.0.1 with: files: ./coverage.xml flags: ${{ matrix.toxenv }} @@ -100,7 +100,7 @@ jobs: TOXENV: cover run: tox - name: Upload codecov coverage - uses: codecov/codecov-action@v3.1.5 + uses: codecov/codecov-action@v4.0.1 with: files: ./coverage.xml flags: unit From 7dc2fa6e632ed2c9adeb6ed32c4899ec155f6622 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 03:45:04 +0000 Subject: [PATCH 06/18] chore(deps): update all non-major dependencies --- .pre-commit-config.yaml | 4 ++-- requirements-docker.txt | 2 +- requirements-lint.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c8f048e6..2a404e97e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: hooks: - id: black - repo: https://github.com/commitizen-tools/commitizen - rev: v3.13.0 + rev: v3.14.1 hooks: - id: commitizen stages: [commit-msg] @@ -47,6 +47,6 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/maxbrunet/pre-commit-renovate - rev: 37.153.0 + rev: 37.168.5 hooks: - id: renovate-config-validator diff --git a/requirements-docker.txt b/requirements-docker.txt index 5c52e5d06..7feca1b86 100644 --- a/requirements-docker.txt +++ b/requirements-docker.txt @@ -1,3 +1,3 @@ -r requirements.txt -r requirements-test.txt -pytest-docker==2.1.0 +pytest-docker==2.2.0 diff --git a/requirements-lint.txt b/requirements-lint.txt index e3064b975..590c3233b 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1,7 +1,7 @@ -r requirements.txt argcomplete==2.0.0 black==24.1.1 -commitizen==3.13.0 +commitizen==3.14.1 flake8==7.0.0 isort==5.13.2 mypy==1.8.0 From 35017167a80809a49351f9e95916fafe61c7bfd5 Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Sun, 4 Feb 2024 19:47:01 -0800 Subject: [PATCH 07/18] chore: update version of `black` for `pre-commit` The version of `black` needs to be updated to be in sync with what is in `requirements-lint.txt` --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a404e97e..ff28acc10 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black - repo: https://github.com/commitizen-tools/commitizen From 35d2aec04532919d6dd7b7090bc4d5209eddd10d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 04:01:06 +0000 Subject: [PATCH 08/18] chore(deps): update dependency pytest-docker to v3 --- requirements-docker.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docker.txt b/requirements-docker.txt index 7feca1b86..781e402ea 100644 --- a/requirements-docker.txt +++ b/requirements-docker.txt @@ -1,3 +1,3 @@ -r requirements.txt -r requirements-test.txt -pytest-docker==2.2.0 +pytest-docker==3.1.1 From 253babb9a7f8a7d469440fcfe1b2741ddcd8475e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 04:50:26 +0000 Subject: [PATCH 09/18] chore(deps): update dependency pytest to v8 --- requirements-lint.txt | 2 +- requirements-test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index 590c3233b..89037d3d6 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -6,7 +6,7 @@ flake8==7.0.0 isort==5.13.2 mypy==1.8.0 pylint==3.0.3 -pytest==7.4.4 +pytest==8.0.0 responses==0.24.1 types-PyYAML==6.0.12.12 types-requests==2.31.0.20240125 diff --git a/requirements-test.txt b/requirements-test.txt index f3b474f19..2aee02840 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -4,7 +4,7 @@ coverage==7.4.1 pytest-console-scripts==1.4.1 pytest-cov==4.1.0 pytest-github-actions-annotate-failures==0.2.0 -pytest==7.4.4 +pytest==8.0.0 PyYaml==6.0.1 responses==0.24.1 wheel==0.42.0 From f6fd02d956529e2c4bce261fe7b3da1442aaea12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 06:24:38 +0000 Subject: [PATCH 10/18] chore(deps): update dependency furo to v2024 --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 3e45437c2..a40c7727a 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,5 +1,5 @@ -r requirements.txt -furo==2023.9.10 +furo==2024.1.29 jinja2==3.1.3 myst-parser==2.0.0 sphinx==7.2.6 From c631eeb55556920f5975b1fa2b1a0354478ce3c0 Mon Sep 17 00:00:00 2001 From: Maximilian Linhoff Date: Thu, 8 Feb 2024 17:22:02 +0100 Subject: [PATCH 11/18] docs(artifacts): Fix argument indentation --- gitlab/v4/objects/artifacts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/v4/objects/artifacts.py b/gitlab/v4/objects/artifacts.py index 26816167c..d3336a026 100644 --- a/gitlab/v4/objects/artifacts.py +++ b/gitlab/v4/objects/artifacts.py @@ -62,7 +62,7 @@ def download( Args: ref_name: Branch or tag name in repository. HEAD or SHA references - are not supported. + are not supported. job: The name of the job. job_token: Job token for multi-project pipeline triggers. streamed: If True the data will be processed by chunks of From 9440a3255018d6a6e49269caf4c878d80db508a8 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 4 Feb 2024 17:20:00 +0000 Subject: [PATCH 12/18] fix(api): update manual job status when playing it --- gitlab/v4/objects/jobs.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gitlab/v4/objects/jobs.py b/gitlab/v4/objects/jobs.py index 952c2958c..8db30f50b 100644 --- a/gitlab/v4/objects/jobs.py +++ b/gitlab/v4/objects/jobs.py @@ -65,7 +65,10 @@ def play(self, **kwargs: Any) -> None: GitlabJobPlayError: If the job could not be triggered """ path = f"{self.manager.path}/{self.encoded_id}/play" - self.manager.gitlab.http_post(path, **kwargs) + result = self.manager.gitlab.http_post(path, **kwargs) + if TYPE_CHECKING: + assert isinstance(result, dict) + self._update_attrs(result) @cli.register_custom_action("ProjectJob") @exc.on_http_error(exc.GitlabJobEraseError) From a867c48baa6f10ffbfb785e624a6e3888a859571 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Sat, 10 Feb 2024 12:43:04 +0100 Subject: [PATCH 13/18] feat(api): allow updating protected branches (#2771) * feat(api): allow updating protected branches Closes #2390 --- docs/gl_objects/protected_branches.rst | 5 +++++ gitlab/v4/objects/branches.py | 13 ++++++++++--- tests/functional/api/test_projects.py | 23 +++++++++++++++++++++-- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/docs/gl_objects/protected_branches.rst b/docs/gl_objects/protected_branches.rst index 15e8948d8..8c4da9bc5 100644 --- a/docs/gl_objects/protected_branches.rst +++ b/docs/gl_objects/protected_branches.rst @@ -27,6 +27,11 @@ Get a single protected branch:: p_branch = project.protectedbranches.get('main') +Update a protected branch: + + p_branch.allow_force_push = True + p_branch.save() + Create a protected branch:: p_branch = project.protectedbranches.create({ diff --git a/gitlab/v4/objects/branches.py b/gitlab/v4/objects/branches.py index 9befe79a4..de7a046d3 100644 --- a/gitlab/v4/objects/branches.py +++ b/gitlab/v4/objects/branches.py @@ -1,7 +1,13 @@ from typing import Any, cast, Union from gitlab.base import RESTManager, RESTObject -from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin +from gitlab.mixins import ( + CRUDMixin, + NoUpdateMixin, + ObjectDeleteMixin, + SaveMixin, + UpdateMethod, +) from gitlab.types import RequiredOptional __all__ = [ @@ -28,11 +34,11 @@ def get( return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs)) -class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject): +class ProjectProtectedBranch(SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "name" -class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager): +class ProjectProtectedBranchManager(CRUDMixin, RESTManager): _path = "/projects/{project_id}/protected_branches" _obj_cls = ProjectProtectedBranch _from_parent_attrs = {"project_id": "id"} @@ -49,6 +55,7 @@ class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager): "code_owner_approval_required", ), ) + _update_method = UpdateMethod.PATCH def get( self, id: Union[str, int], lazy: bool = False, **kwargs: Any diff --git a/tests/functional/api/test_projects.py b/tests/functional/api/test_projects.py index ff9109c68..77bb8348b 100644 --- a/tests/functional/api/test_projects.py +++ b/tests/functional/api/test_projects.py @@ -258,12 +258,31 @@ def test_project_pages_domains(gl, project): assert domain not in project.pagesdomains.list() -def test_project_protected_branches(project): - p_b = project.protectedbranches.create({"name": "*-stable"}) +def test_project_protected_branches(project, wait_for_sidekiq, gitlab_version): + # Updating a protected branch is possible from Gitlab 15.6 + # https://docs.gitlab.com/ee/api/protected_branches.html#update-a-protected-branch + can_update_prot_branch = gitlab_version.major > 15 or ( + gitlab_version.major == 15 and gitlab_version.minor >= 6 + ) + + p_b = project.protectedbranches.create( + { + "name": "*-stable", + "allow_force_push": False, + } + ) assert p_b.name == "*-stable" + assert not p_b.allow_force_push assert p_b in project.protectedbranches.list() + if can_update_prot_branch: + p_b.allow_force_push = True + p_b.save() + wait_for_sidekiq(timeout=60) + p_b = project.protectedbranches.get("*-stable") + if can_update_prot_branch: + assert p_b.allow_force_push p_b.delete() assert p_b not in project.protectedbranches.list() From 3c4b27e64f4b51746b866f240a1291c2637355cc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:04:49 +0000 Subject: [PATCH 14/18] chore(deps): update all non-major dependencies --- .github/workflows/docs.yml | 2 +- .github/workflows/test.yml | 4 ++-- .pre-commit-config.yaml | 2 +- requirements-precommit.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 42b8fc33d..19e0f014b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -34,7 +34,7 @@ jobs: TOXENV: docs run: tox - name: Archive generated docs - uses: actions/upload-artifact@v4.3.0 + uses: actions/upload-artifact@v4.3.1 with: name: html-docs path: build/sphinx/html/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b4f3d8ebb..56b2d4094 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -119,7 +119,7 @@ jobs: pip install -r requirements-test.txt - name: Build package run: python -m build -o dist/ - - uses: actions/upload-artifact@v4.3.0 + - uses: actions/upload-artifact@v4.3.1 with: name: dist path: dist @@ -133,7 +133,7 @@ jobs: uses: actions/setup-python@v5.0.0 with: python-version: '3.12' - - uses: actions/download-artifact@v4.1.1 + - uses: actions/download-artifact@v4.1.2 with: name: dist path: dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff28acc10..ef44e53e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,6 +47,6 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/maxbrunet/pre-commit-renovate - rev: 37.168.5 + rev: 37.183.0 hooks: - id: renovate-config-validator diff --git a/requirements-precommit.txt b/requirements-precommit.txt index 5cef2202d..2e6e37675 100644 --- a/requirements-precommit.txt +++ b/requirements-precommit.txt @@ -1 +1 @@ -pre-commit==3.6.0 +pre-commit==3.6.1 From e11d889cd19ec1555b2bbee15355a8cdfad61d5f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 06:51:18 +0000 Subject: [PATCH 15/18] chore(deps): update python-semantic-release/python-semantic-release action to v9 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 177d1b3d1..27c6e064d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: - name: Python Semantic Release id: release - uses: python-semantic-release/python-semantic-release@v8.7.2 + uses: python-semantic-release/python-semantic-release@v9.0.3 with: github_token: ${{ secrets.RELEASE_GITHUB_TOKEN }} From 9596e09b5be519dd71a9aee75f101ff272c01cb5 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Fri, 19 Jan 2024 12:23:36 +0100 Subject: [PATCH 16/18] feat(job_token_scope): support job token access allowlist API --- docs/gl_objects/job_token_scope.rst | 20 ++++++++++++++++++++ gitlab/v4/objects/job_token_scope.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/docs/gl_objects/job_token_scope.rst b/docs/gl_objects/job_token_scope.rst index 370ffa282..2de8c6f1a 100644 --- a/docs/gl_objects/job_token_scope.rst +++ b/docs/gl_objects/job_token_scope.rst @@ -49,3 +49,23 @@ Refresh the current state of job token scope:: scope.refresh() print(scope.inbound_enabled) # False + +Get a project's CI/CD job token inbound allowlist:: + + allowlist = scope.allowlist.list() + +Add a project to the project's inbound allowlist:: + + allowed_project = scope.allowlist.create({"target_project_id": 42}) + +Remove a project from the project's inbound allowlist:: + + allowed_project.delete() + # or directly using a project ID + scope.allowlist.delete(42) + +.. warning:: + + Similar to above, the ID attributes you receive from the create and list + APIs are not consistent. To safely retrieve the ID of the allowlisted project + regardless of how the object was created, always use its ``.get_id()`` method. diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index 828fe012c..dcd29f55f 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -2,12 +2,18 @@ from gitlab.base import RESTManager, RESTObject from gitlab.mixins import ( + CreateMixin, + DeleteMixin, GetWithoutIdMixin, + ListMixin, + ObjectDeleteMixin, RefreshMixin, SaveMixin, UpdateMethod, UpdateMixin, ) +from gitlab.types import RequiredOptional + __all__ = [ "ProjectJobTokenScope", @@ -18,6 +24,8 @@ class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject): _id_attr = None + allowlist: "AllowlistedProjectManager" + class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): _path = "/projects/{project_id}/job_token_scope" @@ -27,3 +35,23 @@ class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): def get(self, **kwargs: Any) -> ProjectJobTokenScope: return cast(ProjectJobTokenScope, super().get(**kwargs)) + + +class AllowlistedProject(ObjectDeleteMixin, RESTObject): + _id_attr = "target_project_id" # note: only true for create endpoint + + def get_id(self) -> int: + """Returns the id of the resource. This override deals with + the fact that either an `id` or a `target_project_id` attribute + is returned by the server depending on the endpoint called.""" + try: + return cast(int, getattr(self, self._id_attr)) + except AttributeError: + return cast(int, getattr(self, "id")) + + +class AllowlistedProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): + _path = "/projects/{project_id}/job_token_scope/allowlist" + _obj_cls = AllowlistedProject + _from_parent_attrs = {"project_id": "project_id"} + _create_attrs = RequiredOptional(required=("target_project_id",)) From 4203bec5d9fdecd3079016006721983a18561d58 Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Tue, 13 Feb 2024 16:15:25 +0000 Subject: [PATCH 17/18] test: add api integration test for ci_cd_token allowlist Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 1 - .../api/test_project_job_token_scope.py | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/functional/api/test_project_job_token_scope.py diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index dcd29f55f..1a1c58bf6 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -14,7 +14,6 @@ ) from gitlab.types import RequiredOptional - __all__ = [ "ProjectJobTokenScope", "ProjectJobTokenScopeManager", diff --git a/tests/functional/api/test_project_job_token_scope.py b/tests/functional/api/test_project_job_token_scope.py new file mode 100644 index 000000000..11e42de9b --- /dev/null +++ b/tests/functional/api/test_project_job_token_scope.py @@ -0,0 +1,43 @@ +def test_add_project_to_job_token_scope_allowlist(gl, project): + project_to_add = gl.projects.create({"name": "Ci_Cd_token_add_proj"}) + + scope = project.job_token_scope.get() + resp = scope.allowlist.create({"target_project_id": project_to_add.id}) + + assert resp.source_project_id == project.id + assert resp.target_project_id == project_to_add.id + + project_to_add.delete() + + +def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, project): + scope = project.job_token_scope.get() + assert len(scope.allowlist.list()) == 0 + + project_name = "Ci_Cd_token_named_proj" + project_to_add = gl.projects.create({"name": project_name}) + scope.allowlist.create({"target_project_id": project_to_add.id}) + + scope.refresh() + assert any(allowed.name == project_name for allowed in scope.allowlist.list()) + + project_to_add.delete() + + +def test_remove_project_by_id_from_projects_job_token_scope_allowlist(gl, project): + scope = project.job_token_scope.get() + assert len(scope.allowlist.list()) == 0 + + project_to_add = gl.projects.create({"name": "Ci_Cd_token_remove_proj"}) + + scope.allowlist.create({"target_project_id": project_to_add.id}) + + scope.refresh() + assert len(scope.allowlist.list()) != 0 + + scope.allowlist.remove(project_to_add.id) + + scope.refresh() + assert len(scope.allowlist.list()) == 0 + + project_to_add.delete() From e2cae6576dca4ed37b12c5076bff2531835ce4d5 Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 14 Feb 2024 11:25:05 +0000 Subject: [PATCH 18/18] test: skip in Gitlab 15 Signed-off-by: Tim Knight --- tests/functional/api/test_project_job_token_scope.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/functional/api/test_project_job_token_scope.py b/tests/functional/api/test_project_job_token_scope.py index 11e42de9b..694c4bc4c 100644 --- a/tests/functional/api/test_project_job_token_scope.py +++ b/tests/functional/api/test_project_job_token_scope.py @@ -1,3 +1,8 @@ +import pytest + + +# TODO: can be enabled when https://github.com/python-gitlab/python-gitlab/pull/2790 merged +@pytest.mark.xfail(reason="project job_token_scope api only in 16.*") def test_add_project_to_job_token_scope_allowlist(gl, project): project_to_add = gl.projects.create({"name": "Ci_Cd_token_add_proj"}) @@ -10,6 +15,7 @@ def test_add_project_to_job_token_scope_allowlist(gl, project): project_to_add.delete() +@pytest.mark.xfail(reason="project job_token_scope api only in 16.*") def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, project): scope = project.job_token_scope.get() assert len(scope.allowlist.list()) == 0 @@ -24,6 +30,7 @@ def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, proj project_to_add.delete() +@pytest.mark.xfail(reason="project job_token_scope api only in 16.*") def test_remove_project_by_id_from_projects_job_token_scope_allowlist(gl, project): scope = project.job_token_scope.get() assert len(scope.allowlist.list()) == 0