diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a280941 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +target/ +.github/ diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b95ae41..194bf84 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,35 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "daily" + interval: daily + open-pull-requests-limit: 2 reviewers: - - "axone-protocol/maintainers" + - amimart + - ccamel + assignees: + - amimart + - ccamel + - package-ecosystem: gomod + directory: / + schedule: + interval: daily + open-pull-requests-limit: 5 + reviewers: + - amimart + - ccamel + assignees: + - amimart + - ccamel + - package-ecosystem: docker + directory: / + schedule: + interval: daily + open-pull-requests-limit: 2 + reviewers: + - amimart + - ccamel + assignees: + - amimart + - ccamel diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f929151 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,30 @@ +name: Build + +on: + workflow_call: + + push: + branches: [main] + + pull_request: + branches: [main] + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-go: + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Setup Go environment + uses: actions/setup-go@v5.0.2 + with: + go-version: '1.22' + + - name: Build go project + run: | + make build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 74f8396..1eaf2e3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -42,6 +42,112 @@ jobs: - name: Lint yaml files uses: ibiqlik/action-yamllint@v3.1.1 + lint-go: + runs-on: ubuntu-22.04 + timeout-minutes: 10 + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Find changed go files + id: changed-go-files + uses: tj-actions/changed-files@v45.0.2 + with: + files: | + **/*.go + go.mod + go.sum + + - name: Setup Go environment + uses: actions/setup-go@v5.0.2 + if: steps.changed-go-files.outputs.any_changed == 'true' + with: + go-version: "1.22" + cache: false + + - name: Lint go code (golangci-lint) + uses: golangci/golangci-lint-action@v6 + if: steps.changed-go-files.outputs.any_changed == 'true' + with: + version: v1.59 + + - name: Lint go code (gofumpt) + if: steps.changed-go-files.outputs.any_changed == 'true' + run: | + go install mvdan.cc/gofumpt@v0.6.0 + if [ "$(gofumpt -l .)" != "" ]; then + echo "❌ Code is not gofumpt!" + exit 1 + fi + echo "βœ… Code is gofumpt!" + + analyze-go: + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Find changed go files + id: changed-go-files + uses: tj-actions/changed-files@v45.0.2 + with: + files: | + **/*.go + go.mod + go.sum + + - name: Setup Go environment + uses: actions/setup-go@v5.0.2 + with: + go-version: "1.22" + cache: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: "go" + + - name: Autobuild project + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + + lint-dockerfile: + runs-on: ubuntu-22.04 + if: github.actor != 'dependabot[bot]' + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Lint dockerfile (hadolint) + uses: hadolint/hadolint-action@v3.1.0 + with: + verbose: true + + lint-shell: + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Lint shell scripts + uses: ludeeus/action-shellcheck@2.0.0 + with: + scandir: . + version: "v0.9.0" + env: + SHELLCHECK_OPTS: -e SC2034 + lint-branch-name: runs-on: ubuntu-22.04 if: github.actor != 'dependabot[bot]' && github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened') diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9a42409 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,49 @@ +name: Publish + +on: + push: + branches: [ main ] + tags: [ "v*" ] + +concurrency: + group: publish-${{ github.ref }} + cancel-in-progress: true + +jobs: + publish-docker-images: + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract metadata (tags, labels) for Docker + id: docker_metadata + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=raw,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }},value=nightly + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + labels: | + org.opencontainers.image.vendor=OKP4 + + - name: Login to Docker registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ secrets.DOCKER_REGISTRY_ID }} + password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + + - name: Build and publish image(s) + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.docker_metadata.outputs.tags }} + labels: ${{ steps.docker_metadata.outputs.labels }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..804d52b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,66 @@ +name: Release + +on: + workflow_dispatch: + +jobs: + lint: + if: github.ref == 'refs/heads/main' && github.actor == 'bot-anik' + uses: ./.github/workflows/lint.yml + + build: + if: github.ref == 'refs/heads/main' && github.actor == 'bot-anik' + uses: ./.github/workflows/build.yml + + test: + if: github.ref == 'refs/heads/main' && github.actor == 'bot-anik' + uses: ./.github/workflows/test.yml + + perfom-release: + if: github.ref == 'refs/heads/main' && github.actor == 'bot-anik' + needs: + - lint + - build + - test + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.OPS_TOKEN }} + + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.BOT_GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }} + git_config_global: true + git_user_signingkey: true + git_commit_gpgsign: true + + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Release project + uses: cycjimmy/semantic-release-action@v4 + with: + semantic_version: 22.0.5 + branch: main + extra_plugins: | + @semantic-release/changelog + @semantic-release/exec + @semantic-release/git + semantic-release-replace-plugin@1.2.7 + extends: | + conventional-changelog-conventionalcommits@7.0.1 + env: + GITHUB_TOKEN: ${{ secrets.OPS_TOKEN }} + GIT_AUTHOR_NAME: ${{ vars.BOT_GIT_AUTHOR_NAME }} + GIT_AUTHOR_EMAIL: ${{ vars.BOT_GIT_AUTHOR_EMAIL }} + GIT_COMMITTER_NAME: ${{ vars.BOT_GIT_COMMITTER_NAME }} + GIT_COMMITTER_EMAIL: ${{ vars.BOT_GIT_COMMITTER_EMAIL }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ee19be0 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test + +on: + workflow_call: + + push: + branches: [main] + + pull_request: + branches: [main] + +concurrency: + group: test-${{ github.ref }} + cancel-in-progress: true + +jobs: + test-go: + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Setup Go environment + uses: actions/setup-go@v5.0.2 + with: + go-version: "1.22" + + - name: Test go project + run: | + make test-go diff --git a/.github/workflows/thank.yml b/.github/workflows/thank.yml new file mode 100644 index 0000000..ba0e81c --- /dev/null +++ b/.github/workflows/thank.yml @@ -0,0 +1,32 @@ +name: Give thanks + +on: + workflow_dispatch: + + push: + branches: [ main ] + +jobs: + give-thanks: + runs-on: ubuntu-22.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Find changed dependencies + id: changed-dependencies + uses: tj-actions/changed-files@v45.0.2 + with: + files: | + go.mod + + - name: Give thanks! + if: steps.changed-dependencies.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch' + run: | + docker run --rm \ + -v $(pwd):/home \ + psampaz/gothanks:v0.4.0 \ + -y \ + -github-token=${{ secrets.OPS_TOKEN }} diff --git a/.gitignore b/.gitignore index 1d74e21..45e4e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ +target/ +.idea/ .vscode/ +.DS_Store diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..d978a1d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,97 @@ +run: + timeout: 10m +linters: + disable-all: true + enable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - typecheck + - unused + - asciicheck + - bidichk + - bodyclose + - contextcheck + - cyclop + - dupl + - durationcheck + - errname + - errorlint + - exhaustive + - exportloopref + - funlen + - forbidigo + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - goimports + - gomodguard + - goprintffuncname + - gosec + - lll + - makezero + - nakedret + - nestif + - nilerr + - nilnil + - noctx + - prealloc + - predeclared + - promlinter + - revive + - rowserrcheck + - sqlclosecheck + - stylecheck + - tenv + - tparallel + - unconvert + - unparam + - wastedassign + - whitespace + +linters-settings: + cyclop: + max-complexity: 20 + skip-tests: true + funlen: + statements: 65 + godot: + scope: declarations # comments to be checked: `declarations` (default), `toplevel`, or `all` + exclude: + - "this line is used by starport scaffolding .*" + lll: + line-length: 135 +output: + uniq-by-line: false + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + exclude-rules: + - source: "^//\\s*go:generate\\s" + linters: + - lll + - source: "(noinspection|TODO)" + linters: + - godot + - source: "//noinspection" + linters: + - gocritic + - source: "^\\s+if _, ok := err\\.\\([^.]+\\.InternalError\\); ok {" + linters: + - errorlint + - path: "_test\\.go" + linters: + - bodyclose + - revive + - dupl + - funlen + - goconst + - noctx + - unused + - wrapcheck + - lll diff --git a/.releaserc.yml b/.releaserc.yml new file mode 100644 index 0000000..266f436 --- /dev/null +++ b/.releaserc.yml @@ -0,0 +1,69 @@ +branches: + - main + +plugins: + - - "@semantic-release/commit-analyzer" + - preset: conventionalcommits + releaseRules: + - type: build + scope: deps + release: patch + - type: build + scope: deps-dev + release: patch + - type: refactor + release: patch + - type: style + release: patch + - type: ci + release: patch + - type: chore + release: patch + - type: docs + release: patch + - breaking: true + release: major + - - "@semantic-release/release-notes-generator" + - preset: conventionalcommits + - - "@semantic-release/changelog" + - changelogFile: CHANGELOG.md + changelogTitle: "# Axone Jackal auth proxy" + - - "@google/semantic-release-replace-plugin" + - replacements: + - files: [version] + from: ^.+$ + to: ${nextRelease.version} + countMatches: true + results: + - file: version + hasChanged: true + numMatches: 1 + numReplacements: 1 + - - "@semantic-release/exec" + - prepareCmd: | + ./scripts/bump-module.sh + - - "@semantic-release/exec" + - prepareCmd: | + make build-go-all + - - "@semantic-release/github" + - assets: + - name: jackal-auth-proxy_darwin_amd64 + label: Binary - Darwin amd64 + path: "./target/dist/darwin/amd64/jackal-auth-proxy" + - name: jackal-auth-proxy_darwin_arm64 + label: Binary - Darwin arm64 + path: "./target/dist/darwin/arm64/jackal-auth-proxy" + - name: jackal-auth-proxy_linux_amd64 + label: Binary - Linux amd64 + path: "./target/dist/linux/amd64/jackal-auth-proxy" + - name: jackal-auth-proxy_windows_amd64.exe + label: Binary - Windows amd64 + path: "./target/dist/windows/amd64/jackal-auth-proxy.exe" + - - "@semantic-release/git" + - assets: + - CHANGELOG.md + - version + - go.mod + - go.sum + - "**/*.go" + message: "chore(release): perform release ${nextRelease.version}" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..97e432e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +#--- Build stage +FROM golang:1.22-bullseye AS go-builder + +WORKDIR /src + +COPY . /src/ + +RUN make build CGO_ENABLED=0 + +#--- Image stage +FROM alpine:3.20.3 + +COPY --from=go-builder /src/target/dist/jackal-auth-proxy /usr/bin/jackal-auth-proxy + +WORKDIR /opt + +ENTRYPOINT ["/usr/bin/jackal-auth-proxy"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a887197 --- /dev/null +++ b/Makefile @@ -0,0 +1,109 @@ +# β„Ή Freely based on: https://gist.github.com/thomaspoignant/5b72d579bd5f311904d973652180c705 + +# Constants +BINARY_NAME = jackal-auth-proxy +TARGET_FOLDER = target +DIST_FOLDER = $(TARGET_FOLDER)/dist +DOCKER_IMAGE_GOLANG_CI = golangci/golangci-lint:v1.55 + +BINARY := ./${DIST_FOLDER}/${BINARY_NAME} + +# Some colors +COLOR_GREEN = $(shell tput -Txterm setaf 2) +COLOR_YELLOW = $(shell tput -Txterm setaf 3) +COLOR_WHITE = $(shell tput -Txterm setaf 7) +COLOR_CYAN = $(shell tput -Txterm setaf 6) +COLOR_RESET = $(shell tput -Txterm sgr0) + +# Flags +VERSION := $(shell cat version) +COMMIT := $(shell git log -1 --format='%H') +LD_FLAGS = \ + -X axone-protocol/jackal-auth-proxy/internal/version.Name=$(BINARY_NAME) \ + -X axone-protocol/jackal-auth-proxy/internal/version.Version=$(VERSION) \ + -X axone-protocol/jackal-auth-proxy/internal/version.Commit=$(COMMIT) +BUILD_FLAGS := -ldflags '$(LD_FLAGS)' + +# Commands +GO_BUiLD := CGO_ENABLED=0 go build $(BUILD_FLAGS) + +# Environments +ENVIRONMENTS = \ + darwin-amd64 \ + darwin-arm64 \ + linux-amd64 \ + windows-amd64 +ENVIRONMENTS_TARGETS = $(addprefix build-go-, $(ENVIRONMENTS)) + +.PHONY: all lint lint-go build build-go help + +all: help + +## Lint: +lint: lint-go ## Lint all available linters + +lint-go: ## Lint go source code + @echo "${COLOR_CYAN}πŸ” Inspecting go source code${COLOR_RESET}" + @docker run --rm \ + -v `pwd`:/app:ro \ + -w /app \ + ${DOCKER_IMAGE_GOLANG_CI} \ + golangci-lint run -v ./... + +## Build: +build: build-go ## Build all available artefacts (executable, docker image, etc.) + +build-go: ## Build executable for the current environment (default build) + @echo "${COLOR_CYAN} πŸ—οΈ Building project ${COLOR_RESET}${CMD_ROOT}${COLOR_CYAN}${COLOR_RESET} into ${COLOR_YELLOW}${DIST_FOLDER}${COLOR_RESET}" + @$(call build-go,"","",${DIST_FOLDER}/${BINARY_NAME}) + +build-go-all: $(ENVIRONMENTS_TARGETS) ## Build executables for all available environments + +$(ENVIRONMENTS_TARGETS): + @GOOS=$(word 3, $(subst -, ,$@)); \ + GOARCH=$(word 4, $(subst -, ,$@)); \ + FOLDER=${DIST_FOLDER}/$$GOOS/$$GOARCH; \ + if [ $$GOOS = "windows" ]; then \ + EXTENSION=".exe"; \ + fi; \ + FILENAME=$$FOLDER/${BINARY_NAME}$$EXTENSION; \ + echo "${COLOR_CYAN} πŸ—οΈ Building project ${COLOR_RESET}${CMD_ROOT}${COLOR_CYAN} for environment ${COLOR_YELLOW}$$GOOS ($$GOARCH)${COLOR_RESET} into ${COLOR_YELLOW}$$FOLDER${COLOR_RESET}" && \ + $(call build-go,$$GOOS,$$GOARCH,$$FILENAME) + + +## Install: +install: ## Install executable + @echo "${COLOR_CYAN} 🚚 Installing project ${BINARY_NAME}${COLOR_RESET}" + @go install $(BUILD_FLAGS) ${CMD_ROOT} + +## Test: +test: test-go ## Pass all the tests + +test-go: build ## Pass the test for the go source code + @echo "${COLOR_CYAN} πŸ§ͺ Passing go tests${COLOR_RESET}" + @go test -v -covermode=count -coverprofile ./target/coverage.out ./... + +## Help: +help: ## Show this help. + @echo '' + @echo 'Usage:' + @echo ' ${COLOR_YELLOW}make${COLOR_RESET} ${COLOR_GREEN}${COLOR_RESET}' + @echo '' + @echo 'Targets:' + @awk 'BEGIN {FS = ":.*?## "} { \ + if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${COLOR_YELLOW}%-20s${COLOR_GREEN}%s${COLOR_RESET}\n", $$1, $$2} \ + else if (/^## .*$$/) {printf " ${COLOR_CYAN}%s${COLOR_RESET}\n", substr($$1,4)} \ + }' $(MAKEFILE_LIST) + @echo '' + @echo 'This Makefile depends on ${COLOR_CYAN}docker${COLOR_RESET}. To install it, please follow the instructions:' + @echo '- for ${COLOR_YELLOW}macOS${COLOR_RESET}: https://docs.docker.com/docker-for-mac/install/' + @echo '- for ${COLOR_YELLOW}Windows${COLOR_RESET}: https://docs.docker.com/docker-for-windows/install/' + @echo '- for ${COLOR_YELLOW}Linux${COLOR_RESET}: https://docs.docker.com/engine/install/' + +# Build go executable +# $1: operating system (GOOS) +# $2: architecture (GOARCH) +# $3: filename of the executable generated +define build-go + GOOS=$1 GOARCH=$2 $(GO_BUiLD) -o $3 ${CMD_ROOT} +endef diff --git a/README.md b/README.md index 29a391a..02bb626 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,24 @@ -# Template project +# Jackal auth proxy -> Template for [Axone](https://axone.xyz) opensource projects. +> Jackal proxy ensuring authentication and authorization layer based on Axone. -[![lint](https://img.shields.io/github/actions/workflow/status/axone-protocol/template-oss/lint.yml?branch=main&label=lint&style=for-the-badge&logo=github)](https://github.com/axone-protocol/template-oss/actions/workflows/lint.yml) +[![version](https://img.shields.io/github/v/release/axone-protocol/jackal-auth-proxy?style=for-the-badge&logo=github)](https://github.com/axone-protocol/jackal-auth-proxy/releases) +[![lint](https://img.shields.io/github/actions/workflow/status/axone-protocol/jackal-auth-proxy/lint.yml?branch=main&label=lint&style=for-the-badge&logo=github)](https://github.com/axone-protocol/jackal-auth-proxy/actions/workflows/lint.yml) +[![build](https://img.shields.io/github/actions/workflow/status/axone-protocol/jackal-auth-proxy/build.yml?branch=main&label=build&style=for-the-badge&logo=github)](https://github.com/axone-protocol/jackal-auth-proxy/actions/workflows/build.yml) +[![test](https://img.shields.io/github/actions/workflow/status/axone-protocol/jackal-auth-proxy/test.yml?branch=main&label=test&style=for-the-badge&logo=github)](https://github.com/axone-protocol/jackal-auth-proxy/actions/workflows/test.yml) +[![codecov](https://img.shields.io/codecov/c/github/axone-protocol/jackal-auth-proxy?style=for-the-badge&token=6NL9ICGZQS&logo=codecov)](https://codecov.io/gh/axone-protocol/jackal-auth-proxy) [![conventional commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=for-the-badge&logo=conventionalcommits)](https://conventionalcommits.org) -[![contributor covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg?style=for-the-badge)](https://github.com/axone-protocol/.github/blob/main/CODE_OF_CONDUCT.md) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=for-the-badge)](https://github.com/semantic-release/semantic-release) +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg?style=for-the-badge)](https://github.com/axone-protocol/.github/blob/main/CODE_OF_CONDUCT.md) [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg?style=for-the-badge)](https://opensource.org/licenses/BSD-3-Clause) -## You want to get involved? 😍 +## Prerequisites -Please check out Axone health files : +- Be sure you have [Golang](https://go.dev/doc/install) installed. +- [Docker](https://docs.docker.com/engine/install/) as well if you want to use the Makefile. -- [Contributing](https://github.com/axone-protocol/.github/blob/main/CONTRIBUTING.md) -- [Code of conduct](https://github.com/axone-protocol/.github/blob/main/CODE_OF_CONDUCT.md) +## Build + +```sh +make build +``` diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..f2fc854 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,23 @@ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands. +var rootCmd = &cobra.Command{ + Use: "jackal-auth-proxy", + Short: "Jackal connector to the OKP4 chain.", + Long: "Jackal connector to the OKP4 chain.", +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000..0701817 --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "encoding/json" + "strings" + + "github.com/axone-protocol/jackal-auth-proxy/internal/version" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" +) + +const ( + flagLong = "long" + flagOutput = "output" +) + +// NewVersionCommand returns a CLI command to interactively print the application binary version information. +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the application binary version information", + RunE: func(cmd *cobra.Command, _ []string) error { + verInfo := version.NewInfo() + + if long, _ := cmd.Flags().GetBool(flagLong); !long { + cmd.Println(verInfo.Version) + return nil + } + + var ( + bz []byte + err error + ) + + output, _ := cmd.Flags().GetString(flagOutput) + switch strings.ToLower(output) { + case "json": + bz, err = json.Marshal(verInfo) + + default: + bz, err = yaml.Marshal(&verInfo) + } + + if err != nil { + return err + } + + cmd.Println(string(bz)) + return nil + }, +} + +func init() { + rootCmd.AddCommand(versionCmd) + + versionCmd.Flags().Bool(flagLong, false, "Print long version information") + versionCmd.Flags().StringP(flagOutput, "o", "text", "Output format (text|json)") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..669df16 --- /dev/null +++ b/go.mod @@ -0,0 +1,24 @@ +module github.com/axone-protocol/jackal-auth-proxy + +go 1.22.5 + +require ( + github.com/rs/zerolog v1.33.0 + github.com/smartystreets/goconvey v1.8.1 + github.com/spf13/cobra v1.8.1 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/gopherjs/gopherjs v1.17.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jtolds/gls v4.20.0+incompatible // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/smarty/assertions v1.15.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/sys v0.24.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..afb832a --- /dev/null +++ b/go.sum @@ -0,0 +1,51 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..e1c9446 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,37 @@ +package version + +import ( + "fmt" + "runtime" +) + +var ( + Name = "" + Version = "" + Commit = "" +) + +// Info defines the application version information. +type Info struct { + Name string `json:"name" yaml:"name"` + Version string `json:"version" yaml:"version"` + GitCommit string `json:"commit" yaml:"commit"` + GoVersion string `json:"go" yaml:"go"` +} + +func NewInfo() Info { + return Info{ + Name: Name, + Version: Version, + GitCommit: Commit, + GoVersion: fmt.Sprintf("go version %s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH), + } +} + +func (vi Info) String() string { + return fmt.Sprintf(`%s: %s +git commit: %s +%s`, + vi.Name, vi.Version, vi.GitCommit, vi.GoVersion, + ) +} diff --git a/internal/version/version_test.go b/internal/version/version_test.go new file mode 100644 index 0000000..0586aea --- /dev/null +++ b/internal/version/version_test.go @@ -0,0 +1,37 @@ +package version + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestNewInfo(t *testing.T) { + Convey("When summoning a current info object", t, func() { + result := NewInfo() + Convey("Then an info object is returned", func() { + So(result.GoVersion, ShouldStartWith, "go version") + }) + }) +} + +func TestInfoString(t *testing.T) { + Convey("Given an info object", t, func() { + info := new(Info) + info.Name = "jackal-auth-proxy" + info.Version = "0.0" + info.GitCommit = "13245" + info.GoVersion = "go fake version 42" + + Convey("When the object string function is called", func() { + result := info.String() + Convey("Then the result should be an info string", func() { + expected := `jackal-auth-proxy: 0.0 +git commit: 13245 +go fake version 42` + + So(result, ShouldEqual, expected) + }) + }) + }) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..19b95e4 --- /dev/null +++ b/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "os" + + "github.com/axone-protocol/jackal-auth-proxy/cmd" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + + cmd.Execute() +} diff --git a/scripts/bump-module.sh b/scripts/bump-module.sh new file mode 100755 index 0000000..ca2f41b --- /dev/null +++ b/scripts/bump-module.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -eo pipefail + +major_version=$(cut -d. -f1 < version) + +if [ "${major_version}" -gt 1 ]; then + module_name=$(go mod edit -json | jq -r '.Module.Path') + module_name_unversioned=$(echo "${module_name}" | sed -E 's|/v[0-9]+$||') + module_name_versioned="${module_name_unversioned}/v${major_version}" + echo "πŸ”¬ major version detected, updating module path to ${module_name_versioned}" + + go mod edit -module "${module_name_versioned}" + echo "βœ… module name updated to ${module_name_versioned} in go.mod" + + if [ "$(uname)" = "Darwin" ]; then + find . -type f -name "*.go" -exec \ + sed -i '' "s|\"${module_name}|\"${module_name_versioned}|g" {} \; + else + find . -type f -name "*.go" -exec \ + sed -i "s|\"${module_name}|\"${module_name_versioned}|g" {} \; + fi + echo "βœ… packages updated to ${module_name_versioned} in source files" + + echo "🧹 cleaning up go.sum" + go mod tidy +else + echo "πŸ™…version is not greater than 1, no need to update module path" +fi diff --git a/version b/version new file mode 100644 index 0000000..77d6f4c --- /dev/null +++ b/version @@ -0,0 +1 @@ +0.0.0