From a68ccbaafb171e0e2097443db930a4178bdd31b5 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 3 Oct 2024 16:58:35 +0300 Subject: [PATCH] Add version flag to output build information Generating the version number before building and embedding it into the executable so that it can be outputted by the following command: `uipath --version` `uipathcli v1.0.0 (windows, amd64)` --- .github/workflows/ci.yaml | 14 ++++- build.ps1 | 12 ++-- build.sh | 12 ++-- commandline/cli.go | 9 +++ commandline/flag_builder.go | 12 ++++ commandline/version_command_handler.go | 30 ++++++++++ publish.sh | 65 +++++----------------- test/version_test.go | 17 ++++++ version.sh | 76 ++++++++++++++++++++++++++ 9 files changed, 182 insertions(+), 65 deletions(-) create mode 100644 commandline/version_command_handler.go create mode 100644 test/version_test.go create mode 100755 version.sh diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fd3c78e..3a6f88d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,6 +7,8 @@ env: jobs: build: runs-on: ubuntu-latest + outputs: + UIPATHCLI_VERSION: ${{ steps.version.outputs.UIPATHCLI_VERSION }} env: CGO_ENABLED: "0" steps: @@ -17,10 +19,16 @@ jobs: with: go-version: '1.22.2' cache: true + - name: Version + id: version + run: | + UIPATHCLI_VERSION=$(./version.sh "$UIPATHCLI_BASE_VERSION") + echo "UIPATHCLI_VERSION=$(echo $UIPATHCLI_VERSION)" >> $GITHUB_ENV + echo "UIPATHCLI_VERSION=$(echo $UIPATHCLI_VERSION)" >> $GITHUB_OUTPUT - name: Install dependencies run: go get . - name: Build - run: go build . + run: go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" . - name: Lint run: | go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 @@ -74,6 +82,8 @@ jobs: needs: build if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest + env: + UIPATHCLI_VERSION: ${{ needs.build.outputs.UIPATHCLI_VERSION }} steps: - name: Checkout uses: actions/checkout@v3 @@ -83,6 +93,6 @@ jobs: name: packages path: build/packages/ - name: Publish - run: ./publish.sh "$UIPATHCLI_BASE_VERSION" + run: ./publish.sh "$UIPATHCLI_VERSION" env: GITHUB_TOKEN: ${{ github.token }} diff --git a/build.ps1 b/build.ps1 index 89bda1a..d216938 100644 --- a/build.ps1 +++ b/build.ps1 @@ -3,21 +3,21 @@ New-Item -ItemType Directory -Force -Path build | out-null Copy-Item README.md -Destination build/README.md Write-Host "Building Linux (amd64) executable" -pwsh -Command { $env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o build/uipath-linux-amd64 } +pwsh -Command { $env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build/uipath-linux-amd64 } Write-Host "Building Windows (amd64) executable" -pwsh -Command { $env:GOOS = "windows"; $env:GOARCH = "amd64"; go build -o build/uipath-windows-amd64.exe } +pwsh -Command { $env:GOOS = "windows"; $env:GOARCH = "amd64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build/uipath-windows-amd64.exe } Write-Host "Building MacOS (amd64) executable" -pwsh -Command { $env:GOOS = "darwin"; $env:GOARCH = "amd64"; go build -o build/uipath-darwin-amd64 } +pwsh -Command { $env:GOOS = "darwin"; $env:GOARCH = "amd64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build/uipath-darwin-amd64 } Write-Host "Building Linux (arm64) executable" -pwsh -Command { $env:GOOS = "linux"; $env:GOARCH = "arm64"; go build -o build/uipath-linux-arm64 } +pwsh -Command { $env:GOOS = "linux"; $env:GOARCH = "arm64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build/uipath-linux-arm64 } Write-Host "Building Windows (arm64) executable" -pwsh -Command { $env:GOOS = "windows"; $env:GOARCH = "arm64"; go build -o build/uipath-windows-arm64.exe } +pwsh -Command { $env:GOOS = "windows"; $env:GOARCH = "arm64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build/uipath-windows-arm64.exe } Write-Host "Building MacOS (arm64) executable" -pwsh -Command { $env:GOOS = "darwin"; $env:GOARCH = "arm64"; go build -o build//uipath-darwin-arm64 } +pwsh -Command { $env:GOOS = "darwin"; $env:GOARCH = "arm64"; go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$env:UIPATHCLI_VERSION" -o build//uipath-darwin-arm64 } Write-Host "Successfully completed" \ No newline at end of file diff --git a/build.sh b/build.sh index 889e0db..22e5da8 100755 --- a/build.sh +++ b/build.sh @@ -6,21 +6,21 @@ mkdir -p build cp README.md build/README.md echo "Building Linux (amd64) executable" -GOOS=linux GOARCH=amd64 go build -o build/uipath-linux-amd64 +GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-linux-amd64 echo "Building Windows (amd64) executable" -GOOS=windows GOARCH=amd64 go build -o build/uipath-windows-amd64.exe +GOOS=windows GOARCH=amd64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-windows-amd64.exe echo "Building MacOS (amd64) executable" -GOOS=darwin GOARCH=amd64 go build -o build/uipath-darwin-amd64 +GOOS=darwin GOARCH=amd64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-darwin-amd64 echo "Building Linux (arm64) executable" -GOOS=linux GOARCH=arm64 go build -o build/uipath-linux-arm64 +GOOS=linux GOARCH=arm64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-linux-arm64 echo "Building Windows (arm64) executable" -GOOS=windows GOARCH=arm64 go build -o build/uipath-windows-arm64.exe +GOOS=windows GOARCH=arm64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-windows-arm64.exe echo "Building MacOS (arm64) executable" -GOOS=darwin GOARCH=arm64 go build -o build/uipath-darwin-arm64 +GOOS=darwin GOARCH=arm64 go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" -o build/uipath-darwin-arm64 echo "Successfully completed" \ No newline at end of file diff --git a/commandline/cli.go b/commandline/cli.go index 01878cd..ddf4029 100644 --- a/commandline/cli.go +++ b/commandline/cli.go @@ -43,6 +43,7 @@ func (c Cli) run(args []string, input utils.Stream) error { flags := NewFlagBuilder(). AddDefaultFlags(false). + AddVersionFlag(). Build() commands, err := CommandBuilder.Create(args) @@ -62,6 +63,14 @@ func (c Cli) run(args []string, input utils.Stream) error { HideVersion: true, HideHelpCommand: true, DisableSliceFlagSeparator: true, + Action: func(context *cli.Context) error { + if context.IsSet(FlagNameVersion) { + handler := newVersionCommandHandler(c.stdOut) + handler.Execute() + return nil + } + return cli.ShowAppHelp(context) + }, } return app.Run(args) } diff --git a/commandline/flag_builder.go b/commandline/flag_builder.go index 03723d0..2835a33 100644 --- a/commandline/flag_builder.go +++ b/commandline/flag_builder.go @@ -20,6 +20,7 @@ const FlagNameFile = "file" const FlagNameIdentityUri = "identity-uri" const FlagNameServiceVersion = "service-version" const FlagNameHelp = "help" +const FlagNameVersion = "version" const FlagValueFromStdIn = "-" const FlagValueOutputFormatJson = "json" @@ -40,6 +41,7 @@ var FlagNamesPredefined = []string{ FlagNameIdentityUri, FlagNameServiceVersion, FlagNameHelp, + FlagNameVersion, } // The FlagBuilder can be used to prepare a list of flags for a CLI command. @@ -75,6 +77,11 @@ func (b *FlagBuilder) AddHelpFlag() *FlagBuilder { return b } +func (b *FlagBuilder) AddVersionFlag() *FlagBuilder { + b.AddFlag(b.versionFlag()) + return b +} + func (b *FlagBuilder) AddServiceVersionFlag(hidden bool) *FlagBuilder { b.AddFlag(b.serviceVersionFlag(hidden)) return b @@ -134,6 +141,11 @@ func (b FlagBuilder) defaultFlags(hidden bool) []*FlagDefinition { } } +func (b FlagBuilder) versionFlag() *FlagDefinition { + return NewFlag(FlagNameVersion, "Display the build version", FlagTypeBoolean). + WithHidden(true) +} + func (b FlagBuilder) serviceVersionFlag(hidden bool) *FlagDefinition { return NewFlag(FlagNameServiceVersion, "Specific service version", FlagTypeString). WithEnvVarName("UIPATH_SERVICE_VERSION"). diff --git a/commandline/version_command_handler.go b/commandline/version_command_handler.go new file mode 100644 index 0000000..f3dd2f0 --- /dev/null +++ b/commandline/version_command_handler.go @@ -0,0 +1,30 @@ +package commandline + +import ( + "fmt" + "io" + "runtime" +) + +// This Version variable is overridden during build time +// by providing the linker flag: +// -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=1.2.3" +var Version = "main" + +// The VersionCommandHandler outputs the build information +// +// Example: +// uipath --version +// +// uipathcli v1.0.0 (windows, amd64) +type versionCommandHandler struct { + StdOut io.Writer +} + +func (h versionCommandHandler) Execute() { + fmt.Fprintf(h.StdOut, "uipathcli %s (%s, %s)\n", Version, runtime.GOOS, runtime.GOARCH) +} + +func newVersionCommandHandler(stdOut io.Writer) *versionCommandHandler { + return &versionCommandHandler{stdOut} +} diff --git a/publish.sh b/publish.sh index 0688890..647c0cf 100755 --- a/publish.sh +++ b/publish.sh @@ -3,8 +3,8 @@ # Publishes a new version of the uipathcli on GitHub # # DESCRIPTION: -# This scripts retrieves the latest tag, increments the -# version and creates a new release on GitHub. +# This scripts publishes a tag with the latest version and +# creates a new release on GitHub. ############################################################ set -o pipefail @@ -22,43 +22,6 @@ declare -a RELEASE_FILES=( "build/packages/uipathcli-darwin-arm64.tar.gz" ) -############################################################ -# Retrieves the latest version by sorting the git tags -# -# Returns: -# The latest git tag -############################################################ -function get_latest_version() -{ - local version_filter="$1" - - git fetch --all --tags --quiet - git tag | sort -V | grep "^$version_filter.*" | tail -1 || echo "$version_filter" -} - -############################################################ -# Increment patch version on the provided semver string -# -# Arguments: -# - The version (semver format, e.g. 1.0.0) -# -# Returns: -# Incremented patch version (e.g. 1.0.1) -############################################################ -function increment_patch_version() -{ - local version="$1" - - local array - local IFS='.'; read -r -a array <<< "$version" - if [ -z "${array[2]}" ]; then - array[2]="0" - else - array[2]=$((array[2]+1)) - fi - echo "$(local IFS='.'; echo "${array[*]}")" -} - ############################################################ # Create new tag and push it to remote # @@ -69,7 +32,7 @@ function create_tag() { local tag_name="$1" - git tag "$tag_name" + git tag "$tag_name" || true git push --tags --quiet } @@ -127,17 +90,17 @@ function upload_release_file() ############################################################ function main() { - local base_version="$1" - local latest_version - local new_version - - latest_version=$(get_latest_version "$base_version") - new_version=$(increment_patch_version "$latest_version") - echo "==================================" - echo "Releasing new version of uipathcli" - echo "Current version is: $latest_version" - echo "Creating new release: $new_version" - echo "==================================" + local new_version="$1" + + if [ -z "${new_version}" ]; then + echo "Please provide the new version to publish!" + exit 1 + fi + + echo "===================================" + echo "Releasing new version of uipathcli:" + echo "$new_version" + echo "===================================" local release_id create_tag "$new_version" diff --git a/test/version_test.go b/test/version_test.go new file mode 100644 index 0000000..db3116b --- /dev/null +++ b/test/version_test.go @@ -0,0 +1,17 @@ +package test + +import ( + "strings" + "testing" +) + +func TestVersionOutput(t *testing.T) { + context := NewContextBuilder(). + Build() + + result := RunCli([]string{"--version"}, context) + + if !strings.HasPrefix(result.StdOut, "uipathcli main") { + t.Errorf("Did not return version information, got: %v", result.StdOut) + } +} diff --git a/version.sh b/version.sh new file mode 100755 index 0000000..ad45510 --- /dev/null +++ b/version.sh @@ -0,0 +1,76 @@ +#! /bin/bash +############################################################ +# Generates the next version to publish +# +# DESCRIPTION: +# This scripts retrieves the latest tag, increments the +# version and creates a new release on GitHub. +############################################################ + +set -o pipefail +set -e + +############################################################ +# Retrieves the latest version by sorting the git tags +# +# Returns: +# The latest git tag +############################################################ +function get_latest_version() +{ + local version_filter="$1" + + git fetch --all --tags --quiet + git tag | sort -V | grep "^$version_filter.*" | tail -1 || echo "$version_filter" +} + +############################################################ +# Increment patch version on the provided semver string +# +# Arguments: +# - The version (semver format, e.g. 1.0.0) +# +# Returns: +# Incremented patch version (e.g. 1.0.1) +############################################################ +function increment_patch_version() +{ + local version="$1" + + local array + local IFS='.'; read -r -a array <<< "$version" + if [ -z "${array[2]}" ]; then + array[2]="0" + else + array[2]=$((array[2]+1)) + fi + echo "$(local IFS='.'; echo "${array[*]}")" +} + +############################################################ +# Create new tag +# +# Arguments: +# - The tag name +############################################################ +function create_tag() +{ + local tag_name="$1" + + git tag "$tag_name" +} + +############################################################ +# Main +############################################################ +function main() +{ + local base_version="$1" + local latest_version + local new_version + + latest_version=$(get_latest_version "$base_version") + new_version=$(increment_patch_version "$latest_version") + echo "$new_version" +} +main "$1"