diff --git a/Makefile b/Makefile index cb5d43e02..d7e726df1 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,11 @@ ifeq ($(shell expr $(ACTIVE_GO_VERSION_MINOR) \>= 21), 1) LOOPVARFIX := GOEXPERIMENT=loopvar endif +# GO_VERSION is the Go version used for the release build, docker files, and +# GitHub Actions. This is the reference version for the project. All other Go +# versions are checked against this version. +GO_VERSION = 1.22.5 + GOBUILD := $(LOOPVARFIX) go build -v GOINSTALL := $(LOOPVARFIX) go install -v GOTEST := $(LOOPVARFIX) go test @@ -298,11 +303,27 @@ fmt-check: fmt @$(call print, "Checking fmt results.") if test -n "$$(git status --porcelain)"; then echo "code not formatted correctly, please run `make fmt` again!"; git status; git diff; exit 1; fi -#? lint: Run static code analysis -lint: docker-tools +#? check-go-version-yaml: Verify that the Go version is correct in all YAML files +check-go-version-yaml: + @$(call print, "Checking for target Go version (v$(GO_VERSION)) in YAML files (*.yaml, *.yml)") + ./scripts/check-go-version-yaml.sh $(GO_VERSION) + +#? check-go-version-dockerfile: Verify that the Go version is correct in all Dockerfile files +check-go-version-dockerfile: + @$(call print, "Checking for target Go version (v$(GO_VERSION)) in Dockerfile files (*Dockerfile)") + ./scripts/check-go-version-dockerfile.sh $(GO_VERSION) + +#? check-go-version: Verify that the Go version is correct in all project files +check-go-version: check-go-version-dockerfile check-go-version-yaml + +#? lint-source: Run static code analysis +lint-source: docker-tools @$(call print, "Linting source.") $(DOCKER_TOOLS) golangci-lint run -v $(LINT_WORKERS) +#? lint: Run static code analysis +lint: check-go-version lint-source + #? protolint: Lint proto files using protolint protolint: @$(call print, "Linting proto files.") diff --git a/scripts/check-go-version-dockerfile.sh b/scripts/check-go-version-dockerfile.sh new file mode 100755 index 000000000..303ee42ed --- /dev/null +++ b/scripts/check-go-version-dockerfile.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Function to check if the Dockerfile contains only the specified Go version. +check_go_version() { + local dockerfile="$1" + local required_go_version="$2" + + # Use grep to find lines with 'FROM golang:' + local go_lines=$(grep -i '^FROM golang:' "$dockerfile") + + # Check if all lines have the required Go version. + if [ -z "$go_lines" ]; then + # No Go version found in the file. Skip the check. + return + elif echo "$go_lines" | grep -q -v "$required_go_version"; then + echo "$go_lines" + echo "Error: $dockerfile does not use Go version $required_go_version exclusively." + exit 1 + else + echo "$dockerfile is using Go version $required_go_version." + fi +} + +# Check if the target Go version argument is provided. +if [ $# -eq 0 ]; then + echo "Usage: $0 " + exit 1 +fi + +target_go_version="$1" + +# File paths to be excluded from the check. +exception_list=( + # Exclude the tools Dockerfile as otherwise the linter may need to be + # considered every time the Go version is updated. + "./tools/Dockerfile" +) + +# is_exception checks if a file is in the exception list. +is_exception() { + local file="$1" + for exception in "${exception_list[@]}"; do + if [ "$file" == "$exception" ]; then + return 0 + fi + done + return 1 +} + +# Search for Dockerfiles in the current directory and its subdirectories. +dockerfiles=$(find . -type f -name "*.Dockerfile" -o -name "Dockerfile") + +# Check each Dockerfile +for file in $dockerfiles; do + # Skip the file if it is in the exception list. + if is_exception "$file"; then + echo "Skipping $file" + continue + fi + + check_go_version "$file" "$target_go_version" +done + +echo "All Dockerfiles pass the Go version check for Go version $target_go_version." diff --git a/scripts/check-go-version-yaml.sh b/scripts/check-go-version-yaml.sh new file mode 100755 index 000000000..bd65ffa01 --- /dev/null +++ b/scripts/check-go-version-yaml.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Function to check if the YAML file contains the specified Go version after +# field 'go:'. +check_go_version_yaml() { + local yamlfile="$1" + local required_go_version="$2" + + # Use grep to find lines with 'go:'. The grep exist status is ignored. + local go_lines=$(grep -i '^\s*go:\s*"[0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?"' "$yamlfile" || true) + + # Check if any lines specify the Go version. + if [ -n "$go_lines" ]; then + # Extract the Go version from the file's lines. Example matching strings: + # go: "1.21.0" + local extracted_go_version=$(echo "$go_lines" | sed -n 's/.*go: "\([^"]*\)".*/\1/p') + + # Check if the extracted Go version matches the required version. + if [ "$extracted_go_version" != "$required_go_version" ]; then + echo "Error finding pattern 'go:': $yamlfile specifies Go version '$extracted_go_version', but required version is '$required_go_version'." + exit 1 + else + echo "$yamlfile specifies Go version $required_go_version." + fi + fi +} + +# Function to check if the YAML file contains the specified Go version after +# environment variable 'GO_VERSION:'. +check_go_version_env_variable() { + local yamlfile="$1" + local required_go_version="$2" + + # Use grep to find lines with 'GO_VERSION:'. The grep exist status is + # ignored. + local go_lines=$(grep -i 'GO_VERSION:' "$yamlfile" || true) + + # Check if any lines specify the Go version. + if [ -n "$go_lines" ]; then + # Extract the Go version from the file's lines. Example matching strings: + # GO_VERSION: "1.21.0" + # GO_VERSION: '1.21.0' + # GO_VERSION: 1.21.0 + # GO_VERSION:1.21.0 + # GO_VERSION:1.21.0 + local extracted_go_version=$(echo "$go_lines" | sed -n 's/.*GO_VERSION[: ]*["'\'']*\([0-9.]*\).*/\1/p') + + # Check if the extracted Go version matches the required version. + if [ "$extracted_go_version" != "$required_go_version" ]; then + echo "Error finding pattern 'GO_VERSION:': $yamlfile specifies Go version '$extracted_go_version', but required version is '$required_go_version'." + exit 1 + else + echo "$yamlfile specifies Go version $required_go_version." + fi + fi +} + +# Check if the target Go version argument is provided. +if [ $# -eq 0 ]; then + echo "Usage: $0 " + exit 1 +fi + +target_go_version="$1" + +# Search for YAML files in the current directory and its subdirectories. +yaml_files=$(find . -type f \( -name "*.yaml" -o -name "*.yml" \)) + +# Check each YAML file. +for file in $yaml_files; do + check_go_version_yaml "$file" "$target_go_version" + check_go_version_env_variable "$file" "$target_go_version" +done + +echo "All YAML files pass the Go version check for Go version $target_go_version."