#!/bin/bash # Selectively run tests for this repo, based on what has changed # in a commit. Runs short tests for the whole repo, and full tests # for changed directories. set -e prefix=cloud.google.com/go dryrun=false if [[ $1 == "-n" ]]; then dryrun=true shift fi if [[ $1 == "" ]]; then echo >&2 "usage: $0 [-n] COMMIT" exit 1 fi # Files or directories that cause all tests to run if modified. declare -A run_all run_all=([.travis.yml]=1 [run-tests.sh]=1) function run { if $dryrun; then echo $* else (set -x; $*) fi } # Find all the packages that have changed in this commit. declare -A changed_packages for f in $(git diff-tree --no-commit-id --name-only -r $1); do if [[ ${run_all[$f]} == 1 ]]; then # This change requires a full test. Do it and exit. run go test -race -v $prefix/... exit fi # Map, e.g., "spanner/client.go" to "$prefix/spanner". d=$(dirname $f) if [[ $d == "." ]]; then pkg=$prefix else pkg=$prefix/$d fi changed_packages[$pkg]=1 done echo "changed packages: ${!changed_packages[*]}" # Reports whether its argument, a package name, depends (recursively) # on a changed package. function depends_on_changed_package { # According to go list, a package does not depend on itself, so # we test that separately. if [[ ${changed_packages[$1]} == 1 ]]; then return 0 fi for dep in $(go list -f '{{range .Deps}}{{.}} {{end}}' $1); do if [[ ${changed_packages[$dep]} == 1 ]]; then return 0 fi done return 1 } # Collect the packages into two separate lists. (It is faster to call "go test" on a # list of packages than to individually "go test" each one.) shorts= fulls= for pkg in $(go list $prefix/...); do # for each package in the repo if depends_on_changed_package $pkg; then # if it depends on a changed package fulls="$fulls $pkg" # run the full test else # otherwise shorts="$shorts $pkg" # run the short test fi done run go test -race -v -short $shorts if [[ $fulls != "" ]]; then run go test -race -v $fulls fi