8000 feat: add support for commit GPG signature by nejch · Pull Request #1055 · python-gitlab/python-gitlab · GitHub
[go: up one dir, main page]

Skip to content

feat: add support for commit GPG signature #1055

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,18 @@ Create a snippet:
$ gitlab project-snippet create --project-id 2 --title "the title" \
--file-name "the name" --code "the code"

Get a specific project commit by its SHA id:

.. code-block:: console

$ gitlab project-commit get --project-id 2 --id a43290c

Get the GPG signature of a signed commit:

.. code-block:: console

$ gitlab project-commit signature --project-id 2 --id a43290c

Define the status of a commit (as would be done from a CI tool for example):

.. code-block:: console
Expand Down
4 changes: 4 additions & 0 deletions docs/gl_objects/commits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ Get the references the commit has been pushed to (branches and tags)::
commit.refs('tag') # only tags
commit.refs('branch') # only branches

Get the GPG signature of the commit (if the commit was signed)::

commit.signature()

List the merge requests related to a commit::

commit.merge_requests()
Expand Down
106 changes: 106 additions & 0 deletions gitlab/tests/objects/test_commits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from httmock import urlmatch, response, with_httmock

from .test_projects import headers, TestProject


@urlmatch(
scheme="http",
netloc="localhost",
path="/api/v4/projects/1/repository/commits/6b2257ea",
method="get",
)
def resp_get_commit(url, request):
"""Mock for commit GET response."""
content = """{
"id": "6b2257eabcec3db1f59dafbd84935e3caea04235",
"short_id": "6b2257ea",
"title": "Initial commit"
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)


@urlmatch(
scheme="http", path="/api/v4/projects/1/repository/commits", method="post",
)
def resp_create_commit(url, request):
"""Mock for commit create POST response."""
content = """{
"id": "ed899a2f4b50b4370feeea94676502b42383c746",
"short_id": "ed899a2f",
"title": "Commit message"
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)


@urlmatch(
scheme="http", path="/api/v4/projects/1/repository/commits/6b2257ea", method="post",
)
def resp_revert_commit(url, request):
"""Mock for commit revert POST response."""
content = """{
"id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
"short_id": "8b090c1b",
"title":"Revert \\"Initial commit\\""
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)


@urlmatch(
scheme="http",
netloc="localhost",
path="/api/v4/projects/1/repository/commits/6b2257ea/signature",
method="get",
)
def resp_get_commit_gpg_signature(url, request):
"""Mock for commit GPG signature GET response."""
content = """{
"gpg_key_id": 1,
"gpg_key_primary_keyid": "8254AAB3FBD54AC9",
"gpg_key_user_name": "John Doe",
"gpg_key_user_email": "johndoe@example.com",
"verification_status": "verified",
"gpg_key_subkey_id": null
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)


class TestCommit(TestProject):
"""
Base class for commit tests. Inheri 8000 ts from TestProject,
since currently all commit methods are under projects.
"""

@with_httmock(resp_get_commit)
def test_get_commit(self):
commit = self.project.commits.get("6b2257ea")
self.assertEqual(commit.short_id, "6b2257ea")
self.assertEqual(commit.title, "Initial commit")

@with_httmock(resp_create_commit)
def test_create_commit(self):
data = {
"branch": "master",
"commit_message": "Commit message",
"actions": [{"action": "create", "file_path": "README", "content": "",}],
}
commit = self.project.commits.create(data)
self.assertEqual(commit.short_id, "ed899a2f")
self.assertEqual(commit.title, data["commit_message"])

@with_httmock(resp_revert_commit)
def test_revert_commit(self):
commit = self.project.commits.get("6b2257ea", lazy=True)
revert_commit = commit.revert(branch="master")
self.assertEqual(revert_commit["short_id"], "8b090c1b")
self.assertEqual(revert_commit["title"], 'Revert "Initial commit"')

@with_httmock(resp_get_commit_gpg_signature)
def test_get_commit_gpg_signature(self):
commit = self.project.commits.get("6b2257ea", lazy=True)
signature = commit.signature()
self.assertEqual(signature["gpg_key_primary_keyid"], "8254AAB3FBD54AC9")
self.assertEqual(signature["verification_status"], "verified")
44 changes: 0 additions & 44 deletions gitlab/tests/test_gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,50 +843,6 @@ def resp_deactivate(url, request):
self.gl.users.get(1, lazy=True).activate()
self.gl.users.get(1, lazy=True).deactivate()

def test_commit_revert(self):
@urlmatch(
scheme="http",
netloc="localhost",
path="/api/v4/projects/1/repository/commits/6b2257ea",
method="get",
)
def resp_get_commit(url, request):
headers = {"content-type": "application/json"}
content = """{
"id": "6b2257eabcec3db1f59dafbd84935e3caea04235",
"short_id": "6b2257ea",
"title": "Initial commit"
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)

@urlmatch(
scheme="http",
netloc="localhost",
path="/api/v4/projects/1/repository/commits/6b2257ea",
method="post",
)
def resp_revert_commit(url, request):
headers = {"content-type": "application/json"}
content = """{
"id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
"short_id": "8b090c1b",
"title":"Revert \\"Initial commit\\""
}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)

with HTTMock(resp_get_commit):
project = self.gl.projects.get(1, lazy=True)
commit = project.commits.get("6b2257ea")
self.assertEqual(commit.short_id, "6b2257ea")
self.assertEqual(commit.title, "Initial commit")

with HTTMock(resp_revert_commit):
revert_commit = commit.revert(branch="master")
self.assertEqual(revert_commit["short_id"], "8b090c1b")
self.assertEqual(revert_commit["title"], 'Revert "Initial commit"')

def test_update_submodule(self):
@urlmatch(
scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get"
Expand Down
18 changes: 18 additions & 0 deletions gitlab/v4/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,24 @@ def revert(self, branch, **kwargs):
post_data = {"branch": branch}
return self.manager.gitlab.http_post(path, post_data=post_data, **kwargs)

@cli.register_custom_action("ProjectCommit")
@exc.on_http_error(exc.GitlabGetError)
def signature(self, **kwargs):
"""Get the GPG signature of the commit.

Args:
**kwargs: Extra options to send to the server (e.g. sudo)

Raises:
GitlabAuthenticationError: If authentication is not correct
GitlabGetError: If the signature could not be retrieved

Returns:
dict: The commit's GPG signature data
"""
path = "%s/%s/signature" % (self.manager.path, self.get_id())
return self.manager.gitlab.http_get(path, **kwargs)


class ProjectCommitManager(RetrieveMixin, CreateMixin, RESTManager):
_path = "/projects/%(project_id)s/repository/commits"
Expand Down
7 changes: 7 additions & 0 deletions tools/cli_test_v4.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ testcase "revert commit" '
--id "$COMMIT_ID" --branch master
'

# Test commit GPG signature
testcase "attempt to get GPG signature of unsigned commit" '
OUTPUT=$(GITLAB project-commit signature --project-id "$PROJECT_ID" \
--id "$COMMIT_ID" 2>&1 || exit 0)
echo "$OUTPUT" | grep -q "404 GPG Signature Not Found"
'

# Test project labels
testcase "create project label" '
OUTPUT=$(GITLAB -v project-label create --project-id $PROJECT_ID \
Expand Down
8 changes: 8 additions & 0 deletions tools/python_test_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,14 @@
# assert commit.refs()
# assert commit.merge_requests()

# commit GPG signature (for unsigned commits)
# TODO: reasonable tests for signed commits?
try:
signature = commit.signature()
except gitlab.GitlabGetError as e:
error_message = e.error_message
assert error_message == "404 GPG Signature Not Found"

# commit comment
commit.comments.create({"note": "This is a commit comment"})
# assert len(commit.comments.list()) == 1
Expand Down
0