Rework DCO with check and match commands 42/16642/9
authorDW Talton <dtalton@contractor.linuxfoundation.org>
Thu, 22 Aug 2019 01:59:06 +0000 (18:59 -0700)
committerDW Talton <dtalton@contractor.linuxfoundation.org>
Thu, 29 Aug 2019 22:50:59 +0000 (15:50 -0700)
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 <dtalton@contractor.linuxfoundation.org>
Change-Id: I36f57ccdc993df9923dc2d9102b7bac4c92e2739

lftools/cli/dco.py
releasenotes/notes/dco-check-2ef51234a4ee7d80.yaml [new file with mode: 0644]
shell/dco [changed mode: 0644->0755]

index 86d2d94..7bd0cb4 100644 (file)
@@ -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 (file)
index 0000000..501ffd9
--- /dev/null
@@ -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.
old mode 100644 (file)
new mode 100755 (executable)
index df93825..c8992cb
--- a/shell/dco
+++ b/shell/dco
 # 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