Skip to content

Commit 8e93a3e

Browse files
authored
Merge pull request #38 from ccdc-opensource/PLA-3204_conventional-commit
PLA-3204 conventional commit
2 parents 6217d92 + ec9815d commit 8e93a3e

1 file changed

Lines changed: 39 additions & 1 deletion

File tree

main/githooks.py

100755100644
Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,19 @@ def check_commit_msg(message, files, repo):
858858
if re.match(r'^ccdc-opensource/', repo):
859859
# Do not check for JIRA in opensource repo as we don't want to require external contributors to do this
860860
return 0
861-
861+
862+
863+
# Check for Conventional Commits compliance.
864+
# Opt-in per repo: commit an empty marker file named
865+
# `.conventional-commits` at the repo root.
866+
if _conventional_commits_enabled():
867+
if not conventional_commit_present(message):
868+
_fail('Commit message does not follow the Angular Conventional '
869+
'Commits standard.\n'
870+
'Expected: <type>(<scope>)?: <subject>\n'
871+
'See https://github.com/angular/angular/blob/main/contributing-docs/commit-message-guidelines.md')
872+
return 1
873+
862874
if (
863875
NO_JIRA_MARKER not in message
864876
and copilot_autofix_coauthor_pattern.search(message) is None
@@ -884,6 +896,32 @@ def check_commit_msg(message, files, repo):
884896
jira_id_pattern = re.compile(r'\b[A-Z]{2,8}-[0-9]{1,5}\b')
885897

886898

899+
900+
def _conventional_commits_enabled():
901+
'''Return True if the repo opts in to Conventional Commits enforcement.
902+
903+
Opt-in is signalled by a `.conventional-commits` file at the repo root.
904+
'''
905+
repo_root = _get_output(['git', 'rev-parse', '--show-toplevel']).strip()
906+
return (Path(repo_root) / '.conventional-commits').is_file()
907+
908+
909+
def conventional_commit_present(message):
910+
'''Return True if the commit message follows the Angular Conventional Commits standard.'''
911+
# Angular Conventional Commits header: type(scope?): subject
912+
# Allowed types from @commitlint/config-angular:
913+
# build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
914+
# Note: Angular does not use the `!` breaking-change marker in the header;
915+
pattern = re.compile(
916+
r'^(BREAKING CHANGE|feat|fix|refactor|build|chore|ci|docs|perf|revert|style|test)' # type
917+
r'(\([\w\-\.\/]+\))?' # optional scope
918+
r': ' # required ": "
919+
r'.+' # subject
920+
)
921+
first_line = message.split('\n', 1)[0]
922+
return pattern.match(first_line) is not None
923+
924+
887925
class TestJiraIDPattern(unittest.TestCase):
888926
def test_various_strings(self):
889927
def _test(input, is_jira=True):

0 commit comments

Comments
 (0)