# Projects

### Reference

- v4 API:
  - `gitlab.v4.objects.Project`
  - `gitlab.v4.objects.ProjectManager`
  - `gitlab.Gitlab.projects`
- v3 API:
  - `gitlab.v3.objects.Project`
  - `gitlab.v3.objects.ProjectManager`
  - `gitlab.Gitlab.projects`
- GitLab API: https://docs.gitlab.com/ce/api/projects.html

### Examples

List projects:

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`)

    # Active projects
    projects = gl.projects.list()
    # 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.owned()

    # List starred projects
    projects = gl.projects.starred()

    # List all the projects
    projects = gl.projects.all()

    # Search projects
    projects = gl.projects.list(search='keyword')

Get a single project:

    # Get a project by ID
    project = gl.projects.get(10)
    # Get a project by userspace/name
    project = gl.projects.get('myteam/myproject')

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.search('my-group')[0].id
    project = gl.projects.create({'name': 'myrepo', 'namespace_id': group_id})

Update a project:

    project.snippets_enabled = 1
    project.save()

Delete a project:

    gl.projects.delete(1)
    # or
    project.delete()

Fork a project:

    fork = project.forks.create({})

    # fork to a specific namespace
    fork = project.forks.create({'namespace': 'myteam'})

Create/delete a fork relation between projects (requires admin permissions):

    project.create_fork_relation(source_project.id)
    project.delete_fork_relation()

Star/unstar a project:

    project.star()
    project.unstar()

Archive/unarchive a project:

    project.archive()
    project.unarchive()

Note

Previous versions used `archive_` and `unarchive_` due to a naming issue, they have been deprecated but not yet removed.

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']

Get the repository archive:

    # get the archive for the default branch
    tgz = project.repository_archive()

    # get the archive for a branch/tag/commit
    tgz = project.repository_archive(sha='4567abc')

Warning

Archives are entirely stored in memory unless you use the streaming feature. See 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 the artifacts example.

Compare two branches, tags or commits:

    result = project.repository_compare('master', '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')

## Project custom attributes

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectCustomAttribute`
  - `gitlab.v4.objects.ProjectCustomAttributeManager`
  - `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:
  - `gitlab.v4.objects.ProjectFile`
  - `gitlab.v4.objects.ProjectFileManager`
  - `gitlab.v4.objects.Project.files`
- v3 API:
  - `gitlab.v3.objects.ProjectFile`
  - `gitlab.v3.objects.ProjectFileManager`
  - `gitlab.v3.objects.Project.files`
  - `gitlab.Gitlab.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='master')

    # get the base64 encoded content
    print(f.content)

    # get the decoded content
    print(f.decode())

Create a new file:

    # v4
    f = project.files.create({'file_path': 'testfile',
                              'branch': 'master',
                              'content': file_content,
                              'commit_message': 'Create testfile'})

    # v3
    f = project.files.create({'file_path': 'testfile',
                              'branch_name': 'master',
                              'content': file_content,
                              '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='master', commit_message='Update testfile')  # v4
    f.save(branch_name='master', commit_message='Update testfile')  # v3

    # 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='master', commit_message='Update testfile', encoding='base64')

Delete a file:

    f.delete(commit_message='Delete testfile')

## Project tags

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectTag`
  - `gitlab.v4.objects.ProjectTagManager`
  - `gitlab.v4.objects.Project.tags`
- v3 API:
  - `gitlab.v3.objects.ProjectTag`
  - `gitlab.v3.objects.ProjectTagManager`
  - `gitlab.v3.objects.Project.tags`
  - `gitlab.Gitlab.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': 'master'})

Set or update the release note for a tag:

    tag.set_release_description('awesome v1.0 release')

Delete a tag:

    project.tags.delete('1.0')
    # or
    tag.delete()

## Project snippets

The snippet visibility can be definied using the following constants:

- `gitlab.VISIBILITY_PRIVATE`
- `gitlab.VISIBILITY_INTERNAL`
- `gitlab.VISIBILITY_PUBLIC`

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectSnippet`
  - `gitlab.v4.objects.ProjectSnippetManager`
  - `gitlab.v4.objects.Project.files`
- v3 API:
  - `gitlab.v3.objects.ProjectSnippet`
  - `gitlab.v3.objects.ProjectSnippetManager`
  - `gitlab.v3.objects.Project.files`
  - `gitlab.Gitlab.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:

    snippets = project.snippets.list(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 the artifacts example.

Create a snippet:

    snippet = project.snippets.create({'title': 'sample 1',
                                       'file_name': 'foo.py',
                                       'code': 'import gitlab',
                                       'visibility_level':
                                       gitlab.VISIBILITY_PRIVATE})

Update a snippet:

    snippet.code = 'import gitlab\nimport whatever'
    snippet.save

Delete a snippet:

    project.snippets.delete(snippet_id)
    # or
    snippet.delete()

## Notes

You can manipulate notes (comments) on the issues, merge requests and snippets.

- `ProjectIssue` with `ProjectIssueNote`
- `ProjectMergeRequest` with `ProjectMergeRequestNote`
- `ProjectSnippet` with `ProjectSnippetNote`

### Reference

- v4 API:

  Issues:

  - `gitlab.v4.objects.ProjectIssueNote`
  - `gitlab.v4.objects.ProjectIssueNoteManager`
  - `gitlab.v4.objects.ProjectIssue.notes`

  MergeRequests:

  - `gitlab.v4.objects.ProjectMergeRequestNote`
  - `gitlab.v4.objects.ProjectMergeRequestNoteManager`
  - `gitlab.v4.objects.ProjectMergeRequest.notes`

  Snippets:

  - `gitlab.v4.objects.ProjectSnippetNote`
  - `gitlab.v4.objects.ProjectSnippetNoteManager`
  - `gitlab.v4.objects.ProjectSnippet.notes`

- v3 API:

  Issues:

  - `gitlab.v3.objects.ProjectIssueNote`
  - `gitlab.v3.objects.ProjectIssueNoteManager`
  - `gitlab.v3.objects.ProjectIssue.notes`
  - `gitlab.v3.objects.Project.issue_notes`
  - `gitlab.Gitlab.project_issue_notes`

  MergeRequests:

  - `gitlab.v3.objects.ProjectMergeRequestNote`
  - `gitlab.v3.objects.ProjectMergeRequestNoteManager`
  - `gitlab.v3.objects.ProjectMergeRequest.notes`
  - `gitlab.v3.objects.Project.mergerequest_notes`
  - `gitlab.Gitlab.project_mergerequest_notes`

  Snippets:

  - `gitlab.v3.objects.ProjectSnippetNote`
  - `gitlab.v3.objects.ProjectSnippetNoteManager`
  - `gitlab.v3.objects.ProjectSnippet.notes`
  - `gitlab.v3.objects.Project.snippet_notes`
  - `gitlab.Gitlab.project_snippet_notes`

- GitLab API: https://docs.gitlab.com/ce/api/repository_files.html

### Examples

List the notes for a resource:

    i_notes = issue.notes.list()
    mr_notes = mr.notes.list()
    s_notes = snippet.notes.list()

Get a note for a resource:

    i_note = issue.notes.get(note_id)
    mr_note = mr.notes.get(note_id)
    s_note = snippet.notes.get(note_id)

Create a note for a resource:

    i_note = issue.notes.create({'body': 'note content'})
    mr_note = mr.notes.create({'body': 'note content'})
    s_note = snippet.notes.create({'body': 'note content'})

Update a note for a resource:

    note.body = 'updated note content'
    note.save()

Delete a note for a resource:

    note.delete()

## Project members

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectMember`
  - `gitlab.v4.objects.ProjectMemberManager`
  - `gitlab.v4.objects.Project.members`
- v3 API:
  - `gitlab.v3.objects.ProjectMember`
  - `gitlab.v3.objects.ProjectMemberManager`
  - `gitlab.v3.objects.Project.members`
  - `gitlab.Gitlab.project_members`
- GitLab API: https://docs.gitlab.com/ce/api/members.html

### Examples

List the project members:

    members = project.members.list()

Search project members matching a query string:

    members = project.members.list(query='bar')

Get a single project member:

    member = project.members.get(1)

Add a project member:

    member = project.members.create({'user_id': user.id, 'access_level':
                                     gitlab.DEVELOPER_ACCESS})

Modify a project member (change the access level):

    member.access_level = gitlab.MASTER_ACCESS
    member.save()

Remove a member from the project team:

    project.members.delete(user.id)
    # or
    member.delete()

Share the project with a group:

    project.share(group.id, gitlab.DEVELOPER_ACCESS)

## Project hooks

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectHook`
  - `gitlab.v4.objects.ProjectHookManager`
  - `gitlab.v4.objects.Project.hooks`
- v3 API:
  - `gitlab.v3.objects.ProjectHook`
  - `gitlab.v3.objects.ProjectHookManager`
  - `gitlab.v3.objects.Project.hooks`
  - `gitlab.Gitlab.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(1)

Create a project hook:

    hook = gl.project_hooks.create({'url': 'http://my/action/url',
                                    'push_events': 1},
                                   project_id=1)
    # or
    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(1)
    # or
    hook.delete()

## Project Services

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectService`
  - `gitlab.v4.objects.ProjectServiceManager`
  - `gitlab.v4.objects.Project.services`
- v3 API:
  - `gitlab.v3.objects.ProjectService`
  - `gitlab.v3.objects.ProjectServiceManager`
  - `gitlab.v3.objects.Project.services`
  - `gitlab.Gitlab.project_services`
- GitLab API: https://docs.gitlab.com/ce/api/services.html

### Exammples

Get a service:

    # For v3
    service = project.services.get(service_name='asana', project_id=1)
    # For v4
    service = project.services.get('asana')
    # display its status (enabled/disabled)
    print(service.active)

List the code names of available services (doesn’t return objects):

    services = gl.project_services.available()

Configure and enable a service:

    service.api_key = 'randomkey'
    service.save()

Disable a service:

    service.delete()

## Issue boards

Boards are a visual representation of existing issues for a project. Issues can be moved from one list to the other to track progress and help with priorities.

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectBoard`
  - `gitlab.v4.objects.ProjectBoardManager`
  - `gitlab.v4.objects.Project.boards`
- v3 API:
  - `gitlab.v3.objects.ProjectBoard`
  - `gitlab.v3.objects.ProjectBoardManager`
  - `gitlab.v3.objects.Project.boards`
  - `gitlab.Gitlab.project_boards`
- GitLab API: https://docs.gitlab.com/ce/api/boards.html

### Examples

Get the list of existing boards for a project:

    boards = project.boards.list()

Get a single board for a project:

    board = project.boards.get(board_id)

## Board lists

### Reference

- v4 API:
  - `gitlab.v4.objects.ProjectBoardList`
  - `gitlab.v4.objects.ProjectBoardListManager`
  - `gitlab.v4.objects.Project.board_lists`
- v3 API:
  - `gitlab.v3.objects.ProjectBoardList`
  - `gitlab.v3.objects.ProjectBoardListManager`
  - `gitlab.v3.objects.ProjectBoard.lists`
  - `gitlab.v3.objects.Project.board_lists`
  - `gitlab.Gitlab.project_board_lists`
- GitLab API: https://docs.gitlab.com/ce/api/boards.html

### Examples

List the issue lists for a board:

    b_lists = board.lists.list()

Get a single list:

    b_list = board.lists.get(list_id)

Create a new list:

    # First get a ProjectLabel
    label = get_or_create_label()
    # Then use its ID to create the new board list
    b_list = board.lists.create({'label_id': label.id})

Change a list position. The first list is at position 0. Moving a list will set it at the given position and move the following lists up a position:

    b_list.position = 2
    b_list.save()

Delete a list:

    b_list.delete()

## File uploads

### Reference

- v4 API:
  - `gitlab.v4.objects.Project.upload`
- v3 API:
  - `gitlab.v3.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:

    # Or provide a full path to the uploaded file
    project.upload("filename.txt", filepath="/some/path/filename.txt")

Upload a file into a project without a filesystem path:

    # Upload a file using its filename and filedata
    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"])
    })