Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ GOIMPORTS_PKG := github.com/rinchsan/gosimports/cmd/gosimports

GO_BIN := ${GOPATH}/bin
GOIMPORTS_BIN := $(GO_BIN)/gosimports
VERSION_GO_FILE := "version.go"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with standard Makefile practices, it's better to define VERSION_GO_FILE without quotes. The quotes are not necessary here as the value doesn't contain spaces or special characters. The variable will be correctly expanded by make in the release-tag target without them.

VERSION_GO_FILE := version.go


GOBUILD := CGO_ENABLED=0 GO111MODULE=on go build -v
GOINSTALL := CGO_ENABLED=0 GO111MODULE=on go install -v
Expand Down Expand Up @@ -86,6 +87,22 @@ docker-release: docker-release-builder
@if [ "$(tag)" = "" ]; then echo "Must specify tag=<commit_or_tag>!"; exit 1; fi
$(DOCKER_RELEASE_BUILDER) bash release.sh $(tag)

# release-tag: Create a signed Git tag from version.go if valid
# Derives the tag name from version.go, validates that it conforms to
# Semantic Versioning (SemVer), and creates a signed Git tag. Ensures
# the tag matches the version declared in version.go to avoid accidental
# or incorrect releases.
release-tag:
@$(call print, "Adding release tag.")

tag=$$(./scripts/get-git-tag-name.sh ${VERSION_GO_FILE}); \
exit_status=$$?; \
if [ $$exit_status -ne 0 ]; then \
echo "Script encountered an error with exit status $$exit_status."; \
fi; \
echo "Adding git tag: $$tag"; \
git tag -as -m "Tag generated using command \`make release-tag\`." "$$tag";
Comment on lines +98 to +104

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error handling in this recipe can be simplified and made more robust. The current implementation checks the exit status of the script but doesn't stop execution on failure. This leads to subsequent commands like git tag being run with an empty tag, causing a confusing failure message.

By using set -e, the recipe will exit immediately if any command fails, which is the desired behavior here. The get-git-tag-name.sh script already prints descriptive error messages to stderr, so no extra error handling is needed in the Makefile.

	set -e; \
	tag=$$(./scripts/get-git-tag-name.sh ${VERSION_GO_FILE}); \
	echo "Adding git tag: $$tag"; \
	git tag -as -m "Tag generated using command \`make release-tag\`." "$$tag"


rpc:
@$(call print, "Compiling protos.")
cd ./swapserverrpc; ./gen_protos_docker.sh
Expand Down
51 changes: 51 additions & 0 deletions scripts/get-git-tag-name.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

# Derive a git tag name from the version fields defined in the given Go file.

set -e

get_git_tag_name() {
local file_path="$1"

if [ ! -f "$file_path" ]; then
echo "Error: File not found at $file_path" >&2
exit 1
fi

local app_major
app_major=$(grep -oP 'appMajor\s*uint\s*=\s*\K\d+' "$file_path")

local app_minor
app_minor=$(grep -oP 'appMinor\s*uint\s*=\s*\K\d+' "$file_path")

local app_patch
app_patch=$(grep -oP 'appPatch\s*uint\s*=\s*\K\d+' "$file_path")

local app_pre_release
app_pre_release=$(grep -oP 'appPreRelease\s*=\s*"\K([A-Za-z0-9.-]*)' "$file_path")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The script will fail if appPreRelease is not defined in the version file because grep will exit with a non-zero status, and set -e is active. Since a pre-release version is optional for a release, it's better to handle its absence gracefully. You can append || true to the grep command to ensure the script doesn't exit if appPreRelease is not found. In that case, $app_pre_release will be empty, which is handled correctly later in the script.

Suggested change
app_pre_release=$(grep -oP 'appPreRelease\s*=\s*"\K([A-Za-z0-9.-]*)' "$file_path")
app_pre_release=$(grep -oP 'appPreRelease\s*=\s*"\K([A-Za-z0-9.-]*)' "$file_path" || true)


if [ -z "$app_major" ] || [ -z "$app_minor" ] || [ -z "$app_patch" ]; then
echo "Error: Could not parse version constants from $file_path" >&2
exit 1
fi

local tag_name="v${app_major}.${app_minor}.${app_patch}"

if [ -n "$app_pre_release" ]; then
tag_name+="-${app_pre_release}"
fi

echo "$tag_name"
}

file_path="$1"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It's good practice to validate the number of script arguments. This provides a clearer error message to the user if the script is called incorrectly, improving its usability.

Suggested change
file_path="$1"
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <path-to-version-file>" >&2
exit 1
fi
file_path="$1"

echo "Reading version fields from file: $file_path" >&2
tag_name=$(get_git_tag_name "$file_path")
echo "Derived git tag name: $tag_name" >&2

if ! [[ "$tag_name" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "Error: Derived tag \"$tag_name\" is not semver compliant" >&2
exit 1
fi

echo "$tag_name"
Loading