Skip to content
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

(Added) Enhance commit linting process and configuration #9

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

MarjovanLier
Copy link
Owner

@MarjovanLier MarjovanLier commented Apr 2, 2024

User description

Summary

This merge request introduces improvements to the project's commit linting process and configuration. It adds a new last_commit script in the bin directory to streamline the linting process and makes adjustments to the commitlint configuration file (.commitlintrc.json) to enforce a consistent commit structure and promote cleaner, more informative commit messages.

Context and Background

Commit linting is an essential practice to maintain a consistent and meaningful commit history. By enforcing a standardized commit message format, it becomes easier to understand the purpose and scope of each commit. The existing commitlint configuration required enhancements to focus on the most important aspects of commit style and ensure a consistent structure across all commits.

Related resources:

Problem Description

The current commit linting process lacked a dedicated script to streamline the execution of commitlint with the appropriate configuration file. Additionally, the commitlint configuration included unused rules and needed improvements to enforce a consistent commit structure and promote cleaner, more informative commit messages.

Solution Description

The introduced changes address the identified issues in the following ways:

  1. A new last_commit script is added to the bin directory. This script determines the full path to its location and constructs the appropriate commitlint command using the project's configuration file. It enhances robustness by exiting immediately if any invoked command fails or if any required variable is unset.

  2. The commitlint configuration file (.commitlintrc.json) is updated to remove unused rules and focus on the essential aspects of commit style. New rules are introduced to enforce a consistent commit structure, such as minimum and maximum lengths for the header, subject, and body.

  3. The severity level of the "scope-empty" rule is changed from an error (2) to a warning (1). This adjustment allows commits with empty scopes to proceed but displays a warning message to encourage the inclusion of a scope when appropriate.

  4. The rules in the configuration file are reordered to improve organization and readability.

List of Changes

  • feat: Add last_commit script to streamline commit linting process
  • refactor: Remove unused rules from commitlint configuration
  • feat: Introduce new rules to enforce consistent commit structure
  • refactor: Adjust severity of "scope-empty" rule from error to warning
  • style: Reorder commitlint rules for better organization and readability

Type

enhancement, documentation


Description

  • Renamed commit_message_validator to first_commit_message_validator and introduced second_commit_message_validator for enhanced commit message validation.
  • Added support for 'Signed-off-by' in commit footers.
  • Added a new commitlint configuration with rules for commit message validation.
  • Updated test cases and examples to reflect changes.
  • Added @commitlint/cli and @commitlint/config-conventional as dev dependencies.

Changes walkthrough

Relevant files
Enhancement
main.py
Enhance commit message validation and support 'Signed-off-by'

