From 8aa21b6444d2c055a4351bc46de5b4fce8f8a717 Mon Sep 17 00:00:00 2001 From: mclacore Date: Tue, 8 Oct 2024 12:50:58 -0700 Subject: [PATCH 1/2] Adding version command * Added supporting packages * Added prettylogs * Updated goreleaser to get version * Updated makefile to add version --- .goreleaser.yaml | 7 ++-- Makefile | 6 ++-- cmd/root.go | 1 + cmd/version.go | 33 +++++++++++++++++++ pkg/prettylogs/main.go | 15 +++++++++ pkg/version/version.go | 66 +++++++++++++++++++++++++++++++++++++ pkg/version/version_test.go | 48 +++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 cmd/version.go create mode 100644 pkg/prettylogs/main.go create mode 100644 pkg/version/version.go create mode 100644 pkg/version/version_test.go diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 1170452..6eceadf 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -13,10 +13,9 @@ builds: goarch: - amd64 - arm64 - # commented these out so i work on implementing them with airlock - # ldflags: &build-ldflags | - # -X github.com/massdriver-cloud/mass/pkg/version.version={{.Version}} - # -X github.com/massdriver-cloud/mass/pkg/version.gitSHA={{.FullCommit}} + ldflags: &build-ldflags | + -X github.com/massdriver-cloud/airlock/pkg/version.version={{.Version}} + -X github.com/massdriver-cloud/airlock/pkg/version.gitSHA={{.FullCommit}} - id: darwin-build binary: airlock diff --git a/Makefile b/Makefile index ebda9fb..64c60a6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ INSTALL_PATH ?= /usr/local/bin +GIT_SHA := $(shell git log -1 --pretty=format:"%H") +LD_FLAGS := "-X github.com/massdriver-cloud/airlock/pkg/version.version=dev -X github.com/massdriver-cloud/airlock/pkg/version.gitSHA=local-dev-${GIT_SHA}" MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) MKFILE_DIR := $(dir $(MKFILE_PATH)) @@ -30,11 +32,11 @@ lint: .PHONY: build.macos build.macos: bin - GOOS=darwin GOARCH=arm64 go build -o bin/airlock-darwin-arm64 + GOOS=darwin GOARCH=arm64 go build -o bin/airlock-darwin-arm64 -ldflags=${LD_FLAGS} .PHONY: build.linux build.linux: bin - GOOS=linux GOARCH=amd64 go build -o bin/airlock-linux-amd64 + GOOS=linux GOARCH=amd64 go build -o bin/airlock-linux-amd64 -ldflags=${LD_FLAGS} .PHONY: install.macos install.macos: build.macos diff --git a/cmd/root.go b/cmd/root.go index 64fec27..4da84a6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -36,6 +36,7 @@ func Execute() { rootCmd.AddCommand(NewCmdHelm()) rootCmd.AddCommand(NewCmdOpenTofu()) rootCmd.AddCommand(NewCmdValidate()) + rootCmd.AddCommand(NewCmdVersion()) if err := rootCmd.Execute(); err != nil { os.Exit(1) } diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000..e5842b9 --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "fmt" + + "github.com/massdriver-cloud/airlock/pkg/prettylogs" + "github.com/massdriver-cloud/airlock/pkg/version" + "github.com/spf13/cobra" +) + +func NewCmdVersion() *cobra.Command { + versionCmd := &cobra.Command{ + Use: "version", + Aliases: []string{"v"}, + Short: "Version of Airlock", + Run: runVersion, + } + return versionCmd +} + +func runVersion(cmd *cobra.Command, args []string) { + latestVersion, err := version.GetLatestVersion() + if err != nil { + fmt.Errorf("could not check for newer version, skipping.\nurl: %s\nerror: %w\n", version.LatestReleaseURL, err) + } + + isOld, _ := version.CheckForNewerVersionAvailable(latestVersion) + if isOld { + fmt.Printf("A newer version of Airlock is available, you can download it here: %v\n", version.LatestReleaseURL) + } + airlockVersion := prettylogs.Green(version.AirlockVersion()) + fmt.Printf("Airlock version: %v (git SHA: %v)\n", airlockVersion, version.AirlockGitSHA()) +} diff --git a/pkg/prettylogs/main.go b/pkg/prettylogs/main.go new file mode 100644 index 0000000..974cb7c --- /dev/null +++ b/pkg/prettylogs/main.go @@ -0,0 +1,15 @@ +package prettylogs + +import "github.com/charmbracelet/lipgloss" + +func Underline(word string) lipgloss.Style { + return lipgloss.NewStyle().SetString(word).Underline(true).Foreground(lipgloss.Color("#7D56f4")) +} + +func Green(word string) lipgloss.Style { + return lipgloss.NewStyle().SetString(word).Foreground(lipgloss.Color("#00FF00")) +} + +func Orange(word string) lipgloss.Style { + return lipgloss.NewStyle().SetString(word).Foreground(lipgloss.Color("#FFA500")) +} diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 0000000..4c8396b --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,66 @@ +package version + +import ( + "context" + "net/http" + "strings" + + "golang.org/x/mod/semver" +) + +const LatestReleaseURL = "https://github.com/massdriver-cloud/airlock/releases/latest" + +var ( + version = "unknown" + gitSHA = "unknown" +) + +func AirlockVersion() string { + return version +} + +func AirlockGitSHA() string { + return gitSHA +} + +func SetVersion(setVersion string) { + version = setVersion +} + +func GetLatestVersion() (string, error) { + ctx := context.Background() + req, reqErr := http.NewRequestWithContext(ctx, http.MethodGet, LatestReleaseURL, nil) + if reqErr != nil { + return "", reqErr + } + + resp, respErr := http.DefaultClient.Do(req) + if respErr != nil { + return "", respErr + } + defer resp.Body.Close() + + redirectURL := resp.Request.URL.String() + parts := strings.Split(redirectURL, "/") + latestVersion := parts[len(parts)-1] + return latestVersion, nil +} + +func CheckForNewerVersionAvailable(latestVersion string) (bool, string) { + currentVersion := version + + // semver requires "v" for version (e.g., v1.0.0 not 1.0.0). Adds "v" if missing + if !strings.HasPrefix(currentVersion, "v") { + currentVersion = "v" + currentVersion + } + + if !strings.HasPrefix(latestVersion, "v") { + latestVersion = "v" + latestVersion + } + + if semver.Compare(currentVersion, latestVersion) < 0 { + return true, latestVersion + } + + return false, latestVersion +} diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go new file mode 100644 index 0000000..49c0882 --- /dev/null +++ b/pkg/version/version_test.go @@ -0,0 +1,48 @@ +package version_test + +import ( + "testing" + + "github.com/massdriver-cloud/airlock/pkg/version" +) + +func TestCheckForNewerVersionAvailable(t *testing.T) { + tests := []struct { + name string + current string + latest string + wantIsOld bool + }{ + { + name: "unknown version should be considered old", + current: "unknown", + latest: "v1.2.0", + wantIsOld: true, + }, + { + name: "current version is the latest version", + current: "1.2.0", + latest: "v1.2.0", + wantIsOld: false, + }, + { + name: "current version is older than the latest version", + current: "1.0.0", + latest: "v1.2.0", + wantIsOld: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + version.SetVersion(tt.current) + + got, latestVersion := version.CheckForNewerVersionAvailable(tt.latest) + if got != tt.wantIsOld { + t.Errorf("CheckForNewerVersionAvailable() got = %v, want %v", got, tt.wantIsOld) + } + if latestVersion != tt.latest { + t.Errorf("CheckForNewerVersionAvailable() latestVersion = %v, want %v", latestVersion, tt.latest) + } + }) + } +} From 69c64e8cd30bebe18458d141ac2cd56949a5e287 Mon Sep 17 00:00:00 2001 From: mclacore Date: Tue, 15 Oct 2024 10:00:05 -0700 Subject: [PATCH 2/2] update makefile, update go.mod --- Makefile | 2 +- go.mod | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 64c60a6..f984e26 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ generate: ${API_DIR}/zz_generated.go .PHONY: test test: - go test ./... -cover + go clean -testcache && go test ./... -cover bin: mkdir bin diff --git a/go.mod b/go.mod index 477e6e8..4cc8a08 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.23.2 require ( github.com/Checkmarx/kics/v2 v2.1.3 github.com/charmbracelet/glamour v0.8.0 + github.com/charmbracelet/lipgloss v0.13.0 github.com/hashicorp/hcl/v2 v2.22.0 github.com/massdriver-cloud/terraform-config-inspect v0.0.1 github.com/spf13/cobra v1.8.1 @@ -14,6 +15,7 @@ require ( github.com/wk8/go-ordered-map/v2 v2.1.8 github.com/xeipuuv/gojsonschema v1.2.0 github.com/zclconf/go-cty v1.15.0 + golang.org/x/mod v0.21.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -26,7 +28,6 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect - github.com/charmbracelet/lipgloss v0.13.0 // indirect github.com/charmbracelet/x/ansi v0.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.11.4 // indirect @@ -55,7 +56,6 @@ require ( github.com/yuin/goldmark-emoji v1.0.3 // indirect golang.org/x/crypto v0.28.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect