mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-07 07:07:05 +02:00
Various different CI jobs need Go modules in order to build or test Vault. To speed this up in CI we cache them in Github Actions. The caching requires downloading all modules first in order to upload them to the actions cache, which is performed by calling the `go-mod-download` Make target. This target will iterate over the directory tree and download Go modules in all directories that include a `go.mod` file. There are two small problems with this approach that we resolved with this PR: * Our `go-mod-download` target would download modules for all `go.mod`'s present in the directory tree, regardless of whether or not they are required to build or test Vault. Only downloading those required results in slightly smaller caches. * `tools/pipeline` is intentionally a separate Go module so as to not require its modules in order to build Vault, however, our `go-mod-download` downloading all modules requires the workflow environment to include auth credentials for internal modules. If a community contributed PRs modifies a `go.mod`, which in turn requires a new cache, the PR will always fail because it cannot download modules that require secrets. Now we avoid installing our `tools/pipeline` modules when generating our module cache which should allow community contributed PRs to execute build and Go tests, while skipping enos workflows which already required secrets and were thus skipped. Signed-off-by: Ryan Cragun <me@ryan.ec>
119 lines
3.4 KiB
Bash
Executable File
119 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
set -euo pipefail
|
|
|
|
# Perform Go formatting checks with gofumpt.
|
|
check_fmt() {
|
|
echo "==> Checking code formatting..."
|
|
|
|
declare -a malformed=()
|
|
IFS=" " read -r -a files <<< "$(tr '\n' ' ' <<< "$@")"
|
|
if [ -n "${files+set}" ] && [[ "${files[0]}" != "" ]]; then
|
|
echo "--> Checking changed files..."
|
|
for file in "${files[@]}"; do
|
|
if [ ! -f "$file" ]; then
|
|
echo "--> $file no longer exists ⚠"
|
|
continue
|
|
fi
|
|
|
|
if echo "$file" | grep -v pb.go | grep -v vendor > /dev/null; then
|
|
local output
|
|
if ! output=$(gofumpt -l "$file") || [ "$output" != "" ]; then
|
|
echo "--> ${file} ✖"
|
|
malformed+=("$file")
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
echo "--> ${file} ✔"
|
|
done
|
|
else
|
|
echo "--> Checking all files..."
|
|
IFS=" " read -r -a malformed <<< "$(find . -name '*.go' | grep -v pb.go | grep -v vendor | xargs gofumpt -l)"
|
|
fi
|
|
|
|
if [ "${#malformed[@]}" -ne 0 ] && [ -n "${malformed[0]}" ] ; then
|
|
echo "--> The following files need to be reformatted with gofumpt"
|
|
printf '%s\n' "${malformed[@]}"
|
|
echo "Run \`make fmt\` to reformat code."
|
|
for file in "${malformed[@]}"; do
|
|
gofumpt -w "$file"
|
|
git diff --no-color "$file"
|
|
done
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Check that the Go toolchain meets minimum version requiremets.
|
|
check_version() {
|
|
GO_CMD=${GO_CMD:-go}
|
|
|
|
GO_VERSION_MIN=$1
|
|
echo "==> Checking that build is using go version >= $1..."
|
|
|
|
if $GO_CMD version | grep -q devel; then
|
|
GO_VERSION="devel"
|
|
else
|
|
GO_VERSION=$($GO_CMD version | grep -o 'go[0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?' | tr -d 'go')
|
|
|
|
IFS="." read -r -a GO_VERSION_ARR <<< "$GO_VERSION"
|
|
IFS="." read -r -a GO_VERSION_REQ <<< "$GO_VERSION_MIN"
|
|
|
|
if [[ ${GO_VERSION_ARR[0]} -lt ${GO_VERSION_REQ[0]} ||
|
|
( ${GO_VERSION_ARR[0]} -eq ${GO_VERSION_REQ[0]} &&
|
|
( ${GO_VERSION_ARR[1]} -lt ${GO_VERSION_REQ[1]} ||
|
|
( ${GO_VERSION_ARR[1]} -eq ${GO_VERSION_REQ[1]} && ${GO_VERSION_ARR[2]} -lt ${GO_VERSION_REQ[2]} )))
|
|
]]; then
|
|
echo "Vault requires go $GO_VERSION_MIN to build; found $GO_VERSION."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "--> Using go version $GO_VERSION..."
|
|
}
|
|
|
|
# Download all the modules for all go.mod's defined in the project.
|
|
mod_download() {
|
|
while IFS= read -r -d '' mod; do
|
|
echo "==> Downloading Go modules for $mod to $(go env GOMODCACHE)..."
|
|
pushd "$(dirname "$mod")" > /dev/null || (echo "failed to push into module dir" && exit 1)
|
|
GOOS=linux GOARCH=amd64 GOPRIVATE=github.com/hashicorp go mod download -x
|
|
popd > /dev/null || (echo "failed to pop out of module dir" && exit 1)
|
|
done < <(find . -type f -name go.mod -not -path "./tools/pipeline/*" -print0 )
|
|
}
|
|
|
|
# Tidy all the go.mod's defined in the project.
|
|
mod_tidy() {
|
|
while IFS= read -r -d '' mod; do
|
|
echo "==> Tidying $mod..."
|
|
pushd "$(dirname "$mod")" > /dev/null || (echo "failed to push into module dir" && exit 1)
|
|
GOOS=linux GOARCH=amd64 GOPRIVATE=github.com/hashicorp go mod tidy
|
|
popd > /dev/null || (echo "failed to pop out of module dir" && exit 1)
|
|
done < <(find . -type f -name go.mod -print0)
|
|
}
|
|
|
|
main() {
|
|
case $1 in
|
|
mod-download)
|
|
mod_download
|
|
;;
|
|
mod-tidy)
|
|
mod_tidy
|
|
;;
|
|
check-fmt)
|
|
check_fmt "${@:2}"
|
|
;;
|
|
check-version)
|
|
check_version "$2"
|
|
;;
|
|
*)
|
|
echo "unknown sub-command" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|