https://new.jameshunt.us

Checking CLAs via Travis— or —Make the Robots Enforce Legal F/OSS Requirements

If you're running an Open Source project using a Copyleft license like the GNU General Public License, its weaker cousin the LGPL, or even a variation on the Apache License, you should probably be getting Contributor License Agreements from everyone submitting code for inclusion.

Why?

Without a CLA, or some other legal contract, you technically have no right to redistribute anyone elses changes. There's a big debate online about whether CLAs are too heavy-handed, whether they provide any real protection, and if they drive away would-be contributors.

I want to side-step the socio-legal issues for now, and just focus on using a the Travis CI tool for enforcing CLAs whenever a Github Pull Request is submitted.

The concept is pretty straightforward: maintain a list of identities (read: email addresses) of people who have signed and submitted CLAs. Keep that file in-repo, and teach the CI build script to check the new commits it's testing against that list.

Simple!

Here's the format of the CONTRIBUTORS file:

# comments start with an octothorpe
# and run until the end of the line

# ^^ blank lines are ignored.

# the normal case - one person, one email
Felicia Adkins <felicia@example.com>

# two emails can be supplied if necessary
Mike Nash <m@example.com> <mike.nash@example.com>

When someone signs a new CLA, add their name to the list!

With Travis, we can use the TRAVISCOMMITRANGE environment variable, which lists the range of commits (SHA1 IDs) that were included in the git push or Github Pull Request. The idea is this:

Here's a Bash function you can add to your CI script:

check_cla() {
  local passchar="\xe2\x9c\x94" # U+2714 - ballot check
  local failchar="\xe2\x9c\x98" # U+2718 - ballot x
  local rc=0
  local IFS=$'\n'

  echo "Checking CONTRIBUTOR status..."
  for x in $(git log --pretty=format:'%aE %h - %s (%aN <%aE>)' \\\\
                 ${TRAVIS_COMMIT_RANGE}); do
    email=${x%% *}
    desc=${x#* }
    if grep -q '^[^#].*<'${email}'>' CONTRIBUTORS; then
      echo -e "\033[32m${passchar}\033[0m $desc"
    else
      echo -e "\033[31m${failchar}\033[0m $desc"
      echo -e "  \033[31m<${email}> not listed in CONTRIBUTORS file!\033[0m"
      rc=1
    fi
  done
  echo

  return $rc
}

When you call it, it will print out something like this:

Screenshot of a Travis CI build log as it checks contributor status.

If it finds any commit authors who aren't listed (again, by email address) in the CONTRIBUTORS file, it will print a message to that effect and ultimately return non-zero. With set -e enabled, this will fail your build. Otherwise, you can just check $? or wrap the call in an if block.

Happy Hacking!

James (@iamjameshunt) works on the Internet, spends his weekends developing new and interesting bits of software and his nights trying to make sense of research papers.

Currently exploring Kubernetes, as both a floor wax and a dessert topping.