Skip to content

Instantly share code, notes, and snippets.

@codeinthehole
Created October 11, 2019 15:52
Show Gist options
  • Save codeinthehole/10e79178066c656425c6eb8a2b229cc5 to your computer and use it in GitHub Desktop.
Save codeinthehole/10e79178066c656425c6eb8a2b229cc5 to your computer and use it in GitHub Desktop.
Sample test module for validating the commits messages on a PR branch
import re
import subprocess
import pytest
@pytest.mark.parametrize(
"subject, error_msg",
[
("WIP: working on something", "is a WIP commit"),
("WIP", "is a WIP commit"),
("fixup! some other commit", "is a fix-up commit"),
("Do the thing.", "ends with a period"),
("do the thing", "isn't capitalised"),
(
"Do the things and include information that should really be in the commit body",
"is too long",
),
],
)
def test_commit_subject_validity(subject, error_msg):
is_valid, _ = _is_commit_subject_valid(subject)
assert is_valid is False, f"'{subject}' {error_msg}"
def _is_commit_subject_valid(subject):
"""
Test if a commit subject is valid.
See https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
"""
if re.match(r"^wip([ :]|$)", subject.lower()):
return False, "WIP commits should be rebased"
if re.match(r"^fixup!", subject.lower()):
return False, "Fix-up commits should be rebased"
if re.search(r"\.$", subject):
return False, "Commit subject should not end with a period"
if re.search(r"^[a-z]", subject):
return False, "Commit subject should be capitalised"
max_length = 70
if len(subject) > max_length:
return False, f"Commit subject should not be longer than {max_length} characters"
return True, ""
def _pr_commits():
"""
Return a generator of commmit message SHAs and subjects for the commits in
this branch.
"""
# Need to run git fetch to ensure CircleCI's checkout of origin/master is up-to-date.
cmd = "git fetch"
subprocess.run(cmd.split(), capture_output=True)
# Grab the oneline summary of the new commits on this PR branch
cmd = "git log origin/master.. --oneline"
result = subprocess.run(cmd.split(), capture_output=True)
output = result.stdout.decode("utf-8")
for line in output.split("\n"):
parts = line.split(" ")
yield parts[0], " ".join(parts[1:])
@pytest.mark.parametrize("sha,commit_subject", _pr_commits())
def test_branch_commit_subject(sha, commit_subject):
is_valid, message = _is_commit_subject_valid(commit_subject)
if not is_valid:
pytest.fail(f"Commit {sha} '{commit_subject}' is invalid: {message}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment