Skip to content

feat: support GPG signature check #261

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions commit_check/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
'error': 'Signed-off-by not found in latest commit',
'suggest': 'run command `git commit -m "conventional commit message" --signoff`',
},
{
'check': 'gpg_signature',
'regex': r'', # Not used for GPG signature check
'error': 'Commit does not have a valid GPG signature',
'suggest': 'run command `git commit -S` to sign your commits with GPG',
},
{
'check': 'merge_base',
'regex': r'main', # it can be master, develop, devel etc based on your project.
Expand Down
63 changes: 63 additions & 0 deletions commit_check/commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,69 @@ def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int:
return PASS


def check_commit_gpg_signature(checks: list) -> int:
"""Check if commit has a valid GPG signature."""
if has_commits() is False:
return PASS # pragma: no cover

for check in checks:
if check['check'] == 'gpg_signature':
# Get GPG signature status using git log --pretty=format:"%G?"
try:
gpg_status = cmd_output(['git', 'log', '--pretty=format:%G?', '-1']).strip()
commit_hash = get_commit_info("H")

# GPG status codes:
# G = good (valid) signature
# B = bad signature
# U = good signature with unknown validity
# X = good signature that has expired
# Y = good signature made by an expired key
# R = good signature made by a revoked key
# E = signature cannot be checked (e.g., missing public key)
# N = no signature

if gpg_status not in ['G', 'U']: # Only accept good signatures
if not print_error_header.has_been_called:
print_error_header() # pragma: no cover

error_msg = check['error']
if gpg_status == 'N':
error_msg = 'Commit is not signed with GPG'
elif gpg_status == 'B':
error_msg = 'Commit has a bad GPG signature'
elif gpg_status == 'E':
error_msg = 'GPG signature cannot be verified (missing public key?)'
elif gpg_status == 'X':
error_msg = 'GPG signature has expired'
elif gpg_status == 'Y':
error_msg = 'GPG signature made by an expired key'
elif gpg_status == 'R':
error_msg = 'GPG signature made by a revoked key'

print_error_message(
check['check'], f'GPG Status: {gpg_status}',
error_msg, commit_hash,
)
if check['suggest']:
print_suggestion(check['suggest'])
return FAIL

except Exception:
# If we can't check GPG status, treat as failure
if not print_error_header.has_been_called:
print_error_header() # pragma: no cover
print_error_message(
check['check'], 'Unknown',
'Unable to check GPG signature status', get_commit_info("H"),
)
if check['suggest']:
print_suggestion(check['suggest'])
return FAIL

return PASS


def check_imperative(checks: list, commit_msg_file: str = "") -> int:
"""Check if commit message uses imperative mood."""
if has_commits() is False:
Expand Down
10 changes: 10 additions & 0 deletions commit_check/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ def get_parser() -> argparse.ArgumentParser:
required=False,
)

parser.add_argument(
'-g',
'--gpg-signature',
help='check commit GPG signature',
action="store_true",
required=False,
)

