mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
* i/builtin: add registry interface Add a registry interface that snaps can use to access a particular registry view. Signed-off-by: Miguel Pires <miguel.pires@canonical.com> * registry: constrain registry name Signed-off-by: Miguel Pires <miguel.pires@canonical.com> --------- Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
470 lines
16 KiB
Bash
Executable File
470 lines
16 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
|
|
# TODO: remove registry once we test the interface in the spread test
|
|
bool-file|gpio|pwm|dsp|netlink-driver|hidraw|i2c|iio|serial-port|spi|registry)
|
|
# skip gadget provided interfaces for now
|
|
continue
|
|
;;
|
|
dbus|content)
|
|
search="interface: $iface"
|
|
;;
|
|
autopilot)
|
|
search='plugs: \[ autopilot-introspection \]'
|
|
;;
|
|
esac
|
|
|
|
# check if a standalone test already exists and that it at least
|
|
# connects and disconnects the interface
|
|
dedicated_test=$(find tests/main/ -maxdepth 1 -name "interfaces-$iface")
|
|
if [ -n "$dedicated_test" ]; then
|
|
if grep -q "$search" "$snap_yaml" ; then
|
|
echo "Dedicated test '$dedicated_test' found for '$iface'."
|
|
echo "Please remove '$iface' from '$snap_yaml'."
|
|
exit 1
|
|
fi
|
|
# dedicated test already exists, skip high-level test check below
|
|
continue
|
|
fi
|
|
|
|
# check if high-level minimal test exists for interface
|
|
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_TITLE:-}" ]; then
|
|
echo Checking pull request summary
|
|
./check-pr-title.py "${GITHUB_PULL_REQUEST_TITLE}"
|
|
else
|
|
echo Skipping pull request summary check: not a 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
|
|
|
|
echo "Checking for usages of deprecated io/ioutil"
|
|
got=""
|
|
for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/vendor/' ); do
|
|
# shellcheck disable=SC2063
|
|
s="$(grep -nP io/ioutil "$dir"/*.go || true)"
|
|
if [ -n "$s" ]; then
|
|
got="$s\\n$got"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$got" ]; then
|
|
echo 'Found usages of deprecated io/ioutil, please use "io" or "os" equivalents'
|
|
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 $(pwd)/$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 a 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
|
|
CHANGED_TESTS=""
|
|
FILTERED_TESTS=""
|
|
EXCLUDE_PATH=tests/lib/external/snapd-testing-tools
|
|
if [ -n "$CHANGED_FILES" ]; then
|
|
# shellcheck disable=SC2086
|
|
for changed_file in $CHANGED_FILES; do
|
|
if [[ $changed_file == */task.yaml ]]; then
|
|
CHANGED_TESTS="$CHANGED_TESTS $changed_file"
|
|
fi
|
|
done
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
for test in $CHANGED_TESTS; do
|
|
if ! echo "$test" | grep -q "$EXCLUDE_PATH"; then
|
|
if [ -z "$FILTERED_TESTS" ]; then
|
|
FILTERED_TESTS="$test"
|
|
else
|
|
FILTERED_TESTS="$FILTERED_TESTS $test"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo "Checking tests formatting"
|
|
if [ -n "$FILTERED_TESTS" ]; then
|
|
# shellcheck disable=SC2086
|
|
./tests/lib/external/snapd-testing-tools/utils/check-test-format --tests $FILTERED_TESTS
|
|
fi
|
|
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=
|
|
race=
|
|
if [ -n "${GO_BUILD_TAGS-}" ]; then
|
|
echo "Using build tags: $GO_BUILD_TAGS"
|
|
tags="-tags $GO_BUILD_TAGS"
|
|
fi
|
|
if [ -n "${GO_TEST_RACE-}" ]; then
|
|
echo "Using go test -race"
|
|
race="-race"
|
|
fi
|
|
|
|
echo Building
|
|
# shellcheck disable=SC2086
|
|
go build -v $tags $race github.com/snapcore/snapd/...
|
|
|
|
# tests
|
|
echo Running tests from "$PWD"
|
|
if [ "$short" = 1 ]; then
|
|
# shellcheck disable=SC2046,SC2086
|
|
GOTRACEBACK=1 $goctest $tags $race -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 $race -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
|
|
command -v pytest-3 && PYTHONDONTWRITEBYTECODE=1 pytest-3 ./release-tools
|
|
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
|