From 4571080a7756d6802c113d36911e831e1ae8110e Mon Sep 17 00:00:00 2001 From: DW Talton Date: Wed, 21 Aug 2019 18:59:06 -0700 Subject: [PATCH] Rework DCO with check and match commands The DCO shell script now has two commands, 'check' and 'match'. Check will scan a git repo for missing DCO signatures and output the results to the console. Match checks commits that do have DCO signatures and confirms that the signature matches the commit author's email address Issue: RELENG-1980 Signed-off-by: DW Talton Change-Id: I36f57ccdc993df9923dc2d9102b7bac4c92e2739 --- lftools/cli/dco.py | 21 ++++++- releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml | 7 +++ shell/dco | 71 ++++++++++++++++------ 3 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml mode change 100644 => 100755 shell/dco diff --git a/lftools/cli/dco.py b/lftools/cli/dco.py index 86d2d94e..7bd0cb45 100644 --- a/lftools/cli/dco.py +++ b/lftools/cli/dco.py @@ -36,8 +36,27 @@ def check(ctx, repo_path): """ if not repo_path: repo_path = "." - status = subprocess.call(['dco', repo_path]) + status = subprocess.call(['dco', 'check', repo_path]) + sys.exit(status) + + +@click.command() +@click.argument('repo-path', required=False) +@click.pass_context +def match(ctx, repo_path): + """Check repository for commits whose DCO does not match the commit author's email. + + This check will exclude merge commits and empty commits. + It operates in your current working directory which has to + be a git repository. Alternatively, you can opt to pass in the + path to a git repo. + Refer to https://developercertificate.org/ + """ + if not repo_path: + repo_path = "." + status = subprocess.call(['dco', 'match', repo_path]) sys.exit(status) dco.add_command(check) +dco.add_command(match) diff --git a/releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml b/releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml new file mode 100644 index 00000000..501ffd9d --- /dev/null +++ b/releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Expanded DCO shell script with 'check' and 'match' commands. The check + mode checks a git repo for missing DCO signatures. The match mode confirms + whether or not the DCO signature(s) match the git commit author's email + address. diff --git a/shell/dco b/shell/dco old mode 100644 new mode 100755 index df93825d..c8992cbd --- a/shell/dco +++ b/shell/dco @@ -13,22 +13,59 @@ # It operates in your current working directory which must be a git repo. # Alternatively you can pass it a path to a git repo. -REPO_PATH="$1" +function dcocheck { + REPO_PATH="$1" + cd "$REPO_PATH" || exit 1 -cd $REPO_PATH || exit 1 + status=0 + while IFS= read -r -a line; do + # shellcheck disable=SC2128 + my_array+=( "$line" ) + done < <( git branch -r | grep -v origin/HEAD ) + for branch in "${my_array[@]}" + do + status=1 + branch=$(echo "$branch" | xargs) + echo "Checking commits in branch $branch for commits missing DCO..." + git log "$branch" --no-merges --pretty="%H %ae" --grep 'Signed-off-by' --invert-grep -- | \ + while read -r results; do + commit_hash="$(echo "$results" | cut -d' ' -f1)" + >&2 echo "$commit_hash is missing Signed-off-by line." + done + done + exit $status +} -status=0 -while IFS= read -a line; do - my_array+=( "$line" ) - done < <( git branch -r | grep -v origin/HEAD ) -for branch in "${my_array[@]}" -do - status=1 - branch=$(echo "$branch" | xargs) - echo "Checking commits in branch $branch for commits missing DCO..." - git log $branch --no-merges --pretty="%H" --grep 'Signed-off-by' --invert-grep * | \ - while read commit_hash; do - echo "ERROR: Commit $commit_hash is missing Signed-off-by line." - done -done -exit $status +function dcomatch { + REPO_PATH="$1" + cd "$REPO_PATH" || exit 1 + + status=0 + while IFS= read -r -a line; do + # shellcheck disable=SC2128 + my_array+=( "$line" ) + done < <( git branch -r | grep -v origin/HEAD ) + for branch in "${my_array[@]}" + do + status=1 + branch=$(echo "$branch" | xargs) + git log "$branch" --no-merges --pretty="%H %ae" --grep 'Signed-off-by' -- | \ + while read -r results; do + commit_hash="$(echo "$results" | cut -d' ' -f1)" + author_email="$(echo "$results" | cut -d' ' -f2)" + sob="$(git show --quiet "$commit_hash" | grep -oP '(?=Signed\-off\-by: )[\s\S]*[\<](.*)[\>]')" + if [[ "$sob" != *"$author_email"* ]] ; then + >&2 echo "$commit_hash author is $author_email and DCO is $sob" + if [ "$sob" = "" ] ; then + >&2 echo "NOTE: If DCO is empty, then the commit is likely signed with a name but no email address" + fi + fi + done + done + exit $status +} + +case "$1" in + match) dcomatch "$2" ;; + check) dcocheck "$2" ;; +esac -- 2.16.6