xref: /openbmc/qemu/.gitlab-ci.d/check-dco.py (revision b8ee011e40e4b83a32ea0e7dca24e1ab089f1e7f)
134ed46a2SDaniel P. Berrangé#!/usr/bin/env python3
234ed46a2SDaniel P. Berrangé#
334ed46a2SDaniel P. Berrangé# check-dco.py: validate all commits are signed off
434ed46a2SDaniel P. Berrangé#
534ed46a2SDaniel P. Berrangé# Copyright (C) 2020 Red Hat, Inc.
634ed46a2SDaniel P. Berrangé#
734ed46a2SDaniel P. Berrangé# SPDX-License-Identifier: GPL-2.0-or-later
834ed46a2SDaniel P. Berrangé
934ed46a2SDaniel P. Berrangéimport os
1034ed46a2SDaniel P. Berrangéimport os.path
1134ed46a2SDaniel P. Berrangéimport sys
1234ed46a2SDaniel P. Berrangéimport subprocess
1334ed46a2SDaniel P. Berrangé
1434ed46a2SDaniel P. Berrangénamespace = "qemu-project"
1534ed46a2SDaniel P. Berrangéif len(sys.argv) >= 2:
1634ed46a2SDaniel P. Berrangé    namespace = sys.argv[1]
1734ed46a2SDaniel P. Berrangé
1834ed46a2SDaniel P. Berrangécwd = os.getcwd()
1934ed46a2SDaniel P. Berrangéreponame = os.path.basename(cwd)
2034ed46a2SDaniel P. Berrangérepourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
2134ed46a2SDaniel P. Berrangé
2297f116f9SAlex Bennéeprint(f"adding upstream git repo @ {repourl}")
2334ed46a2SDaniel P. Berrangésubprocess.check_call(["git", "remote", "add", "check-dco", repourl])
2497f116f9SAlex Bennéesubprocess.check_call(["git", "fetch", "check-dco", "master"])
2534ed46a2SDaniel P. Berrangé
2634ed46a2SDaniel P. Berrangéancestor = subprocess.check_output(["git", "merge-base",
2734ed46a2SDaniel P. Berrangé                                    "check-dco/master", "HEAD"],
2834ed46a2SDaniel P. Berrangé                                   universal_newlines=True)
2934ed46a2SDaniel P. Berrangé
3034ed46a2SDaniel P. Berrangéancestor = ancestor.strip()
3134ed46a2SDaniel P. Berrangé
3234ed46a2SDaniel P. Berrangésubprocess.check_call(["git", "remote", "rm", "check-dco"])
3334ed46a2SDaniel P. Berrangé
3434ed46a2SDaniel P. Berrangéerrors = False
3534ed46a2SDaniel P. Berrangé
3634ed46a2SDaniel P. Berrangéprint("\nChecking for 'Signed-off-by: NAME <EMAIL>' " +
3734ed46a2SDaniel P. Berrangé      "on all commits since %s...\n" % ancestor)
3834ed46a2SDaniel P. Berrangé
3934ed46a2SDaniel P. Berrangélog = subprocess.check_output(["git", "log", "--format=%H %s",
4034ed46a2SDaniel P. Berrangé                               ancestor + "..."],
4134ed46a2SDaniel P. Berrangé                              universal_newlines=True)
4234ed46a2SDaniel P. Berrangé
4334ed46a2SDaniel P. Berrangéif log == "":
4434ed46a2SDaniel P. Berrangé    commits = []
4534ed46a2SDaniel P. Berrangéelse:
4634ed46a2SDaniel P. Berrangé    commits = [[c[0:40], c[41:]] for c in log.strip().split("\n")]
4734ed46a2SDaniel P. Berrangé
4834ed46a2SDaniel P. Berrangéfor sha, subject in commits:
4934ed46a2SDaniel P. Berrangé
5034ed46a2SDaniel P. Berrangé    msg = subprocess.check_output(["git", "show", "-s", sha],
5134ed46a2SDaniel P. Berrangé                                  universal_newlines=True)
5234ed46a2SDaniel P. Berrangé    lines = msg.strip().split("\n")
5334ed46a2SDaniel P. Berrangé
5434ed46a2SDaniel P. Berrangé    print("�� %s %s" % (sha, subject))
5534ed46a2SDaniel P. Berrangé    sob = False
5634ed46a2SDaniel P. Berrangé    for line in lines:
5734ed46a2SDaniel P. Berrangé        if "Signed-off-by:" in line:
5834ed46a2SDaniel P. Berrangé            sob = True
5934ed46a2SDaniel P. Berrangé            if "localhost" in line:
6034ed46a2SDaniel P. Berrangé                print("    ❌ FAIL: bad email in %s" % line)
6134ed46a2SDaniel P. Berrangé                errors = True
6234ed46a2SDaniel P. Berrangé
6334ed46a2SDaniel P. Berrangé    if not sob:
6434ed46a2SDaniel P. Berrangé        print("    ❌ FAIL missing Signed-off-by tag")
6534ed46a2SDaniel P. Berrangé        errors = True
6634ed46a2SDaniel P. Berrangé
6734ed46a2SDaniel P. Berrangéif errors:
6834ed46a2SDaniel P. Berrangé    print("""
6934ed46a2SDaniel P. Berrangé
7034ed46a2SDaniel P. Berrangé❌ ERROR: One or more commits are missing a valid Signed-off-By tag.
7134ed46a2SDaniel P. Berrangé
7234ed46a2SDaniel P. Berrangé
7334ed46a2SDaniel P. BerrangéThis project requires all contributors to assert that their contributions
7434ed46a2SDaniel P. Berrangéare provided in compliance with the terms of the Developer's Certificate
7534ed46a2SDaniel P. Berrangéof Origin 1.1 (DCO):
7634ed46a2SDaniel P. Berrangé
7734ed46a2SDaniel P. Berrangé  https://developercertificate.org/
7834ed46a2SDaniel P. Berrangé
7934ed46a2SDaniel P. BerrangéTo indicate acceptance of the DCO every commit must have a tag
8034ed46a2SDaniel P. Berrangé
81*270c81b7SDaniel P. Berrangé  Signed-off-by: YOUR NAME <EMAIL>
82*270c81b7SDaniel P. Berrangé
83*270c81b7SDaniel P. Berrangéwhere "YOUR NAME" is your commonly known identity in the context
84*270c81b7SDaniel P. Berrangéof the community.
8534ed46a2SDaniel P. Berrangé
8634ed46a2SDaniel P. BerrangéThis can be achieved by passing the "-s" flag to the "git commit" command.
8734ed46a2SDaniel P. Berrangé
8834ed46a2SDaniel P. BerrangéTo bulk update all commits on current branch "git rebase" can be used:
8934ed46a2SDaniel P. Berrangé
9034ed46a2SDaniel P. Berrangé  git rebase -i master -x 'git commit --amend --no-edit -s'
9134ed46a2SDaniel P. Berrangé
9234ed46a2SDaniel P. Berrangé""")
9334ed46a2SDaniel P. Berrangé
9434ed46a2SDaniel P. Berrangé    sys.exit(1)
9534ed46a2SDaniel P. Berrangé
9634ed46a2SDaniel P. Berrangésys.exit(0)
97