main.py

  • Renamed commit_message_validator to first_commit_message_validator.
  • Added support for 'Signed-off-by' in commit footers.
  • Introduced second_commit_message_validator for additional commit
    message validation.
  • Updated examples to correct markdown syntax.
  • +39/-14 
    Tests
    test_validator.py
    Update test cases for commit message validator renaming   

    test_validator.py

  • Updated test cases to reflect the renaming of commit_message_validator
    to first_commit_message_validator.
  • +26/-26 
    Configuration changes
    .commitlintrc.json
    Add commitlint configuration for commit message validation

    .commitlintrc.json

  • Introduced a new commitlint configuration with rules for commit
    message validation.
  • +99/-0   
    Dependencies
    package-lock.json
    Add commitlint dependencies                                                           

    package-lock.json

  • Added dependencies for @commitlint/cli and
    @commitlint/config-conventional.
  • +1449/-0
    package.json
    Add commitlint dev dependencies                                                   

    package.json

  • Added @commitlint/cli and @commitlint/config-conventional as dev
    dependencies.
  • +6/-0     

    PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    Summary by CodeRabbit

    • New Features
      • Introduced commit message linting to enforce consistent and informative commit messages.
      • Added new validation functions for commit messages, including support for additional footer tokens.
    • Refactor
      • Updated the commit message validator function across the application and tests for enhanced semantic clarity.
    • Chores
      • Updated .gitignore to exclude /node_modules/.
      • Added development dependencies for commit linting.

    - Expand valid footer tokens to include 'Signed-off-by'
    - Properly recognize and handle 'Signed-off-by' statements
    - Enhance compliance with version control best practices
    
    This change allows the system to correctly process 'Signed-off-by'
    lines in commit message footers, improving adherence to industry
    standards for version control and collaboration workflows.
    
    Signed-off-by: Marjo van Lier <[email protected]>
    The indentation of the example commit message syntax in the main.py
    file was incorrect. This commit removes the leading spaces so the
    markdown syntax is recognised correctly, accurately conveying the
    example formatting of commit messages.
    
    Signed-off-by: Marjo van Lier <[email protected]>
    - Rename `commit_message_validator` to `first_commit_message_validator`
    - Introduce `second_commit_message_validator` using commitlint CLI
    - Update related test cases to reflect the changes
    - Change `manager_llm` language model to "gpt-4-turbo-preview"
    
    This commit refactors the commit message validation process to
    improve clarity and maintainability. The validation is split into
    two distinct steps, allowing for more flexibility and the ability
    to apply different validation approaches as needed. The related
    test cases are updated to account for these changes. Additionally,
    the `manager_llm` language model is updated to "gpt-4-turbo-preview".
    
    Signed-off-by: Marjo van Lier <[email protected]>
    - Ignore node_modules directory to keep repository clean
    - Incorporate .commitlintrc.json to enforce commit style guidelines
    - Add commitlint and config-conventional as dev dependencies
    
    Signed-off-by: Marjo van Lier <[email protected]>
    - Introduce minimum length rules for commit subject and header
    - Require subject and header to have at least 10 characters
    - Improve commit message quality and consistency
    
    The commitlint configuration has been updated to enforce minimum length
    requirements for the commit message subject line and header.
    This change ensures that commit messages provide sufficient detail
    and context, enhancing the overall quality of the commit history.
    
    Signed-off-by: Marjo van Lier <[email protected]>
    The .commitlintrc.json file has been amended to present the commitlint
    rules in an alphabetical order. This adjustment improves readability
    and simplifies the management of the rules configuration.
    
    Signed-off-by: Marjo van Lier <[email protected]>
    Copy link

    coderabbitai bot commented Apr 2, 2024

    Walkthrough

    This update introduces a refined commit message validation system, enhancing codebase consistency and readability. By integrating commit message linting configurations and updating validation functions, it ensures commit messages adhere to the conventional commit format. The addition of development dependencies supports this new linting process, while test adjustments align with the updated validation logic, maintaining the integrity of automated checks.

    Changes

    Files Change Summary
    .commitlintrc.json Introduced configuration for commit message linting using the conventional commit format.
    .gitignore Added /node_modules/ to ignore list.
    main.py Updated with new commit message validator functions and added new footer tokens for validation.
    package.json, test_validator.py Added dev dependencies for linting in package.json; Updated function names in test_validator.py.

    "In the code's garden, changes bloom, 🌸
    Linting rules clear the gloom. 🌞
    With each commit, we refine,
    Ensuring our messages align.
    A rabbit hops through, leaving behind
    Cleaner code for all to find. 🐇💻"


    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>.
      • Generate unit testing code for this file.
      • 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 generate unit testing code for this file.
      • @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 generate interesting stats about this repository and render them as a table.
      • @coderabbitai show all the console.log statements in this repository.
      • @coderabbitai read src/utils.ts and generate unit testing code.
      • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

    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 as PR comments)

    • @coderabbitai pause to pause the reviews on a PR.
    • @coderabbitai resume to resume the paused reviews.
    • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
    • @coderabbitai resolve resolve all the CodeRabbit review comments.
    • @coderabbitai help to get help.

    Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

    CodeRabbit Configration 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/coderabbit-overrides.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.

    @qodo-merge-pro qodo-merge-pro bot added documentation Improvements or additions to documentation enhancement New feature or request labels Apr 2, 2024
    Copy link

    qodo-merge-pro bot commented Apr 2, 2024

    PR Description updated to latest commit (7221ee2)

    Copy link

    qodo-merge-pro bot commented Apr 2, 2024

    PR Review

    ⏱️ Estimated effort to review [1-5]

    2, because the PR involves changes to multiple files including Python scripts, configuration files, and test cases. The changes are well-scoped and seem to follow a clear purpose of enhancing the commit linting process. The addition of new functionality and the update of dependencies in package.json are straightforward. However, understanding the impact and ensuring compatibility requires a review of the logic changes in the Python scripts and the new linting rules.

    🧪 Relevant tests

    Yes

    🔍 Possible issues

    Possible Bug: The addition of second_commit_message_validator in main.py introduces a new method for validating commit messages. It's crucial to ensure this does not conflict with existing validation logic or introduce unexpected behavior.

    Performance Concern: The new script second_commit_message_validator uses subprocess to execute a shell command. This could introduce performance overhead or potential security concerns with command injection if not properly sanitized.

    🔒 Security concerns

    Command Injection: The second_commit_message_validator function constructs a shell command using string concatenation with user input (suggested_commit_msg). This could lead to command injection if the input is not properly sanitized. Consider using safer alternatives to execute subprocesses or ensure rigorous input validation.


    ✨ Review tool usage guide:

    Overview:
    The review tool scans the PR code changes, and generates a PR review which includes several types of feedbacks, such as possible PR issues, security threats and relevant test in the PR. More feedbacks can be added by configuring the tool.

    The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on any PR.

    • When commenting, to edit configurations related to the review tool (pr_reviewer section), use the following template:
    /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=...
    
    [pr_reviewer]
    some_config1=...
    some_config2=...
    

    See the review usage page for a comprehensive guide on using this tool.

    Copy link

    qodo-merge-pro bot commented Apr 2, 2024

    PR Code Suggestions

    CategorySuggestions                                                                                                                                                       
    Enhancement
    Use assertEqual for clearer test failure messages.

    Consider using assertEqual instead of assertTrue for checking boolean values to get more
    informative error messages in case of test failures.

    test_validator.py [12]

    -self.assertTrue(result['is_valid'])
    +self.assertEqual(result['is_valid'], True)
     
    Add specific test messages for clarity on test failure.

    For tests that expect failure, consider adding a specific test message to assertFalse to
    provide context on failure.

    test_validator.py [196]

    -self.assertFalse(result['is_valid'])
    +self.assertFalse(result['is_valid'], "Expected invalid commit message to be rejected")
     
    Rename validator functions for better clarity.

    To avoid potential confusion and improve code clarity, consider renaming the
    first_commit_message_validator and second_commit_message_validator functions to more
    descriptive names that reflect their specific validation strategies or scopes.

    main.py [42-43]

    -@tool("First Conventional Commit Message Validator")
    -def first_commit_message_validator(suggested_commit_msg: str) -> dict[str, list[str] | bool]:
    -@tool("Second Conventional Commit Message Validator")
    -def second_commit_message_validator(suggested_commit_msg: str) -> str:
    +@tool("Basic Conventional Commit Message Validator")
    +def basic_commit_message_validator(suggested_commit_msg: str) -> dict[str, list[str] | bool]:
    +@tool("Advanced Conventional Commit Message Validator")
    +def advanced_commit_message_validator(suggested_commit_msg: str) -> str:
     
    Readability
    Improve readability by using assertFalse.

    Use assertFalse directly instead of assertTrue with a negation for better readability.

    test_validator.py [54]

    -self.assertTrue(not result['is_valid'])
    +self.assertFalse(result['is_valid'])
     
    Best practice
    Use unittest's assertion methods for consistency.

    Replace assert with self.assertEqual to use unittest's built-in assertion methods for
    consistency and better test reports.

    test_validator.py [168]

    -assert result["is_valid"] == True
    +self.assertEqual(result["is_valid"], True)
     
    Use assertIn/assertNotIn for more informative tests.

    Use assertIn and assertNotIn for checking if a value is in a list for more specific and
    informative test failures.

    test_validator.py [13]

    -self.assertEqual(len(result['errors']), 0)
    +self.assertNotIn("Your specific error", result['errors'])
     
    Use a context manager for subprocess calls for resource management.

    To ensure the code is more Pythonic and concise, consider using a context manager (with
    statement) for subprocess calls that involve piping or redirection. This approach can help
    manage subprocess resources more efficiently and improve code readability.

    main.py [189]

    -return_data = subprocess.getoutput(command)
    +import subprocess
    +with subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as proc:
    +    return_data, _ = proc.communicate()
     
    Security
    Use shlex.quote for safer command argument escaping.

    Instead of manually escaping characters in the suggested_commit_msg, consider using the
    shlex.quote function from the shlex module for safer and more reliable command argument
    escaping. This approach prevents potential command injection vulnerabilities and handles
    more edge cases.

    main.py [178-179]

    -suggested_commit_msg = suggested_commit_msg.replace('`', '\`').strip()
    -suggested_commit_msg = suggested_commit_msg.replace('"', '\"').strip()
    +import shlex
    +suggested_commit_msg = shlex.quote(suggested_commit_msg.strip())
     
    Maintainability
    Use a multi-line string for constructing shell commands.

    To improve the maintainability and readability of the code, consider using a multi-line
    string for constructing the command variable. This approach avoids the need for
    concatenation and makes the command more readable.

    main.py [184]

    -command = 'echo "' + suggested_commit_msg + '" | ' + root_dir + '/node_modules/@commitlint/cli/cli.js -V -g ' + root_dir + '/.commitlintrc.json'
    +command = f'''echo "{suggested_commit_msg}" | {root_dir}/node_modules/@commitlint/cli/cli.js -V -g {root_dir}/.commitlintrc.json'''
     
    Use a list for allowed footer tokens for easier maintenance.

    To enhance the code's readability and maintainability, consider using a list to define the
    allowed footer tokens and then converting it to a string when constructing the error
    message. This approach simplifies adding or removing tokens in the future.

    main.py [140-142]

    -if footer_parts[0] not in ["Reviewed-by", "Refs", "Closes", "Signed-off-by"]:
    +allowed_tokens = ["Reviewed-by", "Refs", "Closes", "Signed-off-by"]
    +if footer_parts[0] not in allowed_tokens:
         errors.append(
    -        f"Invalid footer format: {line}. Footer token should be uppercase, not contain spaces, and be one of the allowed tokens: 'BREAKING CHANGE', 'Reviewed-by', 'Refs', 'Closes', or 'Signed-off-by'."
    +        f"Invalid footer format: {line}. Footer token should be uppercase, not contain spaces, and be one of the allowed tokens: {' '.join(allowed_tokens)}."
         )
     

    ✨ Improve tool usage guide:

    Overview:
    The improve tool scans the PR code changes, and automatically generates suggestions for improving the PR code. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.

    • When commenting, to edit configurations related to the improve tool (pr_code_suggestions section), use the following template:
    /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=...
    
    [pr_code_suggestions]
    some_config1=...
    some_config2=...
    

    See the improve usage page for a comprehensive guide on using this tool.

    Copy link

    @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: 1

    Review Status

    Configuration used: CodeRabbit UI

    Commits Files that changed from the base of the PR and between 46b32c9 and 7221ee2.
    Files ignored due to path filters (1)
    • package-lock.json is excluded by !**/package-lock.json
    Files selected for processing (5)
    • .commitlintrc.json (1 hunks)
    • .gitignore (1 hunks)
    • main.py (11 hunks)
    • package.json (1 hunks)
    • test_validator.py (7 hunks)
    Files skipped from review due to trivial changes (2)
    • .commitlintrc.json
    • .gitignore
    Additional comments not posted (4)
    package.json (1)

    2-5: The addition of @commitlint/cli and @commitlint/config-conventional as development dependencies with version ranges specified using carets is a good practice. This approach allows for automatic updates to newer minor versions, which can include important fixes and improvements.

    test_validator.py (1)

    137-234: > 📝 NOTE

    This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [4-231]

    The update from commit_message_validator to first_commit_message_validator across all test cases is consistent and correctly implemented. Ensure that the first_commit_message_validator function in main.py is implemented as expected to match these test scenarios.

    main.py (2)

    137-147: > 📝 NOTE

    This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [42-144]

    The implementation of first_commit_message_validator is comprehensive and aligns well with the Conventional Commits specification. It's a good practice to return a dictionary with errors, suggestions, and a validity status. However, consider refining the handling of footer tokens to ensure extensibility. For instance, you might want to use a list or a set for allowed footer tokens to make it easier to add new ones in the future.


    347-353: > 📝 NOTE

    This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [321-429]

    The updates to the main function and the introduction of agents and tasks for commit message analysis and suggestion are innovative and demonstrate an effort to automate the commit message validation process. However, consider the maintainability of this complex setup. Simplifying the workflow or providing detailed documentation on how each component interacts could help future developers understand and maintain the system more effectively.

    Comment on lines +173 to +195
    @tool("Second Conventional Commit Message Validator")
    def second_commit_message_validator(suggested_commit_msg: str) -> str:
    """
    Use this tool to validate that a suggested commit message follows the Conventional Commits 1.0.0 specification.
    """
    suggested_commit_msg = suggested_commit_msg.replace('`', '\`').strip()
    suggested_commit_msg = suggested_commit_msg.replace('"', '\"').strip()

    # Get the path of where main.py is located
    root_dir = os.path.dirname(os.path.abspath(__file__))

    command = 'echo "' + suggested_commit_msg + '" | ' + root_dir + '/node_modules/@commitlint/cli/cli.js -V -g ' + root_dir + '/.commitlintrc.json'

    print(f"Command: {command}")

    # Run the command to validate the commit message
    return_data = subprocess.getoutput(command)

    return_data = return_data.strip()

    print(f"Return data: {return_data}")

    return return_data
    Copy link

    Choose a reason for hiding this comment

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

    The second_commit_message_validator function provides a practical approach to validating commit messages using the commitlint CLI. However, consider improving the security of command construction to prevent potential command injection vulnerabilities. Instead of direct string concatenation, use safer methods such as lists for command arguments with subprocess functions that support them.

    - command = 'echo "' + suggested_commit_msg + '" | ' + root_dir + '/node_modules/@commitlint/cli/cli.js -V -g ' + root_dir + '/.commitlintrc.json'
    + command = ['bash', '-c', f'echo "{suggested_commit_msg}" | {root_dir}/node_modules/@commitlint/cli/cli.js -V -g {root_dir}/.commitlintrc.json']

    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.

    Suggested change
    @tool("Second Conventional Commit Message Validator")
    def second_commit_message_validator(suggested_commit_msg: str) -> str:
    """
    Use this tool to validate that a suggested commit message follows the Conventional Commits 1.0.0 specification.
    """
    suggested_commit_msg = suggested_commit_msg.replace('`', '\`').strip()
    suggested_commit_msg = suggested_commit_msg.replace('"', '\"').strip()
    # Get the path of where main.py is located
    root_dir = os.path.dirname(os.path.abspath(__file__))
    command = 'echo "' + suggested_commit_msg + '" | ' + root_dir + '/node_modules/@commitlint/cli/cli.js -V -g ' + root_dir + '/.commitlintrc.json'
    print(f"Command: {command}")
    # Run the command to validate the commit message
    return_data = subprocess.getoutput(command)
    return_data = return_data.strip()
    print(f"Return data: {return_data}")
    return return_data
    @tool("Second Conventional Commit Message Validator")
    def second_commit_message_validator(suggested_commit_msg: str) -> str:
    """
    Use this tool to validate that a suggested commit message follows the Conventional Commits 1.0.0 specification.
    """
    suggested_commit_msg = suggested_commit_msg.replace('`', '\`').strip()
    suggested_commit_msg = suggested_commit_msg.replace('"', '\"').strip()
    # Get the path of where main.py is located
    root_dir = os.path.dirname(os.path.abspath(__file__))
    command = ['bash', '-c', f'echo "{suggested_commit_msg}" | {root_dir}/node_modules/@commitlint/cli/cli.js -V -g {root_dir}/.commitlintrc.json']
    print(f"Command: {command}")
    # Run the command to validate the commit message
    return_data = subprocess.getoutput(command)
    return_data = return_data.strip()
    print(f"Return data: {return_data}")
    return return_data

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    documentation Improvements or additions to documentation enhancement New feature or request Review effort [1-5]: 2
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant