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 TRAVIS_COMMIT_RANGE
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:
- Loop over the commit range
- For each commit, check the Author Email against the
CONTRIBUTORS
file - If the author isn't listed in
CONTRIBUTORS
, fail (but defer...)
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:
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!