mirror of https://github.com/docker/docs.git
Merge pull request #5022 from tianon/make-validate
Add "make validate" for both local and CI gofmt and DCO verification
This commit is contained in:
commit
566d49c9ca
14
.travis.yml
14
.travis.yml
|
@ -10,21 +10,11 @@ install: true
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- env | sort
|
- env | sort
|
||||||
- sudo apt-get update -qq
|
|
||||||
- sudo apt-get install -qq python-yaml
|
|
||||||
- git remote add upstream git://github.com/dotcloud/docker.git
|
|
||||||
- upstream=master;
|
|
||||||
if [ "$TRAVIS_PULL_REQUEST" != false ]; then
|
|
||||||
upstream=$TRAVIS_BRANCH;
|
|
||||||
fi;
|
|
||||||
git fetch --append --no-tags upstream refs/heads/$upstream:refs/remotes/upstream/$upstream
|
|
||||||
# sometimes we have upstream master already as origin/master (PRs), but other times we don't, so let's just make sure we have a completely unambiguous way to specify "upstream master" from here out
|
|
||||||
# but if it's a PR against non-master, we need that upstream branch instead :)
|
|
||||||
- sudo pip install -r docs/requirements.txt
|
- sudo pip install -r docs/requirements.txt
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- hack/travis/dco.py
|
- hack/make.sh validate-dco
|
||||||
- hack/travis/gofmt.py
|
- hack/make.sh validate-gofmt
|
||||||
- make -sC docs SPHINXOPTS=-qW docs man
|
- make -sC docs SPHINXOPTS=-qW docs man
|
||||||
|
|
||||||
# vim:set sw=2 ts=2:
|
# vim:set sw=2 ts=2:
|
||||||
|
|
|
@ -40,13 +40,19 @@ echo
|
||||||
|
|
||||||
# List of bundles to create when no argument is passed
|
# List of bundles to create when no argument is passed
|
||||||
DEFAULT_BUNDLES=(
|
DEFAULT_BUNDLES=(
|
||||||
|
validate-dco
|
||||||
|
validate-gofmt
|
||||||
|
|
||||||
binary
|
binary
|
||||||
|
|
||||||
test
|
test
|
||||||
test-integration
|
test-integration
|
||||||
test-integration-cli
|
test-integration-cli
|
||||||
|
|
||||||
dynbinary
|
dynbinary
|
||||||
dyntest
|
dyntest
|
||||||
dyntest-integration
|
dyntest-integration
|
||||||
|
|
||||||
cover
|
cover
|
||||||
cross
|
cross
|
||||||
tgz
|
tgz
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z "$VALIDATE_UPSTREAM" ]; then
|
||||||
|
# this is kind of an expensive check, so let's not do this twice if we
|
||||||
|
# are running more than one validate bundlescript
|
||||||
|
|
||||||
|
VALIDATE_REPO='https://github.com/dotcloud/docker.git'
|
||||||
|
VALIDATE_BRANCH='master'
|
||||||
|
|
||||||
|
if [ "$TRAVIS" = 'true' -a "$TRAVIS_PULL_REQUEST" != 'false' ]; then
|
||||||
|
VALIDATE_REPO="https://github.com/${TRAVIS_REPO_SLUG}.git"
|
||||||
|
VALIDATE_BRANCH="${TRAVIS_BRANCH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
VALIDATE_HEAD="$(git rev-parse --verify HEAD)"
|
||||||
|
|
||||||
|
git fetch -q "$VALIDATE_REPO" "refs/heads/$VALIDATE_BRANCH"
|
||||||
|
VALIDATE_UPSTREAM="$(git rev-parse --verify FETCH_HEAD)"
|
||||||
|
|
||||||
|
VALIDATE_COMMIT_LOG="$VALIDATE_UPSTREAM..$VALIDATE_HEAD"
|
||||||
|
VALIDATE_COMMIT_DIFF="$VALIDATE_UPSTREAM...$VALIDATE_HEAD"
|
||||||
|
|
||||||
|
validate_diff() {
|
||||||
|
if [ "$VALIDATE_UPSTREAM" != "$VALIDATE_HEAD" ]; then
|
||||||
|
git diff "$VALIDATE_COMMIT_DIFF" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
validate_log() {
|
||||||
|
if [ "$VALIDATE_UPSTREAM" != "$VALIDATE_HEAD" ]; then
|
||||||
|
git log "$VALIDATE_COMMIT_LOG" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
fi
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source "$(dirname "$BASH_SOURCE")/.validate"
|
||||||
|
|
||||||
|
adds=$(validate_diff --numstat | awk '{ s += $1 } END { print s }')
|
||||||
|
dels=$(validate_diff --numstat | awk '{ s += $2 } END { print s }')
|
||||||
|
notDocs="$(validate_diff --numstat | awk '$3 !~ /^docs\// { print $3 }')"
|
||||||
|
|
||||||
|
: ${adds:=0}
|
||||||
|
: ${dels:=0}
|
||||||
|
|
||||||
|
if [ $adds -eq 0 -a $dels -eq 0 ]; then
|
||||||
|
echo '0 adds, 0 deletions; nothing to validate! :)'
|
||||||
|
elif [ -z "$notDocs" -a $adds -le 1 -a $dels -le 1 ]; then
|
||||||
|
echo 'Congratulations! DCO small-patch-exception material!'
|
||||||
|
else
|
||||||
|
dcoPrefix='Docker-DCO-1.1-Signed-off-by:'
|
||||||
|
dcoRegex="^$dcoPrefix ([^<]+) <([^<>@]+@[^<>]+)> \\(github: (\S+)\\)$"
|
||||||
|
commits=( $(validate_log --format='format:%H%n') )
|
||||||
|
badCommits=()
|
||||||
|
for commit in "${commits[@]}"; do
|
||||||
|
if [ -z "$(git log -1 --format='format:' --name-status "$commit")" ]; then
|
||||||
|
# no content (ie, Merge commit, etc)
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! git log -1 --format='format:%B' "$commit" | grep -qE "$dcoRegex"; then
|
||||||
|
badCommits+=( "$commit" )
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ ${#badCommits[@]} -eq 0 ]; then
|
||||||
|
echo "Congratulations! All commits are properly signed with the DCO!"
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "These commits do not have a proper '$dcoPrefix' marker:"
|
||||||
|
for commit in "${badCommits[@]}"; do
|
||||||
|
echo " - $commit"
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
echo 'Please amend each commit to include a properly formatted DCO marker.'
|
||||||
|
echo
|
||||||
|
echo 'Visit the following URL for information about the Docker DCO:'
|
||||||
|
echo ' https://github.com/dotcloud/docker/blob/master/CONTRIBUTING.md#sign-your-work'
|
||||||
|
echo
|
||||||
|
} >&2
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
fi
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source "$(dirname "$BASH_SOURCE")/.validate"
|
||||||
|
|
||||||
|
IFS=$'\n'
|
||||||
|
files=( $(validate_diff --diff-filter=ACMR --name-only -- '*.go' | grep -v '^vendor/' || true) )
|
||||||
|
unset IFS
|
||||||
|
|
||||||
|
badFiles=()
|
||||||
|
for f in "${files[@]}"; do
|
||||||
|
# we use "git show" here to validate that what's committed is formatted
|
||||||
|
if [ "$(git show "$VALIDATE_HEAD:$f" | gofmt -s -l)" ]; then
|
||||||
|
badFiles+=( "$f" )
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#badFiles[@]} -eq 0 ]; then
|
||||||
|
echo 'Congratulations! All Go source files are properly formatted.'
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "These files are not properly gofmt'd:"
|
||||||
|
for f in "${badFiles[@]}"; do
|
||||||
|
echo " - $f"
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
echo 'Please reformat the above files using "gofmt -s -w" and commit the result.'
|
||||||
|
echo
|
||||||
|
} >&2
|
||||||
|
false
|
||||||
|
fi
|
|
@ -1,54 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
from env import commit_range
|
|
||||||
|
|
||||||
commit_format = '-%n hash: "%h"%n author: %aN <%aE>%n message: |%n%w(0,2,2).%B'
|
|
||||||
|
|
||||||
gitlog = subprocess.check_output([
|
|
||||||
'git', 'log', '--reverse',
|
|
||||||
'--format=format:'+commit_format,
|
|
||||||
'..'.join(commit_range), '--',
|
|
||||||
])
|
|
||||||
|
|
||||||
commits = yaml.load(gitlog)
|
|
||||||
if not commits:
|
|
||||||
exit(0) # what? how can we have no commits?
|
|
||||||
|
|
||||||
DCO = 'Docker-DCO-1.1-Signed-off-by:'
|
|
||||||
|
|
||||||
p = re.compile(r'^{0} ([^<]+) <([^<>@]+@[^<>]+)> \(github: (\S+)\)$'.format(re.escape(DCO)), re.MULTILINE|re.UNICODE)
|
|
||||||
|
|
||||||
failed_commits = 0
|
|
||||||
|
|
||||||
for commit in commits:
|
|
||||||
commit['message'] = commit['message'][1:]
|
|
||||||
# trim off our '.' that exists just to prevent fun YAML parsing issues
|
|
||||||
# see https://github.com/dotcloud/docker/pull/3836#issuecomment-33723094
|
|
||||||
# and https://travis-ci.org/dotcloud/docker/builds/17926783
|
|
||||||
|
|
||||||
commit['stat'] = subprocess.check_output([
|
|
||||||
'git', 'log', '--format=format:', '--max-count=1',
|
|
||||||
'--name-status', commit['hash'], '--',
|
|
||||||
])
|
|
||||||
if commit['stat'] == '':
|
|
||||||
print 'Commit {0} has no actual changed content, skipping.'.format(commit['hash'])
|
|
||||||
continue
|
|
||||||
|
|
||||||
m = p.search(commit['message'])
|
|
||||||
if not m:
|
|
||||||
print 'Commit {1} does not have a properly formatted "{0}" marker.'.format(DCO, commit['hash'])
|
|
||||||
failed_commits += 1
|
|
||||||
continue # print ALL the commits that don't have a proper DCO
|
|
||||||
|
|
||||||
(name, email, github) = m.groups()
|
|
||||||
|
|
||||||
# TODO verify that "github" is the person who actually made this commit via the GitHub API
|
|
||||||
|
|
||||||
if failed_commits > 0:
|
|
||||||
exit(failed_commits)
|
|
||||||
|
|
||||||
print 'All commits have a valid "{0}" marker.'.format(DCO)
|
|
||||||
exit(0)
|
|
|
@ -1,21 +0,0 @@
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
if 'TRAVIS' not in os.environ:
|
|
||||||
print 'TRAVIS is not defined; this should run in TRAVIS. Sorry.'
|
|
||||||
exit(127)
|
|
||||||
|
|
||||||
if os.environ['TRAVIS_PULL_REQUEST'] != 'false':
|
|
||||||
commit_range = ['upstream/' + os.environ['TRAVIS_BRANCH'], 'FETCH_HEAD']
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
subprocess.check_call([
|
|
||||||
'git', 'log', '-1', '--format=format:',
|
|
||||||
os.environ['TRAVIS_COMMIT_RANGE'], '--',
|
|
||||||
])
|
|
||||||
commit_range = os.environ['TRAVIS_COMMIT_RANGE'].split('...')
|
|
||||||
if len(commit_range) == 1: # if it didn't split, it must have been separated by '..' instead
|
|
||||||
commit_range = commit_range[0].split('..')
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
print 'TRAVIS_COMMIT_RANGE is invalid. This seems to be a force push. We will just assume it must be against upstream master and compare all commits in between.'
|
|
||||||
commit_range = ['upstream/master', 'HEAD']
|
|
|
@ -1,31 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from env import commit_range
|
|
||||||
|
|
||||||
files = subprocess.check_output([
|
|
||||||
'git', 'diff', '--diff-filter=ACMR',
|
|
||||||
'--name-only', '...'.join(commit_range), '--',
|
|
||||||
])
|
|
||||||
|
|
||||||
exit_status = 0
|
|
||||||
|
|
||||||
for filename in files.split('\n'):
|
|
||||||
if filename.startswith('vendor/'):
|
|
||||||
continue # we can't be changing our upstream vendors for gofmt, so don't even check them
|
|
||||||
|
|
||||||
if filename.endswith('.go'):
|
|
||||||
try:
|
|
||||||
out = subprocess.check_output(['gofmt', '-s', '-l', filename])
|
|
||||||
if out != '':
|
|
||||||
print out,
|
|
||||||
exit_status = 1
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
exit_status = 1
|
|
||||||
|
|
||||||
if exit_status != 0:
|
|
||||||
print 'Reformat the files listed above with "gofmt -s -w" and try again.'
|
|
||||||
exit(exit_status)
|
|
||||||
|
|
||||||
print 'All files pass gofmt.'
|
|
||||||
exit(0)
|
|
Loading…
Reference in New Issue