vault/scripts/go-helper.sh
Ryan Cragun 0d8f1d30f3
VAULT-36174: pipeline(go): deal with relative path issues in cache restore (#30650)
* VAULT-36174: pipeline(go): Deal with relative path issues in cache restore

Cache restore have some surprising relative pathing behavior we need
to deal with. Since our Go module cache-path is in $HOME
(/home/runner/go/...) and $HOME can be different depending on our
self-hosted vs Github hosted runners (/home/runner/actions-runner/_work
vs. /home/runner/work) we need to factor in the absolute path of $HOME
when creating our cache key. If we don't then cache restores will be
incompatible on one or the other runner. This is because the tar restore
uses relative paths backwards our our depth doesn't match on both
runners.

We also slightly change our module caches here to only get
`.../mod/cache` instead of the whole `.../mod` directory. Go is able
to unzip the modules in cache faster than it takes a longer download
with the entire mod directory.

This will double our module caches *sigh* but they ought to be smaller
as they only contain the module zips.

See: https://github.com/actions/cache/issues/1127

Signed-off-by: Ryan Cragun <me@ryan.ec>

* use working dir, not home

Signed-off-by: Ryan Cragun <me@ryan.ec>

* fix logic on no-save

Signed-off-by: Ryan Cragun <me@ryan.ec>

* do a module list after download

Signed-off-by: Ryan Cragun <me@ryan.ec>

---------

Signed-off-by: Ryan Cragun <me@ryan.ec>
2025-05-16 12:41:18 -06:00

146 lines
4.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_imports=()
declare -a malformed_formatting=()
local failed=0
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=$(gosimports -d "$file") || [ "$output" != "" ]; then
echo "----> ${file} ✖ (gosimports)"
malformed_imports+=("$file")
failed=1
fi
if ! output=$(gofumpt -l "$file") || [ "$output" != "" ]; then
echo "----> ${file} ✖ (gofumpt)"
malformed_formatting+=("$file")
failed=1
fi
if [ "$failed" == 1 ]; then
continue
fi
fi
echo "----> ${file}"
done
else
echo "--> Checking all files..."
IFS=" " read -r -a malformed_imports <<< "$(find . -name '*.go' | grep -v pb.go | grep -v vendor | xargs gosimports -l | tr '\n' ' ')"
IFS=" " read -r -a malformed_formatting <<< "$(find . -name '*.go' | grep -v pb.go | grep -v vendor | xargs gofumpt -l)"
fi
if [ "${#malformed_imports[@]}" -ne 0 ] && [ -n "${malformed_imports[0]}" ]; then
failed=1
echo "--> The following files need to be reformatted with gosimports"
printf '%s\n' "${malformed_imports[*]}"
echo "Run \`make fmt\` to reformat code."
for file in "${malformed_imports[@]}"; do
gosimports -d "$file"
done
fi
if [ "${#malformed_formatting[@]}" -ne 0 ] && [ -n "${malformed_formatting[0]}" ]; then
failed=1
echo "--> The following files need to be reformatted with gofumpt"
printf '%s\n' "${malformed_formatting[@]}"
echo "Run \`make fmt\` to reformat code."
for file in "${malformed_formatting[@]}"; do
gofumpt -w "$file"
git diff --no-color "$file"
done
fi
if [ $failed == 1 ]; then
return 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
GOOS=linux GOARCH=amd64 GOPRIVATE=github.com/hashicorp go list ./...
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 "$@"