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

Conversation

shenxianpeng
Copy link
Contributor

@shenxianpeng shenxianpeng commented Jul 27, 2025

closes #217

Summary by CodeRabbit

  • New Features

    • Added support for verifying GPG signatures on commits, including a new command-line flag to enable this check.
    • Users will now receive clear error messages and suggestions if a commit lacks a valid GPG signature.
  • Tests

    • Introduced comprehensive tests to ensure correct behavior of the GPG signature verification feature and its integration with command-line options.

@shenxianpeng shenxianpeng added the enhancement New feature or request label Jul 27, 2025
Copy link
Contributor

coderabbitai bot commented Jul 27, 2025

Walkthrough

A new GPG signature verification feature was introduced to the commit check system. This includes adding the check to the default configuration, implementing the signature validation logic, updating the CLI to support a new flag, and expanding the test suite to cover the new check and its integration with the main entry point.

Changes

File(s) Change Summary
commit_check/init.py Added 'gpg_signature' entry to the default commit checks configuration.
commit_check/commit.py Implemented check_commit_gpg_signature function to verify latest commit's GPG signature.
commit_check/main.py Added -g/--gpg-signature CLI flag; invokes GPG signature check if set.
tests/commit_test.py Added comprehensive tests for check_commit_gpg_signature, including various GPG status cases.
tests/main_test.py Updated main function tests to cover the new GPG signature check and its CLI integration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant CommitCheck
    participant Git

    User->>CLI: Runs commit-check with --gpg-signature
    CLI->>CommitCheck: Parse args, detect --gpg-signature
    CommitCheck->>CommitCheck: check_commit_gpg_signature()
    CommitCheck->>Git: git log --pretty=format:%G? -1
    Git-->>CommitCheck: Return GPG status code
    CommitCheck->>CLI: Report PASS/FAIL based on status
    CLI->>User: Output result and suggestions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Poem

🐇
With keys and signatures, we hop ahead,
Ensuring commits are safely wed.
GPG checks now join the crew,
Guarding history, fresh and new.
So sign your work, don’t leave it bare—
The rabbit’s watching, everywhere!
🥕🔏

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/support-gpg

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@shenxianpeng shenxianpeng marked this pull request as ready for review July 27, 2025 09:43
@shenxianpeng shenxianpeng requested a review from a team as a code owner July 27, 2025 09:43
Copy link

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
commit_check/commit.py (1)

95-155: LGTM! Solid GPG signature verification implementation.

The function correctly handles various GPG signature states with appropriate error messages. The security posture of only accepting 'G' and 'U' status codes is reasonable.

However, consider improving exception handling to avoid potential secondary failures:

         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
+            try:
+                commit_hash = get_commit_info("H")
+            except Exception:
+                commit_hash = "unknown"
             print_error_message(
                 check['check'], 'Unknown',
-                'Unable to check GPG signature status', get_commit_info("H"),
+                'Unable to check GPG signature status', commit_hash,
             )
tests/commit_test.py (1)

560-565: Add missing has_commits mock for completeness.

Even though this test has empty checks, it should mock has_commits() for consistency.

     checks = []
+    mocker.patch("commit_check.commit.has_commits", return_value=True)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2491296 and bdf3e06.

📒 Files selected for processing (5)
  • commit_check/__init__.py (1 hunks)
  • commit_check/commit.py (1 hunks)
  • commit_check/main.py (2 hunks)
  • tests/commit_test.py (2 hunks)
  • tests/main_test.py (6 hunks)
🧰 Additional context used
🪛 GitHub Actions: main
tests/commit_test.py

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


[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.


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

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run benchmarks
🔇 Additional comments (6)
commit_check/main.py (2)

79-85: LGTM! Clean CLI argument addition.

The new --gpg-signature argument follows the established pattern and is properly configured.


139-140: LGTM! Proper integration in main execution flow.

The GPG signature check is correctly integrated following the same pattern as other checks.

commit_check/__init__.py (1)

51-56: LGTM! Well-structured configuration addition.

The GPG signature check configuration follows the established pattern with appropriate error message and helpful suggestion. The empty regex is correct since this check doesn't use pattern matching.

tests/main_test.py (2)

11-29: LGTM! Comprehensive test parameter updates.

The parametrized test cases properly include the new GPG signature check with appropriate call count expectations for various CLI flag combinations.


39-39: LGTM! Proper test mocking integration.

The test methods correctly mock check_commit_gpg_signature and verify call counts, maintaining consistency with existing test patterns.

Also applies to: 55-55, 64-64, 82-82, 91-91

tests/commit_test.py (1)

3-3: LGTM! Proper import addition.

The import correctly includes the new check_commit_gpg_signature function.

Comment on lines +405 to +418
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
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.

Comment on lines +422 to +435
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
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.

Comment on lines +439 to +457
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

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.

Comment on lines +523 to +541
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

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").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GPG Key Signing Verification Not Implemented in Commit-Check
1 participant
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