Skip to content

Instantly share code, notes, and snippets.

@jstangroome
Created September 5, 2024 04:51
Show Gist options
  • Save jstangroome/ed4f131039cd0c78ac420a5c47f23bbf to your computer and use it in GitHub Desktop.
Save jstangroome/ed4f131039cd0c78ac420a5c47f23bbf to your computer and use it in GitHub Desktop.
Upgrade Go modules with Dockerfile builds
#!/bin/bash
set -o errexit
# Assumes the latest version of Go is installed on the PATH.
# Finds all go.mod files under the current working directory and upgrades the
# Go modules to the latest version of Go and upgrades all their Go dependencies
# too.
# Then finds the Dockerfile in the go.mod file's parent directory and updates
# the "FROM golang" line to the latest version of Go and also updates the "RUN"
# line that installs golangci-lint to use the latest version of that tool.
find_golangci_lint_version () {
curl -sL \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/golangci/golangci-lint/releases \
| grep -m1 -Eo 'https://api\.github\.com/repos/golangci/golangci-lint/tarball/v[^"]*' \
| cut -d'/' -f8
}
process_dockerfile () {
local dockerfile="$1"
printf 'Processing %s...\n' "${dockerfile}"
# Set FROM golang line to new golang version
sed -E -e 's/^FROM\s+golang:\S+/FROM golang:'"${GO_VERSION}"'/i' -i "${dockerfile}"
# Ensure golangci-lint install is done on one lint
sed -E -e '\,^RUN\s.*golangci-lint/master/install\.sh\s*\|\s*\\$,{N;s,\s*\\\n\s*, ,}' -i "${dockerfile}"
# Set golangci-lint install to new version
sed -E -e 's,^(RUN\s.*golangci-lint/master/install\.sh\s*\|\s*sh\s.*\s)v[0-9\.]+\s*$,\1'"${GOLANGCI_LINT_VERSION}"',' -i "${dockerfile}"
}
process_go_mod () {
local go_mod="$1" app_dir dockerfile
app_dir=$(dirname "${go_mod}")
printf 'Processing %s...\n' "${go_mod}"
(
cd "${app_dir}"
go mod download
go mod tidy
go get go@"${GO_VERSION}"
go get -u ./...
go mod tidy
)
dockerfile="${app_dir}/Dockerfile"
if [ ! -s "${dockerfile}" ]; then
dockerfile="${app_dir}/../Dockerfile"
fi
if [ -s "${dockerfile}" ]; then
process_dockerfile "${dockerfile}"
fi
}
main () {
declare -g GO_VERSION GOLANGCI_LINT_VERSION
GO_VERSION=$(
go version \
| awk '/^go version go1/ {print $3}' \
| head -n1 \
| sed 's/^go//'
)
if [ -z "${GO_VERSION}" ]; then
printf 'Local Go version not found. Installed desired version of Go locally.\n' >&2
return 1
fi
GOLANGCI_LINT_VERSION=$(find_golangci_lint_version)
if [ -z "${GOLANGCI_LINT_VERSION}" ]; then
printf 'Latest golangci-lint version not found on GitHub.\n' >&2
return 1
fi
printf 'Searching under %s...\n' "${PWD}"
printf 'Upgrading Go apps to v%s \n' "${GO_VERSION}"
printf 'Upgrading golangci-lint to v%s \n' "${GOLANGCI_LINT_VERSION}"
local go_mod
while IFS= read -d '' -r go_mod; do
process_go_mod "${go_mod}"
done < <(
find . -xdev -type f -name go.mod -print0 | sort -z
)
}
main "$@"
# TODO go install golang.org/x/vuln/cmd/govulncheck@v1.1.3
# TODO RUN go run github.com/google/wire/cmd/wire diff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment