diff options
author | Philip Withnall <withnall@endlessm.com> | 2019-04-25 11:23:26 +0100 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2020-01-21 12:26:47 +0000 |
commit | 3f51963b2d6f97aced791854be91a206d04294dd (patch) | |
tree | 1a6e91eb1ddb857fbbc7e318397c276b784809fc /.gitlab-ci | |
parent | 5d32b99d0c620b75ccb861d1ab85e4c959364bbc (diff) | |
download | glib-3f51963b2d6f97aced791854be91a206d04294dd.tar.gz |
ci: Add checks for banned keywords in merge requests
Using the same approach as we have for code style checks (the
`style-check-diff` CI job), check the diff for any banned keywords like
‘TODO’, and also check the commit messages.
The keyword ‘TODO’ is often used by developers to indicate a part of a
commit which needs further work, and hence which shouldn’t yet be merged.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1551
Diffstat (limited to '.gitlab-ci')
-rwxr-xr-x | .gitlab-ci/check-todos.py | 89 | ||||
-rwxr-xr-x | .gitlab-ci/run-check-todos.sh | 16 |
2 files changed, 105 insertions, 0 deletions
diff --git a/.gitlab-ci/check-todos.py b/.gitlab-ci/check-todos.py new file mode 100755 index 000000000..83b3eee7a --- /dev/null +++ b/.gitlab-ci/check-todos.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# +# Copyright © 2019 Endless Mobile, Inc. +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Original author: Philip Withnall + +""" +Checks that a merge request doesn’t add any instances of the string ‘todo’ +(in uppercase), or similar keywords. It may remove instances of that keyword, +or move them around, according to the logic of `git log -S`. +""" + +import argparse +import re +import subprocess +import sys + + +# We have to specify these keywords obscurely to avoid the script matching +# itself. The keyword ‘fixme’ (in upper case) is explicitly allowed because +# that’s conventionally used as a way of marking a workaround which needs to +# be merged for now, but is to be grepped for and reverted or reworked later. +BANNED_KEYWORDS = [ + 'TO' + 'DO', + 'X' + 'XX', + 'W' + 'IP', +] + + +def main(): + parser = argparse.ArgumentParser( + description='Check a range of commits to ensure they don’t contain ' + 'banned keywords.') + parser.add_argument('commits', + help='SHA to diff from, or range of commits to diff') + args = parser.parse_args() + + banned_words_seen = set() + seen_in_log = False + seen_in_diff = False + + # Check the log messages for banned words. + log_process = subprocess.run( + ['git', 'log', '--no-color', args.commits + '..HEAD'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', + check=True) + log_lines = log_process.stdout.strip().split('\n') + + for line in log_lines: + for keyword in BANNED_KEYWORDS: + if re.search('(^|\W+){}(\W+|$)'.format(keyword), line): + banned_words_seen.add(keyword) + seen_in_log = True + + # Check the diff for banned words. + diff_process = subprocess.run( + ['git', 'diff', '-U0', '--no-color', args.commits], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', + check=True) + diff_lines = diff_process.stdout.strip().split('\n') + + for line in diff_lines: + if not line.startswith('+ '): + continue + + for keyword in BANNED_KEYWORDS: + if re.search('(^|\W+){}(\W+|$)'.format(keyword), line): + banned_words_seen.add(keyword) + seen_in_diff = True + + if banned_words_seen: + if seen_in_log and seen_in_diff: + where = 'commit message and diff' + elif seen_in_log: + where = 'commit message' + elif seen_in_diff: + where = 'commit diff' + + print('Saw banned keywords in a {}: {}. ' + 'This indicates the branch is a work in progress and should not ' + 'be merged in its current ' + 'form.'.format(where, ', '.join(banned_words_seen))) + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/.gitlab-ci/run-check-todos.sh b/.gitlab-ci/run-check-todos.sh new file mode 100755 index 000000000..786fd71d6 --- /dev/null +++ b/.gitlab-ci/run-check-todos.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set +e + +# We need to add a new remote for the upstream master, since this script could +# be running in a personal fork of the repository which has out of date branches. +git remote add upstream https://gitlab.gnome.org/GNOME/glib.git +git fetch upstream + +# Work out the newest common ancestor between the detached HEAD that this CI job +# has checked out, and the upstream target branch (which will typically be +# `upstream/master` or `upstream/glib-2-62`). +# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if we’re running in +# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise. +newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}) <(git rev-list --first-parent HEAD) | head -1) +./.gitlab-ci/check-todos.py "${newest_common_ancestor_sha}" |