diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c974f3a45..cb8eab5d6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,7 +22,7 @@ jobs: sphinx: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python uses: actions/setup-python@v5.6.0 with: @@ -37,7 +37,7 @@ jobs: twine-check: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python uses: actions/setup-python@v5.6.0 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d16f7fe09..0647754dc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 with: fetch-depth: 0 - uses: actions/setup-python@v5.6.0 diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml index 9fadeca81..4da71860a 100644 --- a/.github/workflows/pre_commit.yml +++ b/.github/workflows/pre_commit.yml @@ -29,7 +29,7 @@ jobs: pre_commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - uses: actions/setup-python@v5.6.0 with: python-version: "3.13" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 576c1befb..cdf090887 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,14 +14,14 @@ jobs: id-token: write environment: pypi.org steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 with: fetch-depth: 0 token: ${{ secrets.RELEASE_GITHUB_TOKEN }} - name: Python Semantic Release id: release - uses: python-semantic-release/python-semantic-release@v10.2.0 + uses: python-semantic-release/python-semantic-release@v10.3.1 with: github_token: ${{ secrets.RELEASE_GITHUB_TOKEN }} @@ -32,7 +32,7 @@ jobs: if: steps.release.outputs.released == 'true' - name: Publish package distributions to GitHub Releases - uses: python-semantic-release/publish-action@v10.2.0 + uses: python-semantic-release/publish-action@v10.3.1 if: steps.release.outputs.released == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 17d514b11..d8c32dd8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: version: "3.13" toxenv: py313,smoke steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python ${{ matrix.python.version }} uses: actions/setup-python@v5.6.0 with: @@ -67,7 +67,7 @@ jobs: matrix: toxenv: [api_func_v4, cli_func_v4] steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python uses: actions/setup-python@v5.6.0 with: @@ -79,7 +79,7 @@ jobs: TOXENV: ${{ matrix.toxenv }} run: tox -- --override-ini='log_cli=True' - name: Upload codecov coverage - uses: codecov/codecov-action@v5.4.3 + uses: codecov/codecov-action@v5.5.0 with: files: ./coverage.xml flags: ${{ matrix.toxenv }} @@ -89,7 +89,7 @@ jobs: coverage: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5.6.0 with: @@ -102,7 +102,7 @@ jobs: TOXENV: cover run: tox - name: Upload codecov coverage - uses: codecov/codecov-action@v5.4.3 + uses: codecov/codecov-action@v5.5.0 with: files: ./coverage.xml flags: unit @@ -113,7 +113,7 @@ jobs: runs-on: ubuntu-latest name: Python wheel steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - uses: actions/setup-python@v5.6.0 with: python-version: "3.13" @@ -131,12 +131,12 @@ jobs: runs-on: ubuntu-latest needs: [dist] steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v5.0.0 - name: Set up Python uses: actions/setup-python@v5.6.0 with: python-version: '3.13' - - uses: actions/download-artifact@v4.3.0 + - uses: actions/download-artifact@v5.0.0 with: name: dist path: dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f18249f20..cf5dd8e24 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: hooks: - id: isort - repo: https://github.com/pycqa/pylint - rev: v3.3.7 + rev: v3.3.8 hooks: - id: pylint additional_dependencies: @@ -32,7 +32,7 @@ repos: - requests-toolbelt==1.0.0 files: 'gitlab/' - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.17.0 + rev: v1.17.1 hooks: - id: mypy args: [] @@ -51,6 +51,6 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/maxbrunet/pre-commit-renovate - rev: 41.42.1 + rev: 41.82.10 hooks: - id: renovate-config-validator diff --git a/docs/gl_objects/remote_mirrors.rst b/docs/gl_objects/remote_mirrors.rst index b4610117d..c672ca5bb 100644 --- a/docs/gl_objects/remote_mirrors.rst +++ b/docs/gl_objects/remote_mirrors.rst @@ -36,3 +36,7 @@ Update an existing remote mirror's attributes:: Delete an existing remote mirror:: mirror.delete() + +Force push mirror update:: + + mirror.sync() diff --git a/gitlab/_version.py b/gitlab/_version.py index 2f7a85281..c9434cd63 100644 --- a/gitlab/_version.py +++ b/gitlab/_version.py @@ -3,4 +3,4 @@ __email__ = "gauvainpocentek@gmail.com" __license__ = "LGPL3" __title__ = "python-gitlab" -__version__ = "6.2.0" +__version__ = "6.3.0" diff --git a/gitlab/v4/objects/jobs.py b/gitlab/v4/objects/jobs.py index 6aa6fc460..f0062c989 100644 --- a/gitlab/v4/objects/jobs.py +++ b/gitlab/v4/objects/jobs.py @@ -346,5 +346,5 @@ class ProjectJobManager(RetrieveMixin[ProjectJob]): _path = "/projects/{project_id}/jobs" _obj_cls = ProjectJob _from_parent_attrs = {"project_id": "id"} - _list_filters = ("scope",) + _list_filters = ("scope", "order_by", "sort") _types = {"scope": ArrayAttribute} diff --git a/gitlab/v4/objects/packages.py b/gitlab/v4/objects/packages.py index 1a59c7ec7..99edd2f83 100644 --- a/gitlab/v4/objects/packages.py +++ b/gitlab/v4/objects/packages.py @@ -220,6 +220,9 @@ class GroupPackageManager(ListMixin[GroupPackage]): "sort", "package_type", "package_name", + "package_version", + "include_versionless", + "status", ) @@ -234,7 +237,15 @@ class ProjectPackageManager( _path = "/projects/{project_id}/packages" _obj_cls = ProjectPackage _from_parent_attrs = {"project_id": "id"} - _list_filters = ("order_by", "sort", "package_type", "package_name") + _list_filters = ( + "order_by", + "sort", + "package_type", + "package_name", + "package_version", + "include_versionless", + "status", + ) class ProjectPackageFile(ObjectDeleteMixin, RESTObject): diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py index b415a8b98..035b9b861 100644 --- a/gitlab/v4/objects/projects.py +++ b/gitlab/v4/objects/projects.py @@ -1233,7 +1233,20 @@ def create(self, data: dict[str, Any] | None = None, **kwargs: Any) -> ProjectFo class ProjectRemoteMirror(ObjectDeleteMixin, SaveMixin, RESTObject): - pass + @cli.register_custom_action(cls_names="ProjectRemoteMirror") + @exc.on_http_error(exc.GitlabCreateError) + def sync(self, **kwargs: Any) -> dict[str, Any] | requests.Response: + """Force push mirror update. + + Args: + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabCreateError: If the server cannot perform the request + """ + path = f"{self.manager.path}/{self.encoded_id}/sync" + return self.manager.gitlab.http_post(path, **kwargs) class ProjectRemoteMirrorManager( diff --git a/gitlab/v4/objects/users.py b/gitlab/v4/objects/users.py index dec0b375d..2c2393eba 100644 --- a/gitlab/v4/objects/users.py +++ b/gitlab/v4/objects/users.py @@ -410,6 +410,7 @@ class UserManager(CRUDMixin[User]): "custom_attributes", "status", "two_factor", + "admins", ) _create_attrs = RequiredOptional( optional=( diff --git a/requirements-lint.txt b/requirements-lint.txt index 73eb2fda0..6d326d8bd 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -4,11 +4,11 @@ black==25.1.0 commitizen==4.8.3 flake8==7.3.0 isort==6.0.1 -mypy==1.17.0 -pylint==3.3.7 +mypy==1.17.1 +pylint==3.3.8 pytest==8.4.1 -responses==0.25.7 +responses==0.25.8 respx==0.22.0 -types-PyYAML==6.0.12.20250516 -types-requests==2.32.4.20250611 -types-setuptools==80.9.0.20250529 +types-PyYAML==6.0.12.20250822 +types-requests==2.32.4.20250809 +types-setuptools==80.9.0.20250822 diff --git a/requirements-precommit.txt b/requirements-precommit.txt index d5c247795..3ee862221 100644 --- a/requirements-precommit.txt +++ b/requirements-precommit.txt @@ -1 +1 @@ -pre-commit==4.2.0 +pre-commit==4.3.0 diff --git a/requirements-test.txt b/requirements-test.txt index 26d3b35af..36e60a2bb 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,13 +1,13 @@ -r requirements.txt -anyio==4.9.0 -build==1.2.2.post1 -coverage==7.9.2 +anyio==4.10.0 +build==1.3.0 +coverage==7.10.5 pytest-console-scripts==1.4.1 pytest-cov==6.2.1 pytest-github-actions-annotate-failures==0.3.0 pytest==8.4.1 PyYaml==6.0.2 -responses==0.25.7 +responses==0.25.8 respx==0.22.0 trio==0.30.0 wheel==0.45.1 diff --git a/requirements.txt b/requirements.txt index 7941900de..6930e5d2c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ gql==3.5.3 httpx==0.28.1 -requests==2.32.4 +requests==2.32.5 requests-toolbelt==1.0.0 diff --git a/tests/unit/objects/test_remote_mirrors.py b/tests/unit/objects/test_remote_mirrors.py index f493032e8..be2aaaaba 100644 --- a/tests/unit/objects/test_remote_mirrors.py +++ b/tests/unit/objects/test_remote_mirrors.py @@ -54,6 +54,12 @@ def resp_remote_mirrors(): url="http://localhost/api/v4/projects/1/remote_mirrors/1", status=204, ) + + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/remote_mirrors/1/sync", + status=204, + ) yield rsps @@ -81,3 +87,9 @@ def test_update_project_remote_mirror(project, resp_remote_mirrors): def test_delete_project_remote_mirror(project, resp_remote_mirrors): mirror = project.remote_mirrors.create({"url": "https://example.com"}) mirror.delete() + + +def test_sync_project_remote_mirror(project, resp_remote_mirrors): + mirror = project.remote_mirrors.create({"url": "https://example.com"}) + response = mirror.sync() + assert response.status_code == 204