######## Projects ######## Projects ======== Reference --------- * v4 API: + :class:`gitlab.v4.objects.Project` + :class:`gitlab.v4.objects.ProjectManager` + :attr:`gitlab.Gitlab.projects` * GitLab API: https://docs.gitlab.com/ce/api/projects.html Examples -------- List projects:: projects = gl.projects.list() The API provides several filtering parameters for the listing methods: * ``archived``: if ``True`` only archived projects will be returned * ``visibility``: returns only projects with the specified visibility (can be ``public``, ``internal`` or ``private``) * ``search``: returns project matching the given pattern Results can also be sorted using the following parameters: * ``order_by``: sort using the given argument. Valid values are ``id``, ``name``, ``path``, ``created_at``, ``updated_at`` and ``last_activity_at``. The default is to sort by ``created_at`` * ``sort``: sort order (``asc`` or ``desc``) :: # List all projects (default 20) projects = gl.projects.list(all=True) # Archived projects projects = gl.projects.list(archived=1) # Limit to projects with a defined visibility projects = gl.projects.list(visibility='public') # List owned projects projects = gl.projects.list(owned=True) # List starred projects projects = gl.projects.list(starred=True) # Search projects projects = gl.projects.list(search='keyword') .. note:: To list the starred projects of another user, see the :ref:`Users API docs `. .. note:: Fetching a list of projects, doesn't include all attributes of all projects. To retrieve all attributes, you'll need to fetch a single project Get a single project:: # Get a project by ID project_id = 851 project = gl.projects.get(project_id) # Get a project by name with namespace project_name_with_namespace = "namespace/project_name" project = gl.projects.get(project_name_with_namespace) Create a project:: project = gl.projects.create({'name': 'project1'}) Create a project for a user (admin only):: alice = gl.users.list(username='alice')[0] user_project = alice.projects.create({'name': 'project'}) user_projects = alice.projects.list() Create a project in a group:: # You need to get the id of the group, then use the namespace_id attribute # to create the group group_id = gl.groups.list(search='my-group')[0].id project = gl.projects.create({'name': 'myrepo', 'namespace_id': group_id}) List a project's groups:: # Get a list of ancestor/parent groups for a project. groups = project.groups.list() Update a project:: project.snippets_enabled = 1 project.save() Set the avatar image for a project:: # the avatar image can be passed as data (content of the file) or as a file # object opened in binary mode project.avatar = open('path/to/file.png', 'rb') project.save() Delete a project:: gl.projects.delete(project_id) # or project.delete() Fork a project:: fork = project.forks.create({}) # fork to a specific namespace fork = project.forks.create({'namespace': 'myteam'}) Get a list of forks for the project:: forks = project.forks.list() Create/delete a fork relation between projects (requires admin permissions):: project.create_fork_relation(source_project.id) project.delete_fork_relation() Get languages used in the project with percentage value:: languages = project.languages() Star/unstar a project:: project.star() project.unstar() Archive/unarchive a project:: project.archive() project.unarchive() Start the housekeeping job:: project.housekeeping() List the repository tree:: # list the content of the root directory for the default branch items = project.repository_tree() # list the content of a subdirectory on a specific branch items = project.repository_tree(path='docs', ref='branch1') Get the content and metadata of a file for a commit, using a blob sha:: items = project.repository_tree(path='docs', ref='branch1') file_info = p.repository_blob(items[0]['id']) content = base64.b64decode(file_info['content']) size = file_info['size'] Update a project submodule:: items = project.update_submodule( submodule="foo/bar", branch="main", commit_sha="4c3674f66071e30b3311dac9b9ccc90502a72664", commit_message="Message", # optional ) Get the repository archive:: tgz = project.repository_archive() # get the archive for a branch/tag/commit tgz = project.repository_archive(sha='4567abc') # get the archive in a different format zip = project.repository_archive(format='zip') .. note:: For the formats available, refer to https://docs.gitlab.com/ce/api/repositories.html#get-file-archive .. warning:: Archives are entirely stored in memory unless you use the streaming feature. See :ref:`the artifacts example `. Get the content of a file using the blob id:: # find the id for the blob (simple search) id = [d['id'] for d in p.repository_tree() if d['name'] == 'README.rst'][0] # get the content file_content = p.repository_raw_blob(id) .. warning:: Blobs are entirely stored in memory unless you use the streaming feature. See :ref:`the artifacts example `. Get a snapshot of the repository:: tar_file = project.snapshot() .. warning:: Snapshots are entirely stored in memory unless you use the streaming feature. See :ref:`the artifacts example `. Compare two branches, tags or commits:: result = project.repository_compare('main', 'branch1') # get the commits for commit in result['commits']: print(commit) # get the diffs for file_diff in result['diffs']: print(file_diff) Get a list of contributors for the repository:: contributors = project.repository_contributors() Get a list of users for the repository:: users = p.users.list() # search for users users = p.users.list(search='pattern') Start the pull mirroring process (EE edition):: project.mirror_pull() Import / Export =============== You can export projects from gitlab, and re-import them to create new projects or overwrite existing ones. Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectExport` + :class:`gitlab.v4.objects.ProjectExportManager` + :attr:`gitlab.v4.objects.Project.exports` + :class:`gitlab.v4.objects.ProjectImport` + :class:`gitlab.v4.objects.ProjectImportManager` + :attr:`gitlab.v4.objects.Project.imports` + :attr:`gitlab.v4.objects.ProjectManager.import_project` * GitLab API: https://docs.gitlab.com/ce/api/project_import_export.html Examples -------- A project export is an asynchronous operation. To retrieve the archive generated by GitLab you need to: #. Create an export using the API #. Wait for the export to be done #. Download the result :: # Create the export p = gl.projects.get(my_project) export = p.exports.create() # Wait for the 'finished' status export.refresh() while export.export_status != 'finished': time.sleep(1) export.refresh() # Download the result with open('/tmp/export.tgz', 'wb') as f: export.download(streamed=True, action=f.write) Import the project:: output = gl.projects.import_project(open('/tmp/export.tgz', 'rb'), 'my_new_project') # Get a ProjectImport object to track the import status project_import = gl.projects.get(output['id'], lazy=True).imports.get() while project_import.import_status != 'finished': time.sleep(1) project_import.refresh() Project custom attributes ========================= Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectCustomAttribute` + :class:`gitlab.v4.objects.ProjectCustomAttributeManager` + :attr:`gitlab.v4.objects.Project.customattributes` * GitLab API: https://docs.gitlab.com/ce/api/custom_attributes.html Examples -------- List custom attributes for a project:: attrs = project.customattributes.list() Get a custom attribute for a project:: attr = project.customattributes.get(attr_key) Set (create or update) a custom attribute for a project:: attr = project.customattributes.set(attr_key, attr_value) Delete a custom attribute for a project:: attr.delete() # or project.customattributes.delete(attr_key) Search projects by custom attribute:: project.customattributes.set('type', 'internal') gl.projects.list(custom_attributes={'type': 'internal'}) Project files ============= Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectFile` + :class:`gitlab.v4.objects.ProjectFileManager` + :attr:`gitlab.v4.objects.Project.files` * GitLab API: https://docs.gitlab.com/ce/api/repository_files.html Examples -------- Get a file:: f = project.files.get(file_path='README.rst', ref='main') # get the base64 encoded content print(f.content) # get the decoded content print(f.decode()) Get a raw file:: raw_content = project.files.raw(file_path='README.rst', ref='main') print(raw_content) with open('/tmp/raw-download.txt', 'wb') as f: project.files.raw(file_path='README.rst', ref='main', streamed=True, action=f.write) Create a new file:: f = project.files.create({'file_path': 'testfile.txt', 'branch': 'main', 'content': file_content, 'author_email': 'test@example.com', 'author_name': 'yourname', 'commit_message': 'Create testfile'}) Update a file. The entire content must be uploaded, as plain text or as base64 encoded text:: f.content = 'new content' f.save(branch='main', commit_message='Update testfile') # or for binary data # Note: decode() is required with python 3 for data serialization. You can omit # it with python 2 f.content = base64.b64encode(open('image.png').read()).decode() f.save(branch='main', commit_message='Update testfile', encoding='base64') Delete a file:: f.delete(commit_message='Delete testfile', branch='main') # or project.files.delete(file_path='testfile.txt', commit_message='Delete testfile', branch='main') Get file blame:: b = project.files.blame(file_path='README.rst', ref='main') Project tags ============ Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectTag` + :class:`gitlab.v4.objects.ProjectTagManager` + :attr:`gitlab.v4.objects.Project.tags` * GitLab API: https://docs.gitlab.com/ce/api/tags.html Examples -------- List the project tags:: tags = project.tags.list() Get a tag:: tag = project.tags.get('1.0') Create a tag:: tag = project.tags.create({'tag_name': '1.0', 'ref': 'main'}) Delete a tag:: project.tags.delete('1.0') # or tag.delete() .. _project_snippets: Project snippets ================ The snippet visibility can be defined using the following constants: * ``gitlab.const.VISIBILITY_PRIVATE`` * ``gitlab.const.VISIBILITY_INTERNAL`` * ``gitlab.const.VISIBILITY_PUBLIC`` Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectSnippet` + :class:`gitlab.v4.objects.ProjectSnippetManager` + :attr:`gitlab.v4.objects.Project.files` * GitLab API: https://docs.gitlab.com/ce/api/project_snippets.html Examples -------- List the project snippets:: snippets = project.snippets.list() Get a snippet:: snippet = project.snippets.get(snippet_id) Get the content of a snippet:: print(snippet.content()) .. warning:: The snippet content is entirely stored in memory unless you use the streaming feature. See :ref:`the artifacts example `. Create a snippet:: snippet = project.snippets.create({'title': 'sample 1', 'file_name': 'foo.py', 'code': 'import gitlab', 'visibility_level': gitlab.const.VISIBILITY_PRIVATE}) Update a snippet:: snippet.code = 'import gitlab\nimport whatever' snippet.save Delete a snippet:: project.snippets.delete(snippet_id) # or snippet.delete() Get user agent detail (admin only):: detail = snippet.user_agent_detail() Notes ===== See :ref:`project-notes`. Project members =============== Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectMember` + :class:`gitlab.v4.objects.ProjectMemberManager` + :class:`gitlab.v4.objects.ProjectMemberAllManager` + :attr:`gitlab.v4.objects.Project.members` + :attr:`gitlab.v4.objects.Project.members_all` * GitLab API: https://docs.gitlab.com/ce/api/members.html Examples -------- List only direct project members:: members = project.members.list() List the project members recursively (including inherited members through ancestor groups):: members = project.members_all.list(all=True) Search project members matching a query string:: members = project.members.list(query='bar') Get only direct project member:: member = project.members.get(user_id) Get a member of a project, including members inherited through ancestor groups:: members = project.members_all.get(member_id) Add a project member:: member = project.members.create({'user_id': user.id, 'access_level': gitlab.const.DEVELOPER_ACCESS}) Modify a project member (change the access level):: member.access_level = gitlab.const.MAINTAINER_ACCESS member.save() Remove a member from the project team:: project.members.delete(user.id) # or member.delete() Share/unshare the project with a group:: project.share(group.id, gitlab.const.DEVELOPER_ACCESS) project.unshare(group.id) Project hooks ============= Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectHook` + :class:`gitlab.v4.objects.ProjectHookManager` + :attr:`gitlab.v4.objects.Project.hooks` * GitLab API: https://docs.gitlab.com/ce/api/projects.html#hooks Examples -------- List the project hooks:: hooks = project.hooks.list() Get a project hook:: hook = project.hooks.get(hook_id) Create a project hook:: hook = project.hooks.create({'url': 'http://my/action/url', 'push_events': 1}) Update a project hook:: hook.push_events = 0 hook.save() Delete a project hook:: project.hooks.delete(hook_id) # or hook.delete() Project Services ================ Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectService` + :class:`gitlab.v4.objects.ProjectServiceManager` + :attr:`gitlab.v4.objects.Project.services` * GitLab API: https://docs.gitlab.com/ce/api/services.html Examples --------- Get a service:: service = project.services.get('asana') # display its status (enabled/disabled) print(service.active) List active project services:: service = project.services.list() List the code names of available services (doesn't return objects):: services = project.services.available() Configure and enable a service:: service.api_key = 'randomkey' service.save() Disable a service:: service.delete() File uploads ============ Reference --------- * v4 API: + :attr:`gitlab.v4.objects.Project.upload` * Gitlab API: https://docs.gitlab.com/ce/api/projects.html#upload-a-file Examples -------- Upload a file into a project using a filesystem path:: project.upload("filename.txt", filepath="/some/path/filename.txt") Upload a file into a project without a filesystem path:: project.upload("filename.txt", filedata="Raw data") Upload a file and comment on an issue using the uploaded file's markdown:: uploaded_file = project.upload("filename.txt", filedata="data") issue = project.issues.get(issue_id) issue.notes.create({ "body": "See the attached file: {}".format(uploaded_file["markdown"]) }) Upload a file and comment on an issue while using custom markdown to reference the uploaded file:: uploaded_file = project.upload("filename.txt", filedata="data") issue = project.issues.get(issue_id) issue.notes.create({ "body": "See the [attached file]({})".format(uploaded_file["url"]) }) Project push rules ================== Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectPushRules` + :class:`gitlab.v4.objects.ProjectPushRulesManager` + :attr:`gitlab.v4.objects.Project.pushrules` * GitLab API: https://docs.gitlab.com/ee/api/projects.html#push-rules Examples --------- Create project push rules (at least one rule is necessary):: project.pushrules.create({'deny_delete_tag': True}) Get project push rules (returns None is there are no push rules):: pr = project.pushrules.get() Edit project push rules:: pr.branch_name_regex = '^(main|develop|support-\d+|release-\d+\..+|hotfix-.+|feature-.+)$' pr.save() Delete project push rules:: pr.delete() Project protected tags ====================== Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectProtectedTag` + :class:`gitlab.v4.objects.ProjectProtectedTagManager` + :attr:`gitlab.v4.objects.Project.protectedtags` * GitLab API: https://docs.gitlab.com/ce/api/protected_tags.html Examples --------- Get a list of protected tags from a project:: protected_tags = project.protectedtags.list() Get a single protected tag or wildcard protected tag:: protected_tag = project.protectedtags.get('v*') Protect a single repository tag or several project repository tags using a wildcard protected tag:: project.protectedtags.create({'name': 'v*', 'create_access_level': '40'}) Unprotect the given protected tag or wildcard protected tag.:: protected_tag.delete() Additional project statistics ============================= Reference --------- * v4 API: + :class:`gitlab.v4.objects.ProjectAdditionalStatistics` + :class:`gitlab.v4.objects.ProjectAdditionalStatisticsManager` + :attr:`gitlab.v4.objects.Project.additionalstatistics` * GitLab API: https://docs.gitlab.com/ce/api/project_statistics.html Examples --------- Get all additional statistics of a project:: statistics = project.additionalstatistics.get() Get total fetches in last 30 days of a project:: total_fetches = project.additionalstatistics.get().fetches['total']