parser.add_argument(
'-mb',
'--merge-base',
Expand Down Expand Up @@ -128,6 +136,8 @@ def main() -> int:
check_results.append(branch.check_branch(checks))
if args.commit_signoff:
check_results.append(commit.check_commit_signoff(checks))
if args.gpg_signature:
check_results.append(commit.check_commit_gpg_signature(checks))
if args.merge_base:
check_results.append(branch.check_merge_base(checks))
if args.imperative:
Expand Down
167 changes: 166 additions & 1 deletion tests/commit_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from commit_check import PASS, FAIL
from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff, check_imperative
from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff, check_commit_gpg_signature, check_imperative

# used by get_commit_info mock
FAKE_BRANCH_NAME = "fake_commits_info"
Expand Down Expand Up @@ -398,3 +398,168 @@ def test_is_imperative_invalid_cases():

for case in invalid_cases:
assert not _is_imperative(case), f"'{case}' should not be imperative mood"


# GPG Signature tests
@pytest.mark.benchmark
def test_check_commit_gpg_signature_valid(mocker):
"""Test GPG signature check passes for good signature."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="G")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")

retval = check_commit_gpg_signature(checks)
assert retval == PASS
Comment on lines +405 to +418
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix missing mock for has_commits function.

The test is likely failing because has_commits() is not mocked, causing the function to potentially return early with PASS before executing the GPG check logic.

Add the missing mock:

     mocker.patch("commit_check.util.cmd_output", return_value="G")
     mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
+    mocker.patch("commit_check.commit.has_commits", return_value=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_check_commit_gpg_signature_valid(mocker):
"""Test GPG signature check passes for good signature."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", return_value="G")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
retval = check_commit_gpg_signature(checks)
assert retval == PASS
def test_check_commit_gpg_signature_valid(mocker):
"""Test GPG signature check passes for good signature."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", return_value="G")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
mocker.patch("commit_check.commit.has_commits", return_value=True)
retval = check_commit_gpg_signature(checks)
assert retval == PASS
🧰 Tools
🪛 GitHub Actions: main

[error] 418-418: AssertionError: test_check_commit_gpg_signature_valid failed. Expected PASS but got failure indicating GPG signature check did not pass.

🤖 Prompt for AI Agents
In tests/commit_test.py around lines 405 to 418, the
test_check_commit_gpg_signature_valid function is missing a mock for the
has_commits function, which may cause the test to return early and not properly
test the GPG signature logic. Add a mock for has_commits to return True before
calling check_commit_gpg_signature to ensure the GPG signature check code is
executed during the test.



@pytest.mark.benchmark
def test_check_commit_gpg_signature_valid_unknown(mocker):
"""Test GPG signature check passes for good signature with unknown validity."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="U")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")

retval = check_commit_gpg_signature(checks)
assert retval == PASS
Comment on lines +422 to +435
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix missing mock for has_commits function.

Same issue as the previous test - missing has_commits() mock.

Add the missing mock:

     mocker.patch("commit_check.util.cmd_output", return_value="U")
     mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
+    mocker.patch("commit_check.commit.has_commits", return_value=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_check_commit_gpg_signature_valid_unknown(mocker):
"""Test GPG signature check passes for good signature with unknown validity."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", return_value="U")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
retval = check_commit_gpg_signature(checks)
assert retval == PASS
def test_check_commit_gpg_signature_valid_unknown(mocker):
"""Test GPG signature check passes for good signature with unknown validity."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", return_value="U")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
mocker.patch("commit_check.commit.has_commits", return_value=True)
retval = check_commit_gpg_signature(checks)
assert retval == PASS
🧰 Tools
🪛 GitHub Actions: main

[error] 435-435: AssertionError: test_check_commit_gpg_signature_valid_unknown failed. Expected PASS but got failure indicating GPG signature check did not pass for unknown validity.

🤖 Prompt for AI Agents
In tests/commit_test.py around lines 422 to 435, the test is missing a mock for
the has_commits() function, which is necessary for the test to run correctly.
Add a mock for has_commits() using mocker.patch to return True or an appropriate
value before calling check_commit_gpg_signature. This will ensure the test
environment simulates the presence of commits properly.



@pytest.mark.benchmark
def test_check_commit_gpg_signature_no_signature(mocker):
"""Test GPG signature check fails for unsigned commit."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="N")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")

retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1

Comment on lines +439 to +457
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add missing has_commits mock for consistency.

These tests should also mock has_commits() to ensure consistent test behavior and prevent potential early returns.

Add the missing mock to all GPG signature tests:

+    mocker.patch("commit_check.commit.has_commits", return_value=True)

Also applies to: 460-478, 481-499, 502-520

🤖 Prompt for AI Agents
In tests/commit_test.py around lines 439 to 457, the
test_check_commit_gpg_signature_no_signature function is missing a mock for
has_commits(), which can cause inconsistent test behavior or early returns. Add
a mock for has_commits() returning True in this test and similarly add the same
mock to the other GPG signature tests at lines 460-478, 481-499, and 502-520 to
ensure consistent test execution.


@pytest.mark.benchmark
def test_check_commit_gpg_signature_bad_signature(mocker):
"""Test GPG signature check fails for bad signature."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="B")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")

retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1


@pytest.mark.benchmark
def test_check_commit_gpg_signature_expired(mocker):
"""Test GPG signature check fails for expired signature."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="X")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")

retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1


@pytest.mark.benchmark
def test_check_commit_gpg_signature_cannot_check(mocker):
"""Test GPG signature check fails when signature cannot be verified."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", return_value="E")
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")

retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1


@pytest.mark.benchmark
def test_check_commit_gpg_signature_exception(mocker):
"""Test GPG signature check fails when git command throws exception."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.util.cmd_output", side_effect=Exception("Git command failed"))
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")

retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1

Comment on lines +523 to +541
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix exception test setup and add missing mock.

The exception test needs proper mocking and should handle the case where both cmd_output and get_commit_info might fail.

     mocker.patch("commit_check.util.cmd_output", side_effect=Exception("Git command failed"))
-    mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
+    mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
+    mocker.patch("commit_check.commit.has_commits", return_value=True)

The test should pass with these mocks since the exception handler in the implementation calls get_commit_info("H") which is mocked to return "abc123".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_check_commit_gpg_signature_exception(mocker):
"""Test GPG signature check fails when git command throws exception."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", side_effect=Exception("Git command failed"))
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")
retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1
def test_check_commit_gpg_signature_exception(mocker):
"""Test GPG signature check fails when git command throws exception."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]
mocker.patch("commit_check.util.cmd_output", side_effect=Exception("Git command failed"))
mocker.patch("commit_check.util.get_commit_info", return_value="abc123")
mocker.patch("commit_check.commit.has_commits", return_value=True)
m_print_error_message = mocker.patch(f"{LOCATION}.print_error_message")
m_print_suggestion = mocker.patch(f"{LOCATION}.print_suggestion")
retval = check_commit_gpg_signature(checks)
assert retval == FAIL
assert m_print_error_message.call_count == 1
assert m_print_suggestion.call_count == 1
🧰 Tools
🪛 GitHub Actions: main

[error] 537-537: Exception: test_check_commit_gpg_signature_exception failed due to 'Git command failed' exception raised during GPG signature check.

🤖 Prompt for AI Agents
In tests/commit_test.py around lines 523 to 541, the test for GPG signature
exception handling lacks proper mocking for both cmd_output and get_commit_info
functions. Fix this by ensuring that cmd_output is mocked to raise an Exception
and get_commit_info is also mocked to return a valid commit hash like "abc123".
This setup will correctly simulate the exception scenario and allow the test to
pass as the exception handler calls get_commit_info("H").


@pytest.mark.benchmark
def test_check_commit_gpg_signature_no_commits(mocker):
"""Test GPG signature check passes when no commits exist."""
checks = [{
"check": "gpg_signature",
"regex": "",
"error": "Commit does not have a valid GPG signature",
"suggest": "Use git commit -S to sign commits"
}]

mocker.patch("commit_check.commit.has_commits", return_value=False)

retval = check_commit_gpg_signature(checks)
assert retval == PASS


@pytest.mark.benchmark
def test_check_commit_gpg_signature_empty_checks(mocker):
"""Test GPG signature check with empty checks list."""
checks = []

retval = check_commit_gpg_signature(checks)
assert retval == PASS
40 changes: 24 additions & 16 deletions tests/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@

class TestMain:
@pytest.mark.benchmark
@pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count, check_imperative_call_count", [
([CMD, "--message"], 1, 0, 0, 0, 0, 0),
([CMD, "--branch"], 0, 1, 0, 0, 0, 0),
([CMD, "--author-name"], 0, 0, 1, 0, 0, 0),
([CMD, "--author-email"], 0, 0, 1, 0, 0, 0),
([CMD, "--commit-signoff"], 0, 0, 0, 1, 0, 0),
([CMD, "--merge-base"], 0, 0, 0, 0, 1, 0),
([CMD, "--imperative"], 0, 0, 0, 0, 0, 1),
([CMD, "--message", "--author-email"], 1, 0, 1, 0, 0, 0),
([CMD, "--branch", "--message"], 1, 1, 0, 0, 0, 0),
([CMD, "--author-name", "--author-email"], 0, 0, 2, 0, 0, 0),
([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0, 0, 0),
([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0, 0, 0),
([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base"], 1, 1, 2, 1, 1, 0),
([CMD, "--message", "--imperative"], 1, 0, 0, 0, 0, 1),
([CMD, "--dry-run"], 0, 0, 0, 0, 0, 0),
@pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_gpg_signature_call_count, check_merge_base_call_count, check_imperative_call_count", [
([CMD, "--message"], 1, 0, 0, 0, 0, 0, 0),
([CMD, "--branch"], 0, 1, 0, 0, 0, 0, 0),
([CMD, "--author-name"], 0, 0, 1, 0, 0, 0, 0),
([CMD, "--author-email"], 0, 0, 1, 0, 0, 0, 0),
([CMD, "--commit-signoff"], 0, 0, 0, 1, 0, 0, 0),
([CMD, "--gpg-signature"], 0, 0, 0, 0, 1, 0, 0),
([CMD, "--merge-base"], 0, 0, 0, 0, 0, 1, 0),
([CMD, "--imperative"], 0, 0, 0, 0, 0, 0, 1),
([CMD, "--message", "--author-email"], 1, 0, 1, 0, 0, 0, 0),
([CMD, "--branch", "--message"], 1, 1, 0, 0, 0, 0, 0),
([CMD, "--author-name", "--author-email"], 0, 0, 2, 0, 0, 0, 0),
([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0, 0, 0, 0),
([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0, 0, 0, 0),
([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base"], 1, 1, 2, 1, 0, 1, 0),
([CMD, "--message", "--gpg-signature"], 1, 0, 0, 0, 1, 0, 0),
([CMD, "--commit-signoff", "--gpg-signature"], 0, 0, 0, 1, 1, 0, 0),
([CMD, "--message", "--imperative"], 1, 0, 0, 0, 0, 0, 1),
([CMD, "--dry-run"], 0, 0, 0, 0, 0, 0, 0),
])
def test_main(
self,
Expand All @@ -33,6 +36,7 @@ def test_main(
check_branch_call_count,
check_author_call_count,
check_commit_signoff_call_count,
check_gpg_signature_call_count,
check_merge_base_call_count,
check_imperative_call_count,
):
Expand All @@ -48,6 +52,7 @@ def test_main(
m_check_branch = mocker.patch("commit_check.branch.check_branch")
m_check_author = mocker.patch("commit_check.author.check_author")
m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff")
m_check_gpg_signature = mocker.patch("commit_check.commit.check_commit_gpg_signature")
m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base")
m_check_imperative = mocker.patch("commit_check.commit.check_imperative")
sys.argv = argv
Expand All @@ -56,6 +61,7 @@ def test_main(
assert m_check_branch.call_count == check_branch_call_count
assert m_check_author.call_count == check_author_call_count
assert m_check_commit_signoff.call_count == check_commit_signoff_call_count
assert m_check_gpg_signature.call_count == check_gpg_signature_call_count
assert m_check_merge_base.call_count == check_merge_base_call_count
assert m_check_imperative.call_count == check_imperative_call_count

Expand All @@ -73,6 +79,7 @@ def test_main_help(self, mocker, capfd):
m_check_branch = mocker.patch("commit_check.branch.check_branch")
m_check_author = mocker.patch("commit_check.author.check_author")
m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff")
m_check_gpg_signature = mocker.patch("commit_check.commit.check_commit_gpg_signature")
m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base")
sys.argv = ["commit-check", "--h"]
with pytest.raises(SystemExit):
Expand All @@ -81,6 +88,7 @@ def test_main_help(self, mocker, capfd):
assert m_check_branch.call_count == 0
assert m_check_author.call_count == 0
assert m_check_commit_signoff.call_count == 0
assert m_check_gpg_signature.call_count == 0
assert m_check_merge_base.call_count == 0
stdout, _ = capfd.readouterr()
assert "usage: " in stdout
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy