diff options
| -rw-r--r-- | .gitlab-ci.yml | 96 | ||||
| -rw-r--r-- | .travis.yml | 21 | ||||
| -rw-r--r-- | docs/api-objects.rst | 2 | ||||
| -rw-r--r-- | docs/gl_objects/projects.rst | 33 | ||||
| -rw-r--r-- | docs/gl_objects/repositories.rst | 28 | ||||
| -rw-r--r-- | docs/gl_objects/repository_tags.rst | 47 | ||||
| -rw-r--r-- | gitlab/__init__.py | 2 | ||||
| -rw-r--r-- | gitlab/v4/objects.py | 57 | ||||
| -rw-r--r-- | tools/Dockerfile-test | 34 |
9 files changed, 298 insertions, 22 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..0b8fa4f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,96 @@ +image: python:3.7 + +stages: + - lint + - build-test-image + - test + - deploy + +commitlint: + image: node:12 + stage: lint + before_script: + - npm install -g @commitlint/cli @commitlint/config-conventional + - 'echo "module.exports = {extends: [\"@commitlint/config-conventional\"]}" > commitlint.config.js' + script: + - npx commitlint --from=origin/master + except: + - master + +#build_test_image: # Currently hangs forever, because of GitLab Runner infrastructure issues +# stage: build-test-image +# image: +# name: gcr.io/kaniko-project/executor:debug +# entrypoint: [""] +# script: +# - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json +# - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/tools/Dockerfile-test --destination $CI_REGISTRY_IMAGE:test +# only: +# refs: +# - master +# changes: +# - tools/ + +.tox_includes: &tox_includes + stage: test + before_script: + - pip install tox + script: + - tox -e $TOX_ENV + +test_2.7: + <<: *tox_includes + image: python:2.7 + variables: + TOX_ENV: py27 + +test_3.4: + <<: *tox_includes + image: python:3.4 + variables: + TOX_ENV: py34 + +test_3.5: + <<: *tox_includes + image: python:3.5 + variables: + TOX_ENV: py35 + +test_3.6: + <<: *tox_includes + image: python:3.6 + variables: + TOX_ENV: py36 + +test_3.7: + <<: *tox_includes + image: python:3.7 + variables: + TOX_ENV: py37 + +test_3.8: + <<: *tox_includes + image: python:3.8-rc-alpine + variables: + TOX_ENV: py38 + allow_failure: true + +test_docs: + <<: *tox_includes + variables: + TOX_ENV: docs + +deploy: + stage: deploy + script: + - pip install -U setuptools wheel twine + - python setup.py sdist bdist_wheel + # test package + - python3 -m venv test + - . test/bin/activate + - pip install -U dist/python-gitlab*.whl + - gitlab -h + - deactivate + - twine upload --skip-existing -u $TWINE_USERNAME -p $TWINE_PASSWORD dist/* + only: + - tags diff --git a/.travis.yml b/.travis.yml index e96e86f..1e9cc4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,33 +1,12 @@ sudo: required services: - docker -addons: - apt: - sources: - - deadsnakes - packages: - - python3.5 language: python python: 2.7 env: - - TOX_ENV=py35 - - TOX_ENV=py34 - - TOX_ENV=py27 - - TOX_ENV=pep8 - - TOX_ENV=docs - TOX_ENV=py_func_v4 - TOX_ENV=cli_func_v4 install: - pip install tox script: - tox -e $TOX_ENV - -deploy: - provider: pypi - user: max-wittig - password: - secure: LmNkZdbNe1oBSJ/PeTCKXaeu9Ml/biY4ZN4aedbD4lLXbxV/sgsHEE4N1Xrg2D/CJsnNjBY7CHzO0vL5iak8IRpV61xkdquZHvAUQKuhjMY30HopReAEw8sP+Wpf3lYcD1BjC5KT9vqWG99feoQ6epRt//Xm4DdkBYNmmUsCsMBTZLlGnj3B/mE8w+XQxQpdA2QzpRJ549N12vidwZRKqP0Zuug3rELVSo64O2bpqarKx/EeUUhTXZ0Y4XeVYgvuHBjvPqtuSJzR17CNkjaBhacD7EFTP34sAaCKGRDpfYiiiGx9LeKOEAv5Hj0+LOqEC/o6EyiIFviE+HvLQ/kBLJ6Oo2p47fibyIU/YOAFdZYKmBRq2ZUaV0DhhuuCRPZ+yLrsuaFRrKTVEMsHVtdsXJkW5gKG08vwOndW+kamppRhkAcdFVyokIgu/6nPBRWMuS6ue2aKoKRdP2gmqk0daKM1ao2uv06A2/J1/xkPy1EX5MjyK8Mh78ooKjITp5DHYn8l1pxaB0YcEkRzfwMyLErGQaRDgo7rCOm0tTRNhArkn0VE1/KLKFbATo2NSxZDwUJQ5TBNCEqfdBN1VzNEduJ7ajbZpq3DsBRM/9hzQ5LLxn7azMl9m+WmT12Qcgz25wg2Sgbs9Z2rT6fto5h8GSLpy8ReHo+S6fALJBzA4pg= - distributions: sdist bdist_wheel - on: - tags: true - skip_existing: true diff --git a/docs/api-objects.rst b/docs/api-objects.rst index 0cc5014..451e411 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -34,6 +34,8 @@ API examples gl_objects/pagesdomains gl_objects/projects gl_objects/runners + gl_objects/repositories + gl_objects/repository_tags gl_objects/search gl_objects/settings gl_objects/snippets diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index b91f5f2..c151889 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -663,6 +663,39 @@ Delete project push rules:: pr.delete() +Project releases +================ + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectRelease` + + :class:`gitlab.v4.objects.ProjectReleaseManager` + + :attr:`gitlab.v4.objects.Project.releases` + +* Gitlab API: https://docs.gitlab.com/ee/api/releases/index.html + +Examples +-------- + +Get a list of releases from a project:: + + release = project.releases.list() + +Get a single release:: + + release = project.releases.get('v1.2.3') + +Create a release for a project tag:: + + release = project.releases.create({'name':'Demo Release', 'tag_name':'v1.2.3', 'description':'release notes go here'}) + +Delete a release:: + + release = p.releases.delete('v1.2.3') + Project protected tags ====================== diff --git a/docs/gl_objects/repositories.rst b/docs/gl_objects/repositories.rst new file mode 100644 index 0000000..6622c0c --- /dev/null +++ b/docs/gl_objects/repositories.rst @@ -0,0 +1,28 @@ +##################### +Registry Repositories +##################### + +References +---------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectRegistryRepository` + + :class:`gitlab.v4.objects.ProjectRegistryRepositoryManager` + + :attr:`gitlab.v4.objects.Project.repositories` + +* Gitlab API: https://docs.gitlab.com/ce/api/container_registry.html + +Examples +-------- + +Get the list of container registry repositories associated with the project:: + + repositories = project.repositories.list() + +Delete repository:: + + project.repositories.delete(id=x) + # or + repository = repositories.pop() + repository.delete() diff --git a/docs/gl_objects/repository_tags.rst b/docs/gl_objects/repository_tags.rst new file mode 100644 index 0000000..94593da --- /dev/null +++ b/docs/gl_objects/repository_tags.rst @@ -0,0 +1,47 @@ +######################## +Registry Repository Tags +######################## + +References +---------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectRegistryTag` + + :class:`gitlab.v4.objects.ProjectRegistryTagManager` + + :attr:`gitlab.v4.objects.Repository.tags` + +* Gitlab API: https://docs.gitlab.com/ce/api/container_registry.html + +Examples +-------- + +Get the list of repository tags in given registry:: + + repositories = project.repositories.list() + repository = repositories.pop() + tags = repository.tags.list() + +Get specific tag:: + + repository.tags.get(id=tag_name) + +Delete tag:: + + repository.tags.delete(id=tag_name) + # or + tag = repository.tags.get(id=tag_name) + tag.delete() + +Delete tag in bulk:: + + repository.tags.delete_in_bulk(keep_n=1) + # or + repository.tags.delete_in_bulk(older_than="1m") + # or + repository.tags.delete_in_bulk(name_regex="v.+", keep_n=2) + +.. note:: + + Delete in bulk is asnychronous operation and may take a while. + Refer to: https://docs.gitlab.com/ce/api/container_registry.html#delete-repository-tags-in-bulk diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 819096d..9532267 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -359,7 +359,7 @@ class Gitlab(object): def enable_debug(self): import logging try: - from http.client import HTTPConnection + from http.client import HTTPConnection # noqa except ImportError: from httplib import HTTPConnection # noqa diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 2175e0c..ed559cf 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1177,6 +1177,49 @@ class PagesDomainManager(ListMixin, RESTManager): _obj_cls = PagesDomain +class ProjectRegistryRepository(ObjectDeleteMixin, RESTObject): + _managers = ( + ('tags', 'ProjectRegistryTagManager'), + ) + + +class ProjectRegistryRepositoryManager(DeleteMixin, ListMixin, RESTManager): + _path = '/projects/%(project_id)s/registry/repositories' + _obj_cls = ProjectRegistryRepository + _from_parent_attrs = {'project_id': 'id'} + + +class ProjectRegistryTag(ObjectDeleteMixin, RESTObject): + _id_attr = 'name' + + +class ProjectRegistryTagManager(DeleteMixin, RetrieveMixin, RESTManager): + _obj_cls = ProjectRegistryTag + _from_parent_attrs = {'project_id': 'project_id', 'repository_id': 'id'} + _path = '/projects/%(project_id)s/registry/repositories/%(repository_id)s/tags' + + @cli.register_custom_action('ProjectRegistryTagManager', optional=('name_regex', 'keep_n', 'older_than')) + @exc.on_http_error(exc.GitlabDeleteError) + def delete_in_bulk(self, name_regex='.*', **kwargs): + """Delete Tag in bulk + + Args: + name_regex (string): The regex of the name to delete. To delete all + tags specify .*. + keep_n (integer): The amount of latest tags of given name to keep. + older_than (string): Tags to delete that are older than the given time, + written in human readable form 1h, 1d, 1month. + **kwargs: Extra options to send to the server (e.g. sudo) + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabDeleteError: If the server cannot perform the request + """ + valid_attrs = ['keep_n', 'older_than'] + data = {'name_regex': name_regex} + data.update({k: v for k, v in kwargs.items() if k in valid_attrs}) + self.gitlab.http_delete(self.path, query_data=data, **kwargs) + + class ProjectBoardList(SaveMixin, ObjectDeleteMixin, RESTObject): pass @@ -1993,6 +2036,18 @@ class ProjectPagesDomainManager(CRUDMixin, RESTManager): _update_attrs = (tuple(), ('certificate', 'key')) +class ProjectRelease(RESTObject): + _id_attr = 'tag_name' + + +class ProjectReleaseManager(NoUpdateMixin, RESTManager): + _path = '/projects/%(project_id)s/releases' + _obj_cls = ProjectRelease + _from_parent_attrs = {'project_id': 'id'} + _create_attrs = (('name', 'tag_name', 'description', ), + ('ref', 'assets', )) + + class ProjectTag(ObjectDeleteMixin, RESTObject): _id_attr = 'name' _short_print_attr = 'name' @@ -3273,6 +3328,8 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject): ('protectedtags', 'ProjectProtectedTagManager'), ('pipelineschedules', 'ProjectPipelineScheduleManager'), ('pushrules', 'ProjectPushRulesManager'), + ('releases', 'ProjectReleaseManager'), + ('repositories', 'ProjectRegistryRepositoryManager'), ('runners', 'ProjectRunnerManager'), ('services', 'ProjectServiceManager'), ('snippets', 'ProjectSnippetManager'), diff --git a/tools/Dockerfile-test b/tools/Dockerfile-test new file mode 100644 index 0000000..7d491de --- /dev/null +++ b/tools/Dockerfile-test @@ -0,0 +1,34 @@ +FROM ubuntu:16.04 +# based on Vincent Robert <vincent.robert@genezys.net> initial Dockerfile +MAINTAINER Gauvain Pocentek <gauvain@pocentek.net> + +# Install required packages +RUN apt-get update \ + && apt-get install -qy --no-install-recommends \ + openssh-server \ + ca-certificates \ + curl \ + tzdata \ + && curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash \ + && apt-get install -qy --no-install-recommends \ + gitlab-ce=11.10.0-ce.0 + +# Manage SSHD through runit +RUN mkdir -p /opt/gitlab/sv/sshd/supervise \ + && mkfifo /opt/gitlab/sv/sshd/supervise/ok \ + && printf "#!/bin/sh\nexec 2>&1\numask 077\nexec /usr/sbin/sshd -D" > /opt/gitlab/sv/sshd/run \ + && chmod a+x /opt/gitlab/sv/sshd/run \ + && ln -s /opt/gitlab/sv/sshd /opt/gitlab/service \ + && mkdir -p /var/run/sshd + +# Default root password +RUN echo "gitlab_rails['initial_root_password'] = '5iveL!fe'" >> /etc/gitlab/gitlab.rb; \ + sed -i "s,^external_url.*,external_url 'http://gitlab.test'," /etc/gitlab/gitlab.rb; \ + echo 'pages_external_url "http://pages.gitlab.lxd/"' >> /etc/gitlab/gitlab.rb; \ + echo "gitlab_pages['enable'] = true" >> /etc/gitlab/gitlab.rb + +# Expose web & ssh +EXPOSE 80 22 + +# Default is to run runit & reconfigure +CMD sleep 3 && gitlab-ctl reconfigure & /opt/gitlab/embedded/bin/runsvdir-start |
