Skip to content

Commit

Permalink
gitlab: add a CI job to validate the DCO sign off
Browse files Browse the repository at this point in the history
While checkpatch.pl can validate DCO sign off that job must always be
advisory only since it is expected that certain patches will fail some
code style rules.

We require the DCO sign off to be mandatory for all commits though, so
it benefits from being validated in a standalone job.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20200918132903.1848939-3-berrange@redhat.com>
[thuth: Use "stage: build" to let it run earlier]
Signed-off-by: Thomas Huth <thuth@redhat.com>
  • Loading branch information
berrange authored and huth committed Oct 13, 2020
1 parent 1f47547 commit 34ed46a
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
94 changes: 94 additions & 0 deletions .gitlab-ci.d/check-dco.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env python3
#
# check-dco.py: validate all commits are signed off
#
# Copyright (C) 2020 Red Hat, Inc.
#
# SPDX-License-Identifier: GPL-2.0-or-later

import os
import os.path
import sys
import subprocess

namespace = "qemu-project"
if len(sys.argv) >= 2:
namespace = sys.argv[1]

cwd = os.getcwd()
reponame = os.path.basename(cwd)
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)

subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
subprocess.check_call(["git", "fetch", "check-dco", "master"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)

ancestor = subprocess.check_output(["git", "merge-base",
"check-dco/master", "HEAD"],
universal_newlines=True)

ancestor = ancestor.strip()

subprocess.check_call(["git", "remote", "rm", "check-dco"])

errors = False

print("\nChecking for 'Signed-off-by: NAME <EMAIL>' " +
"on all commits since %s...\n" % ancestor)

log = subprocess.check_output(["git", "log", "--format=%H %s",
ancestor + "..."],
universal_newlines=True)

if log == "":
commits = []
else:
commits = [[c[0:40], c[41:]] for c in log.strip().split("\n")]

for sha, subject in commits:

msg = subprocess.check_output(["git", "show", "-s", sha],
universal_newlines=True)
lines = msg.strip().split("\n")

print("🔍 %s %s" % (sha, subject))
sob = False
for line in lines:
if "Signed-off-by:" in line:
sob = True
if "localhost" in line:
print(" ❌ FAIL: bad email in %s" % line)
errors = True

if not sob:
print(" ❌ FAIL missing Signed-off-by tag")
errors = True

if errors:
print("""
❌ ERROR: One or more commits are missing a valid Signed-off-By tag.
This project requires all contributors to assert that their contributions
are provided in compliance with the terms of the Developer's Certificate
of Origin 1.1 (DCO):
https://developercertificate.org/
To indicate acceptance of the DCO every commit must have a tag
Signed-off-by: REAL NAME <EMAIL>
This can be achieved by passing the "-s" flag to the "git commit" command.
To bulk update all commits on current branch "git rebase" can be used:
git rebase -i master -x 'git commit --amend --no-edit -s'
""")

sys.exit(1)

sys.exit(0)
10 changes: 10 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,13 @@ check-patch:
variables:
GIT_DEPTH: 1000
allow_failure: true

check-dco:
stage: build
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
script: .gitlab-ci.d/check-dco.py
except:
variables:
- $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
variables:
GIT_DEPTH: 1000

0 comments on commit 34ed46a

Please sign in to comment.