Skip to content

Add commit-msg git hook and update readme. #154

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
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# rust-vmm-ci

The `rust-vmm-ci` repository contains [integration tests](#integration-tests)
and [Buildkite pipeline](#buildkite-pipeline) definitions that are used for
running the CI for all rust-vmm crates.
running the CI for all rust-vmm crates, as well as [git hooks](#git-hooks)
to ensure quality and consistency with the rust-vmm commit message standards.

CI tests are executed on the container image maintained at [rust-vmm/rust-vmm-container repo](https://github.com/rust-vmm/rust-vmm-container) with builds available on [Docker Hub](https://hub.docker.com/r/rustvmm/dev/tags).

Expand All @@ -15,6 +15,7 @@ To run the integration tests defined in the pipeline as part of the CI:

1. Add rust-vmm-ci as a git submodule to your repository

Adding rust-vmm-ci to new repos:
```bash
# Add rust-vmm-ci as a submodule. This will point to the latest rust-vmm-ci
# commit from the main branch. The following command will also add a
Expand All @@ -25,6 +26,12 @@ git submodule add https://github.com/rust-vmm/rust-vmm-ci.git
git commit -s -m "Added rust-vmm-ci as submodule"
```

Initializing rust-vmm-ci in cloned rust-vmm repos with existing
uninitialized rust-vmm-ci submodule:
```bash
git submodule update --init
```

2. Create the coverage test configuration file named
`coverage_config_ARCH.json` in the root of the repository, where `ARCH` is the
architecture of the machine.
Expand Down Expand Up @@ -122,6 +129,33 @@ triggering the CI on
and [push](https://developer.github.com/v3/activity/events/types/#pushevent)
events.

## Git Hooks
To ensure consistency and quality across commit messages in your repository, rust-vmm-ci
includes git hooks located at `rust-vmm-ci/git-hooks/`. Hooks are programs
that trigger actions at certain points in git's execution.

### Commit-Msg
This hook is designed to automatically check your commit messages against with the
rust-vmm commit message standards.

To utilize this hook for checking commit messages in your local repository, follow
these steps:

1. Copy the Hook
After adding rust-vmm-ci as a submodule, copy the commit-msg hook from the submodule's
git-hooks directory to your repository's .git/hooks directory. You can do this with
the following command from the root of your repository:

```shell
cp rust-vmm-ci/git-hooks/commit-msg .git/hooks/
```

2. Make the Hook Executable
For the hook to run, it must be executable. Change its permissions accordingly:
```shell
chmod +x .git/hooks/commit-msg
```

## Buildkite Pipeline

The [Buildkite](https://buildkite.com) pipeline is the definition of tests to
Expand Down
52 changes: 52 additions & 0 deletions githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""
Commit-msg hook to check the commit message format.
Ensures commit messages do not have exceedingly long titles (maximum 60 characters for the title)
and that commits are signed.
"""

import sys

COMMIT_TITLE_MAX_LEN = 60
COMMIT_BODY_LINE_MAX_LEN = 75

def get_commit_message(commit_msg_filepath):
"""Retrieve the commit message from the provided file path."""
with open(commit_msg_filepath, 'r') as file:
return file.read()

def main(commit_msg_filepath):
message = get_commit_message(commit_msg_filepath)
message_lines = message.split("\n")

# Check for long commit title
if not message_lines or len(message_lines[0]) > COMMIT_TITLE_MAX_LEN:
print(f"Error: Commit title is too long (maximum {COMMIT_TITLE_MAX_LEN} characters allowed). Title: '{message_lines[0]}'")
sys.exit(1)

# Ensure there is a blank line following the title
if len(message_lines) < 3 or message_lines[1] != "":
error_line = "None" if len(message_lines) < 2 else message_lines[1]
print(f"Error: The commit message should contain at least 3 lines: title, blank line, and description/sign-off. Problematic line: '{error_line}'")
sys.exit(1)

# Check for a signed-off message
found_signed_off = False
for line in message_lines[2:]:
if line.startswith("Signed-off-by: "):
found_signed_off = True
break
if len(line) > COMMIT_BODY_LINE_MAX_LEN:
print(f"Error: Line in commit body exceeds {COMMIT_BODY_LINE_MAX_LEN} characters. Line: '{line}'")
sys.exit(1)

if not found_signed_off:
print("Error: Commit is not signed. Please sign off your commit by running 'git commit -s'.")
sys.exit(1)

if __name__ == "__main__":
if len(sys.argv) < 2:
print("Error: No commit message file path provided.")
sys.exit(1)
main(sys.argv[1])