From 800e88942bf00335b61cc3bbebb2ddf935a1601e Mon Sep 17 00:00:00 2001 From: joelei Date: Sat, 6 Dec 2025 21:07:42 +0800 Subject: [PATCH] add cli --- .golangci.yml | 125 +++++++++++++++++++++++++++----------------------- Makefile | 67 +++++++++++++-------------- cli/cli.go | 57 +++++++++++++++++++++++ go.mod | 3 ++ go.sum | 9 ++++ 5 files changed, 168 insertions(+), 93 deletions(-) create mode 100644 cli/cli.go diff --git a/.golangci.yml b/.golangci.yml index b8f21dc..6f07cbc 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,85 +1,96 @@ -# Code generated by gen-lint. DO NOT EDIT. +version: "2" run: timeout: 5m + # tests: false # 过滤_test.go文件 + build-tags: + - goexperiment.jsonv2 issues: # 显示所有 issue max-issues-per-linter: 0 max-same-issues: 0 - exclude-use-default: false + +formatters: + # 必须在enable打开才能用 + enable: + - gofmt + - gci + + settings: + gci: + sections: + - standard + - default + - prefix(git.ifooth.com/common/pkg) + custom-order: true linters: - disable-all: true enable: # enable by default - errcheck - - gosimple - govet - ineffassign - staticcheck - unused # custom - - gci - goconst - - gofmt - goheader - - goimports - gosec - misspell - nakedret - revive - unconvert - unparam + - modernize -linters-settings: - # 只开启特定的规则 - errcheck: - exclude-functions: - - (*os.File).Close - - (io.Closer).Close - - (net/http.ResponseWriter).Write - - io.Copy - - os.RemoveAll - govet: - enable: - - shadow - goimports: - local-prefixes: git.ifooth.com/common/pkg - gci: - sections: - - standard - - default - - prefix(git.ifooth.com/common/pkg) - gosec: - includes: - - G201 # SQL query construction using format string - - G202 # SQL query construction using string concatenation - - G101 # Look for hard coded credentials - - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - - G402 # Look for bad TLS connection settings - - G403 # Ensure minimum RSA key length of 2048 bits - - G404 # Insecure random number source (rand) - - G504 # Import blocklist: net/http/cgi - misspell: - locale: US - revive: - rules: - - name: line-length-limit - arguments: - - 160 - - name: function-length - arguments: - - 80 # statements - - 120 # lines - - name: cyclomatic - arguments: - - 30 - - name: use-any - - name: early-return - - name: exported - arguments: - - checkPrivateReceivers - - sayRepetitiveInsteadOfStutters - - name: package-comments + # 忽略特定错误 + # exclusions: + # rules: + # - linters: + # - govet + # text: 'shadow: declaration of "err" shadows declaration' + + settings: + # 只开启特定的规则 + errcheck: + exclude-functions: + - (*os.File).Close + - (io.Closer).Close + - (net/http.ResponseWriter).Write + - io.Copy + - os.RemoveAll + govet: + enable: + - shadow + gosec: + includes: + - G201 # SQL query construction using format string + - G202 # SQL query construction using string concatenation + - G101 # Look for hard coded credentials + - G401 # Detect the usage of DES, RC4, MD5 or SHA1 + - G402 # Look for bad TLS connection settings + - G403 # Ensure minimum RSA key length of 2048 bits + - G504 # Import blocklist: net/http/cgi + misspell: + locale: US + revive: + rules: + - name: line-length-limit + arguments: + - 120 + - name: function-length + arguments: + - 80 # statements + - 80 # lines + - name: cyclomatic + arguments: + - 20 + - name: use-any + - name: early-return + - name: exported + arguments: + - checkPrivateReceivers + - sayRepetitiveInsteadOfStutters + - name: package-comments diff --git a/Makefile b/Makefile index fed18c6..5d858a3 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,7 @@ -PREFIX ?= $(shell pwd)/bin/ -GO ?= go -FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) -GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) -GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) +GOBUILD = GOEXPERIMENT=jsonv2 CGO_ENABLED=0 go build -trimpath +PREFIX ?= $(shell pwd) BUILDTIME = ${shell TZ=Asia/Shanghai date +%Y-%m-%dT%H:%M:%S%z} -GOBUILD = CGO_ENABLED=0 go build -trimpath - -export GOBIN=${PREFIX}/.bin -# protoc v4.22.0 -export PROTOC_VERSION=22.0 +BUILD_PATH = ${PREFIX}/build ifdef VERSION VERSION=${VERSION} @@ -22,46 +15,48 @@ else GITCOMMIT=$(shell git rev-parse HEAD) endif +# Go Debug Build +ifdef DEBUG_BUILD + GOBUILD=CGO_ENABLED=0 go build -gcflags=all="-N -l" +endif + # Go Reproducible Build ifdef REPRODUCIBLE_BUILD GOBUILD=CGO_ENABLED=0 go build -trimpath -ldflags=-buildid= BUILDTIME=0 endif -LDFLAG=-ldflags "-X github.com/ifooth/apollo/pkg/version.Version=${VERSION} \ - -X github.com/ifooth/apollo/pkg/version.GitCommit=${GITCOMMIT} \ - -X github.com/ifooth/apollo/pkg/version.BuildTime=${BUILDTIME}" +LDFLAG=-ldflags "-X git.ifooth.com/common/pkg/version.Version=${VERSION} \ + -X git.ifooth.com/common/pkg/version.GitCommit=${GITCOMMIT} \ + -X git.ifooth.com/common/pkg/version.BuildTime=${BUILDTIME}" -.PHONY: ini -init: - @echo Download protoc - @mkdir -p ${PREFIX}/.bin - @cd ${PREFIX}/.bin && \ - rm -rf protoc-*.zip* && \ - wget -q https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip && \ - unzip -o protoc-${PROTOC_VERSION}-linux-x86_64.zip && \ - mv -f bin/protoc . && \ - rm -rf protoc-*.zip* readme.txt bin - go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1 - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 - go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.15.2 - go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.15.2 - go install github.com/swaggo/swag/cmd/swag@v1.8.10 +# 逃逸分析 +GCFLAG=-gcflags="" +ifdef GO_GCFLAG + GCFLAG=-gcflags="${GO_GCFLAG}" +endif -.PHONY: tidy -tidy: - @go mod tidy +.PHONY: +lint: + @echo ">> linting" + GOEXPERIMENT=jsonv2 golangci-lint fmt + GOEXPERIMENT=jsonv2 golangci-lint run ./... .PHONY: test test: - @echo ">> test not support" + GOEXPERIMENT=jsonv2 go test -count=1 -cover ./... .PHONY: benchmark benchmark: @echo ">> benchmark not support" -.PHONY: swagger -swagger: - @swag init --outputTypes go,json -g pkg/apis/routes.go --exclude ./ - @swag fmt -g pkg/apis/routes.go --exclude ./ +.PHONY: build +build: + @echo ">> rebuilding binaries" + ${GOBUILD} ${LDFLAG} ${GCFLAG} -o ./bin/ai ./main.go + +.PHONY: docker +docker: build + @docker build -t ccr.ccs.tencentyun.com/ifooth/ifooth-ai:latest . + @docker push ccr.ccs.tencentyun.com/ifooth/ifooth-ai:latest diff --git a/cli/cli.go b/cli/cli.go new file mode 100644 index 0000000..6737020 --- /dev/null +++ b/cli/cli.go @@ -0,0 +1,57 @@ +// Package cli provides the common boilerplate code around executing a cobra command. +package cli + +import ( + "context" + "errors" + "fmt" + "os" + "os/signal" + "syscall" + + "git.ifooth.com/common/pkg/version" + "github.com/spf13/cobra" +) + +var ( + // SignalChan ... + SignalChan = make(chan os.Signal, 1) + // ErrSignal ... + ErrSignal = errors.New("signal") +) + +// Run provides the common boilerplate code around executing a cobra command. +func Run(cmd *cobra.Command) int { + // 不开启 自动排序 + cobra.EnableCommandSorting = false + cmd.CompletionOptions.DisableDefaultCmd = true + cmd.SilenceErrors = true + cmd.SilenceUsage = true + + // 添加版本 + cmd.SetVersionTemplate(`{{println .Version}}`) + cmd.Version = version.GetVersion() + + if err := execute(cmd); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + return 1 + } + + return 0 +} + +func execute(cmd *cobra.Command) error { + ctx := context.Background() + // graceful shutdown signal + signal.Notify(SignalChan, syscall.SIGINT, syscall.SIGTERM) + + err := cmd.ExecuteContext(ctx) + if err == nil { + return nil + } + + if errors.Is(err, ErrSignal) { + return nil + } + return err +} diff --git a/go.mod b/go.mod index cc5784c..e92a837 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/prometheus/client_golang v1.14.0 github.com/redis/go-redis/v9 v9.0.3 github.com/samber/lo v1.47.0 + github.com/spf13/cobra v1.10.2 github.com/stretchr/testify v1.9.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 ) @@ -32,6 +33,7 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/labstack/echo/v4 v4.12.0 // indirect github.com/labstack/gommon v0.4.2 // indirect @@ -44,6 +46,7 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/spf13/pflag v1.0.9 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect go.opentelemetry.io/otel v1.27.0 // indirect diff --git a/go.sum b/go.sum index b915930..4cc0f35 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,7 @@ github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -89,8 +92,13 @@ github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDO 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -105,6 +113,7 @@ go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0 go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=