mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
In the past HACKING.md instructed developers to setup GOPATH explicitly.
This was removed some time ago:
github.com/snapcore/snapd/commit/5b9864a203e9ea26d743436a424699ec07a52ac7
The run-checks script will not work on a clean developer machine, even if
someone follows the HACKING.md instructions.
The problem is that run-checks does not support Go's default GOPATH
For example:
/home/foo> go env GOPATH
/home/foo/go
However, the internal GOPATH still respects externally set variables:
/home/foo> GOPATH="/home/foo/go:/home/foo/go2" go env GOPATH
/home/foo/go:/home/foo/go2
The run-checks script supported falling back to a hardcoded GOPATH location,
based on assumptions of where automated tests check out the repository.
For example:
The github actions repo location:
${{ github.workspace }}/src/github.com/snapcore/snapd
resulted in the fallback GOPATH to be:
GOPATH="${GOPATH:-$(realpath "$(dirname "$0")"/../../../../)}"
This was because the GOPATH was placed at the root of the github
action workspace.
However, the location is explicitly set in the environment variable
GOPATH before any call is made to run-checks as part of the job setup and
therefore not needed.
Other references of run-checks always set GOPATH before calling the script.
Changes:
- Use the Go provided "go env GOPATH" command to obtain GOPATH
- Remove the fallback logic for run-checks when determining GOPATH
- Add all possible bin paths from GOPATH to PATH
Signed-off-by: Fred Lotter <fred.lotter@canonical.com>
405 lines
13 KiB
Bash
Executable File
405 lines
13 KiB
Bash
Executable File
#!/bin/bash -eu
|
|
|
|
export LANG=C.UTF-8
|
|
export LANGUAGE=en
|
|
|
|
if command -v goctest >/dev/null; then
|
|
goctest="goctest"
|
|
else
|
|
goctest="go test"
|
|
fi
|
|
COVERMODE=${COVERMODE:-atomic}
|
|
COVERAGE_SUFFIX=${GO_BUILD_TAGS:-notags}
|
|
COVERAGE_OUT=${COVERAGE_OUT:-.coverage/coverage-$COVERAGE_SUFFIX.cov}
|
|
CHANGED_FILES=${CHANGED_FILES:-""}
|
|
|
|
if [ -z "${GITHUB_WORKFLOW:-}" ]; then
|
|
# when *not* running inside github, ensure we use go-1.18 by default
|
|
export PATH=/usr/lib/go-1.18/bin:"${PATH}"
|
|
fi
|
|
|
|
# add workaround for https://github.com/golang/go/issues/24449
|
|
if [ "$(uname -m)" = "s390x" ]; then
|
|
if go version | grep -q go1.10; then
|
|
echo "covermode 'atomic' crashes on s390x with go1.10, reseting "
|
|
echo "to 'set'. see https://github.com/golang/go/issues/24449"
|
|
COVERMODE="set"
|
|
fi
|
|
fi
|
|
|
|
# If GOPATH is set in the shell environment, the path will be reflected
|
|
# in $(go env GOPATH). If no shell path was set, Go will default the internal
|
|
# GOPATH to $HOME/go. Note that GOPATH may contain a colon delimited set
|
|
# of paths, so in order to run any binary from any of the installed GOPATHs
|
|
# we must add all the possible bin locations.
|
|
GOBINS=$(go env GOPATH | sed 's|:|/bin:|g' | sed 's|.*|\0/bin|g')
|
|
export PATH="$PATH:$GOBINS"
|
|
|
|
short=
|
|
|
|
STATIC=
|
|
UNIT=
|
|
|
|
case "${1:-all}" in
|
|
all)
|
|
STATIC=1
|
|
UNIT=1
|
|
;;
|
|
--static)
|
|
STATIC=1
|
|
;;
|
|
--unit)
|
|
UNIT=1
|
|
;;
|
|
--short-unit)
|
|
UNIT=1
|
|
short=1
|
|
;;
|
|
*)
|
|
echo "Wrong flag ${1}. To run a single suite use --static, --unit."
|
|
exit 1
|
|
esac
|
|
|
|
CURRENTTRAP="true"
|
|
EXIT_CODE=99
|
|
|
|
store_exit_code() {
|
|
EXIT_CODE=$?
|
|
}
|
|
|
|
exit_with_exit_code() {
|
|
exit $EXIT_CODE
|
|
}
|
|
|
|
addtrap() {
|
|
CURRENTTRAP="$CURRENTTRAP ; $1"
|
|
# shellcheck disable=SC2064
|
|
trap "store_exit_code; $CURRENTTRAP ; exit_with_exit_code" EXIT
|
|
}
|
|
|
|
goinstall() {
|
|
pkg="$1"
|
|
version="${2:-}"
|
|
# go1.18+ will no longer build/install packages. Here "go install"
|
|
# must be used but it will only fetch remote packages if the @latest
|
|
# (or similar syntax is used). Instead of checking the version we
|
|
# check if the "go install" help mentions this new feature.
|
|
if go help install | grep -q @latest; then
|
|
go install "${pkg}"@"${version:=latest}"
|
|
else
|
|
go get -u "${pkg}"@"${version:=latest}"
|
|
fi
|
|
}
|
|
|
|
endmsg() {
|
|
if [ $EXIT_CODE -eq 0 ]; then
|
|
p="success.txt"
|
|
m="All good, what could possibly go wrong."
|
|
else
|
|
p="failure.txt"
|
|
m="Crushing failure and despair."
|
|
fi
|
|
echo
|
|
if [ -t 1 ] && [ -z "$STATIC" ]; then
|
|
cat "data/$p"
|
|
else
|
|
echo "$m"
|
|
fi
|
|
}
|
|
addtrap endmsg
|
|
|
|
missing_interface_spread_test() {
|
|
snap_yaml="tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml"
|
|
core_snap_yaml="tests/main/interfaces-many-snap-provided/test-snapd-policy-app-provider-core/meta/snap.yaml"
|
|
classic_snap_yaml="tests/main/interfaces-many-snap-provided/test-snapd-policy-app-provider-classic/meta/snap.yaml"
|
|
for iface in $(go run ./tests/lib/list-interfaces.go) ; do
|
|
search="plugs: \\[ $iface \\]"
|
|
case "$iface" in
|
|
bool-file|gpio|pwm|dsp|netlink-driver|hidraw|i2c|iio|serial-port|spi)
|
|
# skip gadget provided interfaces for now
|
|
continue
|
|
;;
|
|
dbus|content)
|
|
search="interface: $iface"
|
|
;;
|
|
autopilot)
|
|
search='plugs: \[ autopilot-introspection \]'
|
|
;;
|
|
esac
|
|
if ! grep -q "$search" "$snap_yaml" ; then
|
|
echo "Missing high-level test for interface '$iface'. Please add to:"
|
|
echo "* $snap_yaml"
|
|
echo "* $core_snap_yaml (if needed)"
|
|
echo "* $classic_snap_yaml (if needed)"
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
if [ "$STATIC" = 1 ]; then
|
|
./get-deps.sh
|
|
|
|
# Run static tests.
|
|
echo Checking docs
|
|
./mdlint.py ./*.md ./**/*.md
|
|
|
|
# XXX: remove once we can use an action, see workflows/test.yaml for
|
|
# details why we still use this script
|
|
if [ -n "${GITHUB_PULL_REQUEST:-}" ] && [ "${GITHUB_PULL_REQUEST:-}" != "false" ]; then
|
|
echo Checking pull request summary
|
|
./check-pr-title.py "$GITHUB_PULL_REQUEST"
|
|
fi
|
|
|
|
# check commit author/committer name for unicode
|
|
./check-commit-email.py
|
|
|
|
if [ -z "${SKIP_GOFMT:-}" ]; then
|
|
echo Checking formatting
|
|
fmt=""
|
|
for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/\(c-\)\?vendor/' ); do
|
|
# skip vendor packages
|
|
s="$(${GOFMT:-gofmt} -s -d "$dir" || true)"
|
|
if [ -n "$s" ]; then
|
|
fmt="$s\\n$fmt"
|
|
fi
|
|
done
|
|
if [ -n "$fmt" ]; then
|
|
echo "Formatting wrong in following files:"
|
|
# shellcheck disable=SC2001
|
|
echo "$fmt" | sed -e 's/\\n/\n/g'
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# go vet
|
|
echo Running vet
|
|
go list ./... | grep -v '/vendor/' | xargs go vet
|
|
|
|
echo 'Checking for usages of http.Status*'
|
|
got=""
|
|
for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/vendor/' ); do
|
|
s="$(grep -nP 'http\.Status(?!Text)' "$dir"/*.go || true)"
|
|
if [ -n "$s" ]; then
|
|
got="$s\\n$got"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$got" ]; then
|
|
echo 'Usages of http.Status*, we prefer the numeric values directly:'
|
|
echo "$got"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Checking for direct usages of math/rand"
|
|
got=""
|
|
for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/vendor/' ); do
|
|
# shellcheck disable=SC2063
|
|
s="$(grep -nP --exclude '*_test.go' --exclude 'randutil/*.go' math/rand "$dir"/*.go || true)"
|
|
if [ -n "$s" ]; then
|
|
got="$s\\n$got"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$got" ]; then
|
|
echo 'Direct usages of math/rand, we prefer randutil:'
|
|
echo "$got"
|
|
exit 1
|
|
fi
|
|
|
|
if command -v shellcheck >/dev/null; then
|
|
exclude_tools_path=tests/lib/external/snapd-testing-tools
|
|
echo "Checking shell scripts..."
|
|
if [ -n "$CHANGED_FILES" ]; then
|
|
echo "Checking just the changed bash files"
|
|
echo "Changed files: $CHANGED_FILES"
|
|
# shellcheck disable=SC2086
|
|
INITIAL_FILES="$( file -N $CHANGED_FILES | awk -F": " '$2~/shell.script/{print $1}' )"
|
|
else
|
|
echo "Checking all the bash files"
|
|
INITIAL_FILES="$( ( git ls-files -z 2>/dev/null || find . \( -name .git -o -name vendor -o -name c-vendor \) -prune -o -print0) | xargs -0 file -N | awk -F": " '$2~/shell.script/{print $1}' )"
|
|
fi
|
|
|
|
echo "Filtering files"
|
|
FILTERED_FILES=
|
|
for file in $INITIAL_FILES; do
|
|
if ! echo "$file" | grep -q "$exclude_tools_path"; then
|
|
FILTERED_FILES="$FILTERED_FILES $file"
|
|
fi
|
|
done
|
|
if [ -n "$FILTERED_FILES" ]; then
|
|
echo "Running shellcheck for files: $FILTERED_FILES"
|
|
# shellcheck disable=SC2086
|
|
shellcheck -x $FILTERED_FILES
|
|
else
|
|
echo "Skipping shellcheck, no files to check"
|
|
fi
|
|
|
|
regexp='GOPATH(?!%%:\*)(?!:)[^= ]*/'
|
|
if grep -qPr --exclude HACKING.md --exclude 'Makefile.*' --exclude-dir .git --exclude-dir vendor "$regexp"; then
|
|
echo "Using GOPATH as if it were a single entry and not a list:"
|
|
grep -PHrn -C1 --color=auto --exclude HACKING.md --exclude 'Makefile.*' --exclude-dir .git --exclude-dir vendor "$regexp"
|
|
echo "Use GOHOME, or {GOPATH%%:*}, instead."
|
|
exit 1
|
|
fi
|
|
unset regexp
|
|
|
|
# also run spread-shellcheck
|
|
FILTERED_FILES="spread.yaml"
|
|
if [ -n "$CHANGED_FILES" ]; then
|
|
# shellcheck disable=SC2086
|
|
for changed_file in $CHANGED_FILES; do
|
|
if [[ $changed_file == */task.yaml ]]; then
|
|
FILTERED_FILES="$FILTERED_FILES $changed_file"
|
|
fi
|
|
done
|
|
else
|
|
FILTERED_FILES="$FILTERED_FILES tests"
|
|
fi
|
|
# XXX: exclude core20-preseed test as its environment block confuses shellcheck, and it's not possible to disable shellcheck there.
|
|
# shellcheck disable=SC2086
|
|
./tests/lib/external/snapd-testing-tools/utils/spread-shellcheck $FILTERED_FILES --exclude "$exclude_tools_path" --exclude "tests/nested/manual/core20-preseed"
|
|
fi
|
|
|
|
if [ -z "${SKIP_MISSPELL-}" ]; then
|
|
echo "Checking spelling errors"
|
|
if ! command -v misspell >/dev/null; then
|
|
goinstall github.com/client9/misspell/cmd/misspell
|
|
fi
|
|
# FIXME: auter is only misspelled in the changelog so we should fix there
|
|
# PROCES is used in the seccomp tests (PRIO_PROCES{,S,SS})
|
|
# exportfs is used in the nfs-support test
|
|
# becuase because of misspell in upstream steam rules (PR#12657)
|
|
MISSPELL_IGNORE="auther,PROCES,PROCESSS,proces,processs,exportfs,becuase"
|
|
git ls-files -z -- . ':!:./po' ':!:./vendor' ':!:./c-vendor' ':!:./cmd/libsnap-confine-private/bpf/vendor' |
|
|
xargs -0 misspell -error -i "$MISSPELL_IGNORE"
|
|
fi
|
|
|
|
if [ -z "${SKIP_INEFFASSIGN-}" ]; then
|
|
if dpkg --compare-versions "$(go version | awk '$3 ~ /^go[0-9]/ {print substr($3, 3)}')" ge 1.12; then
|
|
echo "Checking for ineffective assignments"
|
|
if ! command -v ineffassign >/dev/null; then
|
|
goinstall github.com/gordonklaus/ineffassign
|
|
fi
|
|
# ineffassign knows about ignoring vendor/ \o/
|
|
ineffassign ./...
|
|
fi
|
|
fi
|
|
|
|
echo "Checking for naked returns"
|
|
if ! command -v nakedret >/dev/null; then
|
|
goinstall github.com/alexkohler/nakedret v1.0.1
|
|
fi
|
|
got=$(go list ./... | grep -v '/osutil/udev/' | grep -v '/vendor/' | xargs nakedret 2>&1)
|
|
if [ -n "$got" ]; then
|
|
echo "$got"
|
|
if [ -z "${SKIP_NAKEDRET:-}" ]; then
|
|
exit 1
|
|
else
|
|
echo "Ignoring nakedret errors as requested"
|
|
fi
|
|
fi
|
|
|
|
echo "Checking all interfaces have minimal spread test"
|
|
missing_interface_spread_test
|
|
|
|
echo "Checking for incorrect multiline strings in spread tests"
|
|
badmultiline=$(find tests -name 'task.yaml' -print0 -o -name 'spread.yaml' -print0 | \
|
|
xargs -0 grep -R -n -E '(restore*|prepare*|execute|debug):\s*$' || true)
|
|
if [ -n "$badmultiline" ]; then
|
|
echo "Incorrect multiline strings at the following locations:"
|
|
echo "$badmultiline"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Checking for potentially incorrect use of MATCH -v"
|
|
badMATCH=$(find tests -name 'task.yaml' -print0 -o -name 'spread.yaml' -print0 | \
|
|
xargs -0 grep -R -n -E 'MATCH +-v' || true)
|
|
if [ -n "$badMATCH" ]; then
|
|
echo "Potentially incorrect use of MATCH -v at the following locations:"
|
|
echo "$badMATCH"
|
|
exit 1
|
|
fi
|
|
|
|
# FIXME: re-add staticcheck with a matching version for the used go-version
|
|
|
|
if [ -z "${SKIP_TESTS_FORMAT_CHECK-}" ] || [ "$SKIP_TESTS_FORMAT_CHECK" = 0 ]; then
|
|
echo "Checking tests formatting"
|
|
./tests/lib/external/snapd-testing-tools/utils/check-test-format ./tests
|
|
fi
|
|
|
|
echo "Checking for usages of !=, == or Equals with ErrNoState"
|
|
if got=$(grep -n -R -E "(\!=|==|Equals,) (state\.)?ErrNoState" --include=*.go) ; then
|
|
echo "Don't use equality checks with ErrNoState, use errors.Is() instead"
|
|
echo "$got"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ "$UNIT" = 1 ]; then
|
|
./get-deps.sh
|
|
|
|
echo "Show go version"
|
|
command -v go
|
|
go version
|
|
|
|
tags=
|
|
if [ -n "${GO_BUILD_TAGS-}" ]; then
|
|
echo "Using build tags: $GO_BUILD_TAGS"
|
|
tags="-tags $GO_BUILD_TAGS"
|
|
fi
|
|
|
|
echo Building
|
|
# shellcheck disable=SC2086
|
|
go build -v $tags github.com/snapcore/snapd/...
|
|
|
|
# tests
|
|
echo Running tests from "$PWD"
|
|
if [ "$short" = 1 ]; then
|
|
# shellcheck disable=SC2046,SC2086
|
|
GOTRACEBACK=1 $goctest $tags -short -timeout 5m $(go list ./... | grep -v '/vendor/' )
|
|
else
|
|
coverage=""
|
|
if [ -z "${SKIP_COVERAGE-}" ]; then
|
|
coverage="-coverprofile=$COVERAGE_OUT -covermode=$COVERMODE"
|
|
# Prepare the coverage output profile.
|
|
mkdir -p "$(dirname "$COVERAGE_OUT")"
|
|
echo "mode: $COVERMODE" > "$COVERAGE_OUT"
|
|
else
|
|
echo "Skipping test coverage"
|
|
fi
|
|
|
|
# shellcheck disable=SC2046,SC2086
|
|
GOTRACEBACK=1 $goctest $tags -timeout 5m $coverage $(go list ./... | grep -v '/vendor/' )
|
|
fi
|
|
|
|
# python unit test for mountinfo.query and version-compare
|
|
command -v python2 && python2 ./tests/lib/tools/mountinfo.query --run-unit-tests
|
|
command -v python3 && python3 ./tests/lib/tools/mountinfo.query --run-unit-tests
|
|
command -v python2 && python2 ./tests/lib/tools/version-compare --run-unit-tests
|
|
command -v python3 && python3 ./tests/lib/tools/version-compare --run-unit-tests
|
|
fi
|
|
|
|
UNCLEAN="$(git status -s|grep '^??')" || true
|
|
SKIP_UNCLEAN=${SKIP_UNCLEAN=}
|
|
if [ -n "$UNCLEAN" ] && [ -z "$SKIP_UNCLEAN" ]; then
|
|
cat <<EOF
|
|
|
|
There are files left in the git tree after the tests:
|
|
|
|
$UNCLEAN
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "${SKIP_DIRTY_CHECK-}" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# XXX: re-enable after vendor/vendor.json is removed
|
|
# if git describe --always --dirty | grep -q dirty; then
|
|
# echo "Build tree is dirty"
|
|
# git diff
|
|
# exit 1
|
|
# fi
|