diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..19818e4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +--- +name: CI +on: [push] + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: v1.31 + env: + VERBOSE: "true" + + tidy: + name: Tidy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - name: Check if mods are tidy + run: make check-tidy + + cov: + name: Code coverage + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - name: Publish coverage + uses: paambaati/codeclimate-action@v2.7.4 + with: + coverageCommand: make cov + prefix: github.com/${{ github.repository }} + coverageLocations: | + ${{ github.workspace }}/coverage.out:gocov + env: + VERBOSE: "true" + GOMAXPROCS: 4 + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - name: Run tests + run: make test + env: + VERBOSE: "true" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72bb60a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/* +coverage.out +tools/bin/* diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..14b06be --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,75 @@ +linters-settings: + funlen: + lines: 100 + statements: 150 + gocyclo: + min-complexity: 20 + golint: + min-confidence: 0 + govet: + check-shadowing: true + enable-all: true + lll: + line-length: 80 + tab-width: 4 + maligned: + suggest-new: true + misspell: + locale: US + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dupl + - errcheck + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - goimports + - golint + - goprintffuncname + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - nlreturn + - noctx + - nolintlint + - scopelint + - sqlclosecheck + - staticcheck + - structcheck + - typecheck + - unconvert + - unused + - varcheck + - whitespace + +issues: + exclude: + - Using the variable on range scope `tt` in function literal + - Using the variable on range scope `tc` in function literal + exclude-rules: + - path: "_test\\.go" + linters: + - funlen + - source: "^//go:generate " + linters: + - lll + - source: "`json:" + linters: + - lll + +run: + timeout: 2m + allow-parallel-runners: true + modules-download-mode: readonly diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8ab6b05 --- /dev/null +++ b/Makefile @@ -0,0 +1,154 @@ +NAME := conver +ROOT := $(CURDIR) +SOURCES := $(shell find . -name "*.go" -or -name "go.mod" -or -name "go.sum" \ + -or -name "Makefile") + +# Verbose output +ifdef VERBOSE +V = -v +endif + +# +# Environment +# + +BINDIR := bin +TOOLDIR := tools/bin + +# Global environment variables for all targets +SHELL ?= /bin/bash +SHELL := env \ + GO111MODULE=on \ + GOBIN=$(CURDIR)/$(TOOLDIR) \ + CGO_ENABLED=1 \ + PATH='$(CURDIR)/$(BINDIR):$(CURDIR)/$(TOOLDIR):$(PATH)' \ + $(SHELL) + +# +# Defaults +# + +# Default target +.DEFAULT_GOAL := build + +.PHONY: all +all: lint test build + +# +# Tools +# + +TOOLS += $(TOOLDIR)/gobin +gobin: $(TOOLDIR)/gobin +$(TOOLDIR)/gobin: + GO111MODULE=off go get -u github.com/myitcv/gobin + +# external tool +define tool # 1: binary-name, 2: go-import-path +TOOLS += $(TOOLDIR)/$(1) + +.PHONY: $(1) +$(1): $(TOOLDIR)/$(1) + +$(TOOLDIR)/$(1): $(TOOLDIR)/gobin Makefile + gobin $(V) "$(2)" +endef + +$(eval $(call tool,gofumports,mvdan.cc/gofumpt/gofumports)) +$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.31)) + +.PHONY: tools +tools: $(TOOLS) + +# +# Build +# + +BINARY=$(BINDIR)/$(NAME) +LDFLAGS := -w -s + +VERSION ?= $(shell git describe --tags 2>/dev/null) +GIT_SHA ?= $(shell git rev-parse --short HEAD 2>/dev/null) +DATE ?= $(shell date +%s) + +ifeq ($(trim $(VERSION)),) + VERSION = dev +endif + +.PHONY: build +build: $(BINARY) + +$(BINARY): $(SOURCES) + go build $(V) -a -o "$@" -ldflags "$(LDFLAGS) \ + -X main.Version=$(VERSION) \ + -X main.Commit=$(GIT_SHA) \ + -X main.Date=$(DATE)" + +# +# Development +# + +.PHONY: clean +clean: + rm -rf $(BINS) $(TOOLS) + rm -f ./coverage.out ./go.mod.tidy-check ./go.sum.tidy-check + +.PHONY: test +test: + go test $(V) -count=1 --race ./... + +.PHONY: lint +lint: $(TOOLS) + $(info Running Go linters) + GOGC=off golangci-lint $(V) run + +.PHONY: format +format: gofumports + gofumports -w . + +# +# Coverage +# + +.PHONY: cov +cov: coverage.out + +.PHONY: cov-html +cov-html: coverage.out + go tool cover -html=coverage.out + +.PHONY: cov-func +cov-func: coverage.out + go tool cover -func=coverage.out + +coverage.out: $(SOURCES) + go test $(V) -covermode=count -coverprofile=coverage.out ./... + +# +# Dependencies +# + +.PHONY: deps +deps: + $(info Downloading dependencies) + go mod download + +.PHONY: tidy +tidy: + go mod tidy $(V) + +.PHONY: verify +verify: + go mod verify + +.SILENT: check-tidy +.PHONY: check-tidy +check-tidy: + cp go.mod go.mod.tidy-check + cp go.sum go.sum.tidy-check + go mod tidy + -diff go.mod go.mod.tidy-check + -diff go.sum go.sum.tidy-check + -rm -f go.mod go.sum + -mv go.mod.tidy-check go.mod + -mv go.sum.tidy-check go.sum diff --git a/main.go b/main.go index 383963b..958ba21 100644 --- a/main.go +++ b/main.go @@ -4,9 +4,12 @@ import ( "bytes" "errors" "flag" + "fmt" "html/template" "io/ioutil" "log" + "os" + "strconv" "strings" "time" @@ -28,6 +31,12 @@ const changelogTemplate = ` {{ end }} ` +var ( + Version string + Commit string + Date string +) + type ( config struct { // action @@ -49,6 +58,8 @@ type ( // changelog config ChangelogUpdate bool `flag:"changelog-update" desc:"Update changelog"` ChangelogPath string `flag:"changelog-path" desc:"Changelog file path"` + + PrintVersion bool `flag:"version" desc:"print version"` } changelogEntry struct { Version string @@ -374,7 +385,7 @@ func changelogUpdate(c *config) error { mergedBody := append(newBody.Bytes(), changelogBody...) // and update file - return ioutil.WriteFile(c.ChangelogPath, mergedBody, 0644) + return ioutil.WriteFile(c.ChangelogPath, mergedBody, 0o644) } func fileUpdate(c *config) error { @@ -394,7 +405,7 @@ func fileUpdate(c *config) error { if err != nil { return err } - return ioutil.WriteFile(c.FilePath, []byte(newVersion), 0644) + return ioutil.WriteFile(c.FilePath, []byte(newVersion), 0o644) } func bumpAtLeastMinor(c *config) error { @@ -423,6 +434,16 @@ func bumpVersion(currentVersion string, c *config) (string, error) { return c.VersionPrefix + cleanNewVersion.String(), nil } +func printVersion() { + if Date != "" { + ts, err := strconv.Atoi(Date) + if err == nil { + Date = time.Unix(int64(ts), 0).UTC().String() + } + } + fmt.Printf("conver %s (%s, %s)\n", Version, Commit, Date) +} + func main() { c := &config{ FilePath: "VERSION", @@ -435,6 +456,11 @@ func main() { } flag.Parse() + if c.PrintVersion { + printVersion() + os.Exit(0) + } + actions := []func(*config) error{ autodetectBump, bumpAtLeastMinor,