consul/build-support/scripts/devtools.sh

344 lines
9.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
readonly SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")"
readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions"
source "${SCRIPT_DIR}/functions.sh"
unset CDPATH
set -euo pipefail
usage() {
cat <<-EOF
Usage: ${SCRIPT_NAME} [<options ...>]
Description:
Installs various supporting Go tools.
Options:
-protobuf Just install tools for protobuf.
-lint Just install tools for linting.
-codegen Just install tools for codegen.
-pre-commit Just install pre-commit.
-h | --help Print this help text.
EOF
}
function err_usage {
err "$1"
err ""
err "$(usage)"
}
function main {
while test $# -gt 0
do
case "$1" in
-protobuf )
proto_tools_install
return 0
;;
-lint )
lint_install
return 0
;;
-codegen )
codegen_install
return 0
;;
-pre-commit )
pre_commit_install
return 0
;;
-h | --help )
usage
return 0
;;
esac
done
# ensure these tools are installed
tools_install
}
function proto_tools_install {
local protoc_gen_go_version
local protoc_gen_go_grpc_version
local buf_version
local mog_version
local protoc_go_inject_tag_version
local mockery_version
mockery_version="$(make --no-print-directory print-MOCKERY_VERSION)"
protoc_gen_go_version="$(grep google.golang.org/protobuf go.mod | awk '{print $2}')"
protoc_gen_go_grpc_version="$(make --no-print-directory print-PROTOC_GEN_GO_GRPC_VERSION)"
mog_version="$(make --no-print-directory print-MOG_VERSION)"
protoc_go_inject_tag_version="$(make --no-print-directory print-PROTOC_GO_INJECT_TAG_VERSION)"
buf_version="$(make --no-print-directory print-BUF_VERSION)"
protoc_gen_go_binary_version="$(make --no-print-directory print-PROTOC_GEN_GO_BINARY_VERSION)"
# echo "go: ${protoc_gen_go_version}"
# echo "mog: ${mog_version}"
# echo "tag: ${protoc_go_inject_tag_version}"
install_versioned_tool \
'mockery' \
'github.com/vektra/mockery/v2' \
"${mockery_version}" \
'github.com/vektra/mockery/v2'
install_versioned_tool \
'buf' \
'github.com/bufbuild/buf' \
"${buf_version}" \
'github.com/bufbuild/buf/cmd/buf'
install_versioned_tool \
'protoc-gen-go' \
'google.golang.org/protobuf' \
"${protoc_gen_go_version}" \
'google.golang.org/protobuf/cmd/protoc-gen-go'
install_versioned_tool \
'protoc-gen-go-grpc' \
'google.golang.org/grpc/cmd/protoc-gen-go-grpc' \
"${protoc_gen_go_grpc_version}" \
'google.golang.org/grpc/cmd/protoc-gen-go-grpc'
install_versioned_tool \
protoc-gen-go-binary \
'github.com/hashicorp/protoc-gen-go-binary' \
"${protoc_gen_go_binary_version}" \
'github.com/hashicorp/protoc-gen-go-binary'
install_versioned_tool \
'protoc-go-inject-tag' \
'github.com/favadi/protoc-go-inject-tag' \
"${protoc_go_inject_tag_version}" \
'github.com/favadi/protoc-go-inject-tag'
install_versioned_tool \
'mog' \
'github.com/hashicorp/mog' \
"${mog_version}" \
'github.com/hashicorp/mog'
install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-consul-rate-limit"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-resource-types"
install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-grpc-clone"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-json-shim"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-deepcopy"
return 0
}
function lint_install {
local lint_consul_retry_version
lint_consul_retry_version="$(make --no-print-directory print-LINT_CONSUL_RETRY_VERSION)"
local golangci_lint_version
golangci_lint_version="$(make --no-print-directory print-GOLANGCI_LINT_VERSION)"
local gci_version
gci_version="$(make --no-print-directory print-GCI_VERSION)"
install_versioned_tool \
'lint-consul-retry' \
'github.com/hashicorp/lint-consul-retry' \
"${lint_consul_retry_version}" \
'github.com/hashicorp/lint-consul-retry'
install_unversioned_tool \
'enumcover' \
'github.com/reillywatson/enumcover/cmd/enumcover@master'
install_versioned_tool \
'golangci-lint' \
'github.com/golangci/golangci-lint' \
"${golangci_lint_version}" \
'github.com/golangci/golangci-lint/cmd/golangci-lint'
install_versioned_tool \
'gci' \
'github.com/daixiang0/gci' \
"${gci_version}" \
'github.com/daixiang0/gci'
}
function codegen_install {
deepcopy_install
copywrite_install
}
function deepcopy_install {
local deep_copy_version
deep_copy_version="$(make --no-print-directory print-DEEP_COPY_VERSION)"
install_versioned_tool \
'deep-copy' \
'github.com/globusdigital/deep-copy' \
"${deep_copy_version}" \
'github.com/globusdigital/deep-copy'
}
function copywrite_install {
local copywrite_version
copywrite_version="$(make --no-print-directory print-COPYWRITE_TOOL_VERSION)"
install_versioned_tool \
'copywrite' \
'github.com/hashicorp/copywrite' \
"${copywrite_version}" \
'github.com/hashicorp/copywrite'
}
function pre_commit_install {
# if already installed make sure the hook is also installed
if command -v "pre-commit" &>/dev/null; then
# Not to be confused with installing the tool, this installs
# the git hook locally (.git/hooks/pre-commit) which pre-commit
# uses as a vector to run checks on `git commit`. This hook is
# generated based on the local environment hence not source
# controlled.
pre-commit install
return 0
fi
# Install options based on https://pre-commit.com/#installation
if command -v "brew" &>/dev/null; then
brew install pre-commit && pre-commit install
return 0
fi
# Try python regardless of platform (mac, linux, etc)
if command -v "pip3" &>/dev/null; then
pip3 install pre-commit && pre-commit install
return 0
fi
# Can't disappoint the linux/debian folks
if command -v "apt" &>/dev/null; then
sudo apt-get install -yq pre-commit && pre-commit install
return 0
fi
if [[ "$(uname)" == "Darwin" ]]; then
echo "ERROR: Install homebrew from https://brew.sh/ so that pre-commit (https://pre-commit.com) can be installed."
return 1
fi
echo "ERROR: Install python3 and pip3 so that pre-commit (https://pre-commit.com) can be installed."
return 1
}
function tools_install {
lint_install
proto_tools_install
codegen_install
pre_commit_install
copywrite_install
return 0
}
function install_unversioned_tool {
local command="$1"
local install="$2"
if ! command -v "${command}" &>/dev/null ; then
echo "installing tool: ${install}"
go install "${install}"
else
echo "skipping tool: ${install} (installed)"
fi
return 0
}
function install_versioned_tool {
local command="$1"
local module="$2"
local version="$3"
local installbase="$4"
local should_install=
local install_reason=
local got
local vgot
local vneed
local expect="${module}@${version}"
local install="${installbase}@${version}"
if [[ -z "$version" ]]; then
err "cannot install '${command}' no version selected"
return 1
fi
if [[ "$version" = "@DEV" ]]; then
if ! command -v "${command}" &>/dev/null ; then
err "dev version of '${command}' requested but not installed"
return 1
fi
echo "skipping tool: ${installbase} (using development version)"
return 0
fi
if command -v "${command}" &>/dev/null ; then
mod_line="$(go version -m "$(which "${command}")" | grep '\smod\s')"
act_mod=$(echo "${mod_line}" | awk '{print $2}')
if [[ "$module" != "$act_mod" ]]; then
err "${command} is already installed by module \"${act_mod}\" but should be installed by module \"${module}\". Delete it and re-run to re-install."
return 1
fi
got="$(echo "${mod_line}" | grep "${module}" | awk '{print $2 "@" $3}')"
if [[ "$expect" != "$got" ]]; then
should_install=1
install_reason="upgrade"
fi
# check that they were compiled with the current version of go
set +o pipefail
vgot="$(go version -m $(which "${command}") | head -n 1 | grep -o 'go[0-9.]\+')"
vneed="$(go version | head -n 1 | awk '{print $3}')"
set -o pipefail
if [[ "$vgot" != "$vneed" ]]; then
should_install=1
install_reason="go toolchain upgrade"
fi
else
should_install=1
install_reason="install"
fi
if [[ -n $should_install ]]; then
echo "installing tool (${install_reason}): ${install}"
go install "${install}"
else
echo "skipping tool: ${install} (installed)"
fi
return 0
}
function install_local_protoc_generator {
local src=$1
echo "installing tool $(basename $src) from local source"
pushd -- "$src" > /dev/null
go install
popd > /dev/null
}
main "$@"
exit $?