Compare commits
19 Commits
b243486822
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 123cd38a18 | |||
| f9865168c9 | |||
| 08c1a170dc | |||
| 56848c73fd | |||
| dc05c68ee2 | |||
| e7a65571c8 | |||
| 14ff6977ab | |||
| 3628a7898b | |||
| 04298cad4e | |||
| 8b30e53a69 | |||
| c11139e078 | |||
| ce98e2f482 | |||
| 93917649e6 | |||
| 210ed25805 | |||
| e5be089935 | |||
| 93abb9158d | |||
| 052cd0edf3 | |||
| 0f8d2eb16c | |||
| 18a6569dcc |
@@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.1.0
|
current_version = 1.0.0
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
tag_name = {new_version}
|
tag_name = {new_version}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ steps:
|
|||||||
path: /var/run/docker.sock
|
path: /var/run/docker.sock
|
||||||
settings:
|
settings:
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
tags: 0.1.0
|
tags: 1.0.0
|
||||||
force_tag: true
|
force_tag: true
|
||||||
registry: registry.halfakop.ru
|
registry: registry.halfakop.ru
|
||||||
repo: registry.halfakop.ru/golang/bumpversion
|
repo: registry.halfakop.ru/golang/bumpversion
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
*.run
|
*.run
|
||||||
.env
|
.env
|
||||||
|
.cache
|
||||||
|
|||||||
13
Dockerfile
13
Dockerfile
@@ -1,14 +1,17 @@
|
|||||||
FROM golang:1.24.1-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
ARG SOURCE_VERSION
|
||||||
|
ARG SOURCE_COMMIT
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bumpversion src/main.go
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
||||||
|
-ldflags "-X main.AppVersion=${SOURCE_VERSION} -X main.AppCommit=${SOURCE_COMMIT}" \
|
||||||
FROM alpine/git
|
-o bumpversion ./src
|
||||||
|
|
||||||
|
FROM gcr.io/distroless/static
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
COPY --from=builder /app/bumpversion .
|
COPY --from=builder /app/bumpversion /bumpversion
|
||||||
ENTRYPOINT ["/bumpversion"]
|
ENTRYPOINT ["/bumpversion"]
|
||||||
CMD ["--version"]
|
CMD ["--version"]
|
||||||
|
|||||||
87
Makefile
87
Makefile
@@ -1,21 +1,88 @@
|
|||||||
EXEC=bumpversion.run
|
NAMESPACE ?= golang
|
||||||
|
PACKAGE := bumpversion
|
||||||
|
SHELL := /bin/bash
|
||||||
|
REGISTRY := registry.halfakop.ru
|
||||||
|
REPOSITORY := $(NAMESPACE)/$(PACKAGE)
|
||||||
|
PLATFORM ?= --platform=linux/amd64
|
||||||
|
GOCACHE ?= $(CURDIR)/.cache/go-build
|
||||||
|
|
||||||
all: build
|
SOURCE_VERSION ?= $(shell cat VERSION)
|
||||||
|
SOURCE_COMMIT ?= $(shell git rev-parse --short=8 HEAD)
|
||||||
|
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD | sed s,feature/,,g)
|
||||||
|
LDFLAGS := -X main.AppVersion=$(SOURCE_VERSION) -X main.AppCommit=$(SOURCE_COMMIT)
|
||||||
|
|
||||||
|
IMAGE_NAME_TAGGED = $(REPOSITORY):$(SOURCE_VERSION)
|
||||||
|
EXEC=$(PACKAGE).run
|
||||||
|
|
||||||
|
all: help
|
||||||
|
|
||||||
|
help:
|
||||||
|
@printf "\nMain make targets:\n"
|
||||||
|
@printf " make app - Download deps, fix, build app (binary: %s)\n" "$(EXEC)"
|
||||||
|
@printf " make test - Run unit tests\n"
|
||||||
|
@printf " make test-integration - Run tests that require Postgres (testcontainers)\n"
|
||||||
|
@printf " make run - Build then run locally\n"
|
||||||
|
@printf " make clean - Clean build artifacts\n"
|
||||||
|
@printf " make release - Clean, build image, login, push\n"
|
||||||
|
@printf "\nVariables:\n"
|
||||||
|
@printf " NAMESPACE=%s\n" "$(NAMESPACE)"
|
||||||
|
@printf " PACKAGE=%s\n" "$(PACKAGE)"
|
||||||
|
@printf " IMAGE_NAME_TAGGED=%s\n" "$(IMAGE_NAME_TAGGED)"
|
||||||
|
@printf " EXEC=%s\n\n" "$(EXEC)"
|
||||||
|
|
||||||
|
download:
|
||||||
|
@echo "Download dependencies"
|
||||||
|
@GOCACHE=$(GOCACHE) go mod download
|
||||||
|
|
||||||
fix:
|
fix:
|
||||||
@go fix ./...
|
@echo "Fix code"
|
||||||
|
@GOCACHE=$(GOCACHE) go fix ./...
|
||||||
|
|
||||||
build: fix
|
app: download fix
|
||||||
@go build -o ./${EXEC} ./src
|
@echo "Build application"
|
||||||
|
@GOCACHE=$(GOCACHE) go build -ldflags "$(LDFLAGS)" -o ./${EXEC} ./src
|
||||||
|
|
||||||
tests: build
|
tests: app
|
||||||
@go test ./...
|
@echo "Run tests"
|
||||||
|
@GOCACHE=$(GOCACHE) go test ./...
|
||||||
|
|
||||||
|
test:
|
||||||
|
@echo "Run unit tests"
|
||||||
|
@GOCACHE=$(GOCACHE) go test -count=1 ./...
|
||||||
|
|
||||||
|
test-integration:
|
||||||
|
@echo "Run integration tests (requires Docker for Postgres)"
|
||||||
|
@GOCACHE=$(GOCACHE) go test -tags=integration -count=1 ./...
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
@echo "Run application"
|
||||||
@./${EXEC}
|
@./${EXEC}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf ./${EXEC}%
|
@echo "Clean build environment"
|
||||||
|
@rm -rf ./${EXEC}% $(GOCACHE)
|
||||||
|
|
||||||
image:
|
release: clean build login push
|
||||||
docker build --compress -t rad/bumpversion:latest -f Dockerfile .
|
|
||||||
|
build:
|
||||||
|
DOCKER_BUILDKIT=0 \
|
||||||
|
docker build $(PLATFORM) --progress=plain --compress \
|
||||||
|
-t $(IMAGE_NAME_TAGGED) \
|
||||||
|
-t $(REGISTRY)/$(IMAGE_NAME_TAGGED) \
|
||||||
|
--build-arg SOURCE_VERSION=$(SOURCE_VERSION) \
|
||||||
|
--build-arg SOURCE_COMMIT=$(SOURCE_COMMIT) \
|
||||||
|
--build-arg GOPROXY=$(GOPROXY) \
|
||||||
|
--build-arg GONOSUMDB=$(GONOSUMDB) \
|
||||||
|
${DOCKER_OPTS} \
|
||||||
|
-f Dockerfile .
|
||||||
|
|
||||||
|
login:
|
||||||
|
$(call check-var-defined,DOCKER_USERNAME)
|
||||||
|
$(call check-var-defined,DOCKER_PASSWORD)
|
||||||
|
@echo ${DOCKER_PASSWORD} | \
|
||||||
|
docker login -u ${DOCKER_USERNAME} --password-stdin $(REGISTRY)
|
||||||
|
|
||||||
|
push:
|
||||||
|
docker push $(REGISTRY)/$(IMAGE_NAME_TAGGED)
|
||||||
|
|
||||||
|
.PHONY: tests test test-integration release build login push download fix app clean run help
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# BumpVersion v0.1.0
|
# BumpVersion v1.0.0
|
||||||
|
|
||||||
[](https://drone.halfakop.ru/rad/bumpversion)
|
[](https://drone.halfakop.ru/rad/bumpversion)
|
||||||
|
|
||||||
@@ -6,11 +6,18 @@
|
|||||||
|
|
||||||
## Разработчику
|
## Разработчику
|
||||||
|
|
||||||
|
```bash
|
||||||
export PATH=$PATH:/usr/local/go/bin
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
go mod init src
|
go mod init src
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go build
|
go build
|
||||||
go run .
|
go run .
|
||||||
|
```
|
||||||
|
или
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
## Девопсу
|
## Девопсу
|
||||||
|
|
||||||
|
|||||||
29
go.mod
29
go.mod
@@ -1,7 +1,30 @@
|
|||||||
module src
|
module bumpversion
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
require github.com/go-ini/ini v1.67.0
|
require (
|
||||||
|
github.com/go-git/go-git/v5 v5.14.0
|
||||||
|
github.com/go-ini/ini v1.67.0
|
||||||
|
)
|
||||||
|
|
||||||
require github.com/stretchr/testify v1.10.0 // indirect
|
require (
|
||||||
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
|
github.com/ProtonMail/go-crypto v1.1.5 // indirect
|
||||||
|
github.com/cloudflare/circl v1.6.0 // indirect
|
||||||
|
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||||
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
|
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
|
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||||
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||||
|
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||||
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
|
golang.org/x/crypto v0.35.0 // indirect
|
||||||
|
golang.org/x/net v0.35.0 // indirect
|
||||||
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
)
|
||||||
|
|||||||
94
go.sum
94
go.sum
@@ -1,10 +1,104 @@
|
|||||||
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
|
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
|
||||||
|
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
|
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||||
|
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||||
|
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||||
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
|
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
|
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||||
|
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||||
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||||
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
|
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||||
|
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||||
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
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/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||||
|
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||||
|
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||||
|
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||||
|
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||||
|
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
33
src/build_info.go
Normal file
33
src/build_info.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "runtime/debug"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if AppCommit == "" || AppCommit == "unknown" {
|
||||||
|
if commit := resolveCommitFromBuildInfo(); commit != "" {
|
||||||
|
AppCommit = commit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveCommitFromBuildInfo() string {
|
||||||
|
info, ok := debug.ReadBuildInfo()
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, setting := range info.Settings {
|
||||||
|
if setting.Key == "vcs.revision" && setting.Value != "" {
|
||||||
|
return shortCommit(setting.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func shortCommit(commit string) string {
|
||||||
|
if len(commit) >= 8 {
|
||||||
|
return commit[:8]
|
||||||
|
}
|
||||||
|
return commit
|
||||||
|
}
|
||||||
195
src/git.go
Normal file
195
src/git.go
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
git "github.com/go-git/go-git/v5"
|
||||||
|
"github.com/go-git/go-git/v5/config"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getenvDefault возвращает значение из окружения по ключу, или заданное
|
||||||
|
// по умолчанию
|
||||||
|
func getenvDefault(k, def string) string {
|
||||||
|
if v := os.Getenv(k); v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizePath возвращает нормализованный путь
|
||||||
|
func normalizePath(p string) string {
|
||||||
|
p = strings.TrimSpace(p)
|
||||||
|
p = strings.TrimPrefix(p, "./")
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushRefSpec(headRef *plumbing.Reference) (config.RefSpec, error) {
|
||||||
|
if headRef == nil || !headRef.Name().IsBranch() {
|
||||||
|
return "", fmt.Errorf("cannot determine branch to push from HEAD")
|
||||||
|
}
|
||||||
|
branch := headRef.Name().String()
|
||||||
|
return config.RefSpec(branch + ":" + branch), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signatureFromEnv() *object.Signature {
|
||||||
|
return &object.Signature{
|
||||||
|
Name: getenvDefault("GIT_USERNAME", "bumpversion"),
|
||||||
|
Email: getenvDefault("GIT_EMAIL", "bumpversion@deploy"),
|
||||||
|
When: time.Now().UTC(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// gitCommit выполняет коммит с внесёнными изменениями
|
||||||
|
func gitCommit(bc *BumpConfig, newVersion string, configPath string) {
|
||||||
|
// Открываем локальный репозиторий (предполагается, что он существует в папке ".")
|
||||||
|
repo, err := git.PlainOpen(".")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Repository open error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// получаем рабочее дерево
|
||||||
|
worktree, err := repo.Worktree()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Work directory open error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// создаём список файлов, которые должны быть включены в коммит
|
||||||
|
targets := make([]string, 0, len(bc.FilePaths)+1)
|
||||||
|
targets = append(targets, bc.FilePaths...)
|
||||||
|
targets = append(targets, configPath)
|
||||||
|
|
||||||
|
// проверяем на наличие изменений
|
||||||
|
status, err := worktree.Status()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Status error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
changed := false
|
||||||
|
for _, p := range targets {
|
||||||
|
if p == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p = normalizePath(p)
|
||||||
|
|
||||||
|
// пропускаем отсутствующие файлы тихо
|
||||||
|
if _, err := os.Stat(p); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Printf("Skip missing file: %s", p)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Fatalf("Stat error for %s: %v", p, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
st, ok := status[p]
|
||||||
|
if !ok || st == nil {
|
||||||
|
// nothing to stage for this file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if st.Worktree != git.Unmodified {
|
||||||
|
if _, err := worktree.Add(p); err != nil {
|
||||||
|
log.Fatalf("Add %s error: %v", p, err)
|
||||||
|
}
|
||||||
|
changed = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !changed {
|
||||||
|
log.Printf("No changes detected in configured files; skipping commit.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// формируем сообщение коммита
|
||||||
|
commitMsg := strings.
|
||||||
|
NewReplacer(
|
||||||
|
"{current_version}", bc.CurrentVersion,
|
||||||
|
"{new_version}", newVersion,
|
||||||
|
).Replace(bc.Message)
|
||||||
|
|
||||||
|
author := signatureFromEnv()
|
||||||
|
|
||||||
|
hash, err := worktree.Commit(commitMsg, &git.CommitOptions{
|
||||||
|
Author: author,
|
||||||
|
Committer: author,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Commit error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем объект коммита (по его хэшу)
|
||||||
|
commitObj, err := repo.CommitObject(hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Commit object error: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Committed as %s\n", commitObj.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// gitTag ставит тэг на текущий коммит
|
||||||
|
func gitTag(bc *BumpConfig, newVersion string) {
|
||||||
|
// Открываем локальный репозиторий (предполагается, что он существует в папке ".")
|
||||||
|
repo, err := git.PlainOpen(".")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Repository open error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем текущий HEAD (он должен совпадать с только что созданным коммитом)
|
||||||
|
headRef, err := repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("HEAD open error: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Current HEAD is %s\n", headRef.Hash())
|
||||||
|
|
||||||
|
// Создаем тег на текущем коммите (HEAD)
|
||||||
|
commitMsg := strings.ReplaceAll(bc.Message, "{current_version}", bc.CurrentVersion)
|
||||||
|
commitMsg = strings.ReplaceAll(commitMsg, "{new_version}", newVersion)
|
||||||
|
tagName := strings.ReplaceAll(bc.TagName, "{new_version}", newVersion)
|
||||||
|
_, err = repo.CreateTag(tagName, headRef.Hash(), &git.CreateTagOptions{
|
||||||
|
Tagger: signatureFromEnv(),
|
||||||
|
Message: commitMsg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Tag creation error: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Tag '%s' is created on commit %s\n", tagName, headRef.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitPush(bc *BumpConfig, newVersion string) {
|
||||||
|
// Открываем локальный репозиторий (предполагается, что он существует в папке ".")
|
||||||
|
repo, err := git.PlainOpen(".")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Repository open error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tagName := strings.ReplaceAll(bc.TagName, "{new_version}", newVersion)
|
||||||
|
|
||||||
|
headRef, err := repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("HEAD open error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
branchSpec, err := pushRefSpec(headRef)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Push branch detection error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// (Опционально) Выполняем push на удаленный репозиторий
|
||||||
|
tagSpec := config.RefSpec("refs/tags/" + tagName + ":refs/tags/" + tagName)
|
||||||
|
err = repo.Push(&git.PushOptions{
|
||||||
|
RemoteName: "origin",
|
||||||
|
RefSpecs: []config.RefSpec{
|
||||||
|
branchSpec,
|
||||||
|
tagSpec,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Push error: %v", err)
|
||||||
|
}
|
||||||
|
log.Println("Changes pushed successfully")
|
||||||
|
}
|
||||||
139
src/main.go
139
src/main.go
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -28,7 +27,7 @@ type BumpConfig struct {
|
|||||||
func getBumpConfig(cfg_name string) (*BumpConfig, error) {
|
func getBumpConfig(cfg_name string) (*BumpConfig, error) {
|
||||||
cfg, err := ini.Load(cfg_name)
|
cfg, err := ini.Load(cfg_name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error loading config: %v", err)
|
return nil, fmt.Errorf("error loading config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sec, err := cfg.GetSection("bumpversion")
|
sec, err := cfg.GetSection("bumpversion")
|
||||||
@@ -71,6 +70,7 @@ func bumpVersion(bc *BumpConfig, part string) (string, error) {
|
|||||||
// Создадим карту групп по именам
|
// Создадим карту групп по именам
|
||||||
groupNames := re.SubexpNames()
|
groupNames := re.SubexpNames()
|
||||||
var major, minor, patch int
|
var major, minor, patch int
|
||||||
|
var hasMajor, hasMinor, hasPatch bool
|
||||||
for i, name := range groupNames {
|
for i, name := range groupNames {
|
||||||
switch name {
|
switch name {
|
||||||
case "major":
|
case "major":
|
||||||
@@ -78,18 +78,24 @@ func bumpVersion(bc *BumpConfig, part string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
hasMajor = true
|
||||||
case "minor":
|
case "minor":
|
||||||
minor, err = strconv.Atoi(matches[i])
|
minor, err = strconv.Atoi(matches[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
hasMinor = true
|
||||||
case "patch":
|
case "patch":
|
||||||
patch, err = strconv.Atoi(matches[i])
|
patch, err = strconv.Atoi(matches[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
hasPatch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !hasMajor || !hasMinor || !hasPatch {
|
||||||
|
return "", fmt.Errorf("parse pattern must contain major, minor, and patch groups")
|
||||||
|
}
|
||||||
switch part {
|
switch part {
|
||||||
case "major":
|
case "major":
|
||||||
major++
|
major++
|
||||||
@@ -110,8 +116,8 @@ func bumpVersion(bc *BumpConfig, part string) (string, error) {
|
|||||||
return newVersion, nil
|
return newVersion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateFiles обновляет версию в файле
|
// updateFiles обновляет версию в файле; при fatalIfMissing=true возвращает ошибку, если строка не найдена.
|
||||||
func updateFiles(filePaths []string, oldVersion, newVersion string) {
|
func updateFiles(filePaths []string, oldVersion, newVersion string, fatalIfMissing bool) error {
|
||||||
for _, path := range filePaths {
|
for _, path := range filePaths {
|
||||||
data, err := os.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -119,39 +125,19 @@ func updateFiles(filePaths []string, oldVersion, newVersion string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newData := strings.ReplaceAll(string(data), oldVersion, newVersion)
|
newData := strings.ReplaceAll(string(data), oldVersion, newVersion)
|
||||||
|
if newData == string(data) {
|
||||||
|
log.Printf("Version %s not found in %s; skip update", oldVersion, path)
|
||||||
|
if fatalIfMissing {
|
||||||
|
return fmt.Errorf("version %s not found in %s", oldVersion, path)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err := os.WriteFile(path, []byte(newData), 0644); err != nil {
|
if err := os.WriteFile(path, []byte(newData), 0644); err != nil {
|
||||||
log.Printf("Unable to write file %s: %v", path, err)
|
log.Printf("Unable to write file %s: %v", path, err)
|
||||||
} else {
|
continue
|
||||||
|
}
|
||||||
log.Printf("Updated file: %s", path)
|
log.Printf("Updated file: %s", path)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gitCommit выполняет коммит с внесёнными изменениями
|
|
||||||
func gitCommit(currentVersion, newVersion string, bc *BumpConfig) error {
|
|
||||||
commitMsg := strings.ReplaceAll(bc.Message, "{current_version}", currentVersion)
|
|
||||||
commitMsg = strings.ReplaceAll(commitMsg, "{new_version}", newVersion)
|
|
||||||
if bc.Commit {
|
|
||||||
if err := exec.Command("git", "add", ".").Run(); err != nil {
|
|
||||||
return fmt.Errorf("git add error: %w", err)
|
|
||||||
}
|
|
||||||
if err := exec.Command("git", "commit", "-m", commitMsg).Run(); err != nil {
|
|
||||||
return fmt.Errorf("git commit error: %w", err)
|
|
||||||
}
|
|
||||||
log.Printf("Committed with message: %s", commitMsg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// gitTag ставит тэг на коммит
|
|
||||||
func gitTag(currentVersion, newVersion string, bc *BumpConfig) error {
|
|
||||||
if bc.Tag {
|
|
||||||
tagName := strings.ReplaceAll(bc.TagName, "{new_version}", newVersion)
|
|
||||||
if err := exec.Command("git", "tag", tagName).Run(); err != nil {
|
|
||||||
return fmt.Errorf("git tag error: %w", err)
|
|
||||||
}
|
|
||||||
log.Printf("Created git tag: %s", tagName)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,62 +145,72 @@ func gitTag(currentVersion, newVersion string, bc *BumpConfig) error {
|
|||||||
func updateConfigFile(configPath string, newVersion string) error {
|
func updateConfigFile(configPath string, newVersion string) error {
|
||||||
cfg, err := ini.Load(configPath)
|
cfg, err := ini.Load(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
cfg.Section("bumpversion").Key("current_version").SetValue(newVersion)
|
sec, err := cfg.GetSection("bumpversion")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("section [bumpversion] not found: %w", err)
|
||||||
|
}
|
||||||
|
sec.Key("current_version").SetValue(newVersion)
|
||||||
return cfg.SaveTo(configPath)
|
return cfg.SaveTo(configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveFlag проверяет два логических флага: positive и negative.
|
// resolveFlag проверяет два логических флага: positive и negative.
|
||||||
// Если оба заданы как true, вызывается ошибка; если задан negative, возвращается false;
|
// Если оба заданы как true, вызывается ошибка; если задан negative, возвращается false;
|
||||||
// если задан positive, возвращается true; иначе возвращается defaultValue.
|
// если задан positive, возвращается true; иначе возвращается defaultValue.
|
||||||
func resolveFlag(positive, negative *bool, defaultValue bool) bool {
|
func resolveFlag(positive, negative *bool, defaultValue bool) (bool, error) {
|
||||||
if *positive && *negative {
|
if *positive && *negative {
|
||||||
// Если оба флага заданы, это противоречивое состояние.
|
return false, fmt.Errorf("conflicting flags: both positive and negative are set")
|
||||||
// Здесь можно завершить программу с ошибкой или выбрать приоритет.
|
|
||||||
// Например, завершим выполнение:
|
|
||||||
panic("conflicting flags: both positive and negative are set")
|
|
||||||
}
|
}
|
||||||
if *negative {
|
if *negative {
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
if *positive {
|
if *positive {
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Версия приложения
|
// Версия приложения
|
||||||
const (
|
const AppName = "BumpVersion"
|
||||||
AppName = "BumpVersion"
|
|
||||||
AppVersion = "0.1.0"
|
var (
|
||||||
|
AppVersion = "1.0.0"
|
||||||
|
AppCommit = "unknown"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func versionString() string {
|
||||||
|
if AppCommit == "" || AppCommit == "unknown" {
|
||||||
|
return AppVersion
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s (%s)", AppVersion, AppCommit)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
const cfg_name = ".bumpversion.cfg"
|
const cfg_name = ".bumpversion.cfg"
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
// Проверяем аргументы командной строки
|
// Проверяем аргументы командной строки
|
||||||
if len(args) > 0 && strings.ToLower(args[0]) == "--version" {
|
if len(args) > 0 && strings.ToLower(args[0]) == "--version" {
|
||||||
fmt.Printf("%s version %s\n", AppName, AppVersion)
|
fmt.Printf("%s version %s\n", AppName, versionString())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Печатаем название и версию при старте
|
// Печатаем название и версию при старте
|
||||||
fmt.Printf("Starting %s version %s\n", AppName, AppVersion)
|
fmt.Printf("Starting %s version %s\n", AppName, versionString())
|
||||||
|
|
||||||
bc, err := getBumpConfig(cfg_name)
|
bc, err := getBumpConfig(cfg_name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error reading bumpversion configuration: %v", err)
|
log.Fatalf("Error reading bumpversion configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Current version: %s\n", bc.CurrentVersion)
|
|
||||||
|
|
||||||
// Парсинг аргументов командной строки
|
// Парсинг аргументов командной строки
|
||||||
part := flag.String("part", "patch", "Part of the version to bump (major/minor/patch)")
|
part := flag.String("part", "patch", "Part of the version to bump (major/minor/patch)")
|
||||||
commit := flag.Bool("commit", false, "Create a commit")
|
commit := flag.Bool("commit", false, "Create a commit")
|
||||||
noCommit := flag.Bool("no-commit", false, "Do not create a commit")
|
noCommit := flag.Bool("no-commit", false, "Do not create a commit")
|
||||||
tag := flag.Bool("tag", false, "Add a git tag")
|
tag := flag.Bool("tag", false, "Add a git tag")
|
||||||
noTag := flag.Bool("no-tag", false, "Do not add a git tag")
|
noTag := flag.Bool("no-tag", false, "Do not add a git tag")
|
||||||
|
noFatal := flag.Bool("no-fatal", false, "Do not fail if a configured file does not contain the current version")
|
||||||
|
push := flag.Bool("push", false, "Force push to repository")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Обработка флагов
|
// Обработка флагов
|
||||||
@@ -224,34 +220,45 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Разрешаем флаги:
|
// Разрешаем флаги:
|
||||||
shouldCommit := resolveFlag(commit, noCommit, bc.Commit)
|
shouldCommit, err := resolveFlag(commit, noCommit, bc.Commit)
|
||||||
shouldTag := resolveFlag(tag, noTag, bc.Tag)
|
if err != nil {
|
||||||
|
log.Fatalf("Error resolving commit flags: %v", err)
|
||||||
|
}
|
||||||
|
shouldTag, err := resolveFlag(tag, noTag, bc.Tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error resolving tag flags: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
newVersion, err := bumpVersion(bc, *part)
|
newVersion, err := bumpVersion(bc, *part)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error bumping version: %v", err)
|
log.Fatalf("Error bumping version: %v", err)
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Current version: %s\n", bc.CurrentVersion)
|
||||||
fmt.Printf("New version: %s\n", newVersion)
|
fmt.Printf("New version: %s\n", newVersion)
|
||||||
|
|
||||||
// Обновляем файлы, указанные в конфигурации
|
// Обновляем файлы, указанные в конфигурации
|
||||||
updateFiles(bc.FilePaths, bc.CurrentVersion, newVersion)
|
if err := updateFiles(bc.FilePaths, bc.CurrentVersion, newVersion, !*noFatal); err != nil {
|
||||||
|
log.Fatalf("Error updating files: %v", err)
|
||||||
// Выполняем git commit и tag, если требуется
|
|
||||||
if shouldCommit {
|
|
||||||
if err := gitCommit(bc.CurrentVersion, newVersion, bc); err != nil {
|
|
||||||
log.Printf("Git commit error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Выполняем git commit и tag, если требуется
|
|
||||||
if shouldTag {
|
|
||||||
if err := gitTag(bc.CurrentVersion, newVersion, bc); err != nil {
|
|
||||||
log.Printf("Git tag error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем конфигурационный файл
|
// Обновляем конфигурационный файл
|
||||||
if err := updateConfigFile(cfg_name, newVersion); err != nil {
|
if err := updateConfigFile(cfg_name, newVersion); err != nil {
|
||||||
log.Printf("Error updating config file: %v", err)
|
log.Printf("Error updating config file: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Config file %s updated to version %s", cfg_name, newVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Выполняем git commit и tag, если требуется
|
||||||
|
if shouldCommit {
|
||||||
|
gitCommit(bc, newVersion, cfg_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Выполняем git commit и tag, если требуется
|
||||||
|
if shouldTag {
|
||||||
|
gitTag(bc, newVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *push {
|
||||||
|
gitPush(bc, newVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
292
src/main_test.go
Normal file
292
src/main_test.go
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5/config"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetBumpConfig(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
cfgPath := filepath.Join(tmpDir, ".bumpversion.cfg")
|
||||||
|
cfg := `
|
||||||
|
[bumpversion]
|
||||||
|
current_version = 1.2.3
|
||||||
|
commit = true
|
||||||
|
tag = true
|
||||||
|
tag_name = v{new_version}
|
||||||
|
parse = ^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$
|
||||||
|
serialize = {major}.{minor}.{patch}
|
||||||
|
message = Release {new_version}
|
||||||
|
|
||||||
|
[bumpversion:file:VERSION]
|
||||||
|
[bumpversion:file:README.md]
|
||||||
|
`
|
||||||
|
if err := os.WriteFile(cfgPath, []byte(cfg), 0o644); err != nil {
|
||||||
|
t.Fatalf("write config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := getBumpConfig(cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("getBumpConfig returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got.CurrentVersion != "1.2.3" {
|
||||||
|
t.Fatalf("CurrentVersion = %q, want 1.2.3", got.CurrentVersion)
|
||||||
|
}
|
||||||
|
if !got.Commit || !got.Tag {
|
||||||
|
t.Fatalf("expected commit and tag to be true, got commit=%v tag=%v", got.Commit, got.Tag)
|
||||||
|
}
|
||||||
|
if got.TagName != "v{new_version}" {
|
||||||
|
t.Fatalf("TagName = %q, want v{new_version}", got.TagName)
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(got.Serialize) != "{major}.{minor}.{patch}" {
|
||||||
|
t.Fatalf("Serialize = %q, want {major}.{minor}.{patch}", got.Serialize)
|
||||||
|
}
|
||||||
|
if got.Parse != `^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$` {
|
||||||
|
t.Fatalf("Parse = %q, want regex string", got.Parse)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantPaths := map[string]bool{
|
||||||
|
"VERSION": true,
|
||||||
|
"README.md": true,
|
||||||
|
}
|
||||||
|
for _, p := range got.FilePaths {
|
||||||
|
delete(wantPaths, p)
|
||||||
|
}
|
||||||
|
if len(wantPaths) != 0 {
|
||||||
|
t.Fatalf("FilePaths missing entries: %v", reflect.ValueOf(wantPaths).MapKeys())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateConfigFile(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
cfgPath := filepath.Join(tmpDir, ".bumpversion.cfg")
|
||||||
|
cfg := `
|
||||||
|
[bumpversion]
|
||||||
|
current_version = 0.0.1
|
||||||
|
commit = false
|
||||||
|
`
|
||||||
|
if err := os.WriteFile(cfgPath, []byte(cfg), 0o644); err != nil {
|
||||||
|
t.Fatalf("write config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateConfigFile(cfgPath, "0.0.2"); err != nil {
|
||||||
|
t.Fatalf("updateConfigFile returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, err := getBumpConfig(cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("getBumpConfig returned error: %v", err)
|
||||||
|
}
|
||||||
|
if updated.CurrentVersion != "0.0.2" {
|
||||||
|
t.Fatalf("CurrentVersion = %q, want 0.0.2", updated.CurrentVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBumpVersion(t *testing.T) {
|
||||||
|
bc := &BumpConfig{
|
||||||
|
CurrentVersion: "1.2.3",
|
||||||
|
Parse: `^v?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$`,
|
||||||
|
Serialize: "{major}.{minor}.{patch}",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
part string
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{name: "major", part: "major", want: "2.0.0"},
|
||||||
|
{name: "minor", part: "minor", want: "1.3.0"},
|
||||||
|
{name: "patch", part: "patch", want: "1.2.4"},
|
||||||
|
{name: "unknown", part: "build", wantErr: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := bumpVersion(bc, tt.part)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Fatalf("bumpVersion error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
if err == nil && got != tt.want {
|
||||||
|
t.Fatalf("bumpVersion = %q, want %q", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBumpVersionInvalidCurrent(t *testing.T) {
|
||||||
|
bc := &BumpConfig{
|
||||||
|
CurrentVersion: "1.2",
|
||||||
|
Parse: `^v?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$`,
|
||||||
|
Serialize: "{major}.{minor}.{patch}",
|
||||||
|
}
|
||||||
|
if _, err := bumpVersion(bc, "patch"); err == nil {
|
||||||
|
t.Fatalf("expected error for invalid current_version")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBumpVersionMissingGroups(t *testing.T) {
|
||||||
|
bc := &BumpConfig{
|
||||||
|
CurrentVersion: "1.2.3",
|
||||||
|
Parse: `^(?P<major>\d+)\.(?P<minor>\d+)$`,
|
||||||
|
Serialize: "{major}.{minor}.{patch}",
|
||||||
|
}
|
||||||
|
if _, err := bumpVersion(bc, "patch"); err == nil {
|
||||||
|
t.Fatalf("expected error when parse pattern misses patch group")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetBumpConfigMissingFile(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
if _, err := getBumpConfig(filepath.Join(tmpDir, "missing.cfg")); err == nil {
|
||||||
|
t.Fatalf("expected error for missing config file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignatureFromEnvDefaults(t *testing.T) {
|
||||||
|
prevUser := os.Getenv("GIT_USERNAME")
|
||||||
|
prevEmail := os.Getenv("GIT_EMAIL")
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = os.Setenv("GIT_USERNAME", prevUser)
|
||||||
|
_ = os.Setenv("GIT_EMAIL", prevEmail)
|
||||||
|
})
|
||||||
|
_ = os.Unsetenv("GIT_USERNAME")
|
||||||
|
_ = os.Unsetenv("GIT_EMAIL")
|
||||||
|
|
||||||
|
sig := signatureFromEnv()
|
||||||
|
if sig.Name != "bumpversion" || sig.Email != "bumpversion@deploy" {
|
||||||
|
t.Fatalf("signatureFromEnv defaults = %s %s, want bumpversion bumpversion@deploy", sig.Name, sig.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPushRefSpec(t *testing.T) {
|
||||||
|
head := plumbing.NewHashReference(plumbing.NewBranchReferenceName("main"), plumbing.ZeroHash)
|
||||||
|
spec, err := pushRefSpec(head)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("pushRefSpec returned error: %v", err)
|
||||||
|
}
|
||||||
|
want := config.RefSpec("refs/heads/main:refs/heads/main")
|
||||||
|
if spec != want {
|
||||||
|
t.Fatalf("pushRefSpec = %q, want %q", spec, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = pushRefSpec(plumbing.NewHashReference(plumbing.HEAD, plumbing.ZeroHash))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error for non-branch HEAD")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateFiles(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
oldV := "1.2.3"
|
||||||
|
newV := "1.2.4"
|
||||||
|
|
||||||
|
filePaths := []string{
|
||||||
|
filepath.Join(tmpDir, "VERSION"),
|
||||||
|
filepath.Join(tmpDir, "README.md"),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range filePaths {
|
||||||
|
contents := "project version " + oldV + "\n"
|
||||||
|
if err := os.WriteFile(p, []byte(contents), 0o644); err != nil {
|
||||||
|
t.Fatalf("write %s: %v", p, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateFiles(filePaths, oldV, newV, true); err != nil {
|
||||||
|
t.Fatalf("updateFiles returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range filePaths {
|
||||||
|
data, err := os.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read %s: %v", p, err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(data), newV) || strings.Contains(string(data), oldV) {
|
||||||
|
t.Fatalf("%s not updated correctly: %s", p, string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateFilesMissingVersionFatal(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
oldV := "1.2.3"
|
||||||
|
newV := "1.2.4"
|
||||||
|
|
||||||
|
target := filepath.Join(tmpDir, "README.md")
|
||||||
|
if err := os.WriteFile(target, []byte("no version here\n"), 0o644); err != nil {
|
||||||
|
t.Fatalf("write: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateFiles([]string{target}, oldV, newV, true); err == nil {
|
||||||
|
t.Fatalf("expected error when version is missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateFiles([]string{target}, oldV, newV, false); err != nil {
|
||||||
|
t.Fatalf("did not expect error when no-fatal is set: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveFlag(t *testing.T) {
|
||||||
|
boolPtr := func(b bool) *bool { return &b }
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
positive *bool
|
||||||
|
negative *bool
|
||||||
|
defaultValue bool
|
||||||
|
want bool
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "positive wins",
|
||||||
|
positive: boolPtr(true),
|
||||||
|
negative: boolPtr(false),
|
||||||
|
defaultValue: false,
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "negative wins",
|
||||||
|
positive: boolPtr(false),
|
||||||
|
negative: boolPtr(true),
|
||||||
|
defaultValue: true,
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default used",
|
||||||
|
positive: boolPtr(false),
|
||||||
|
negative: boolPtr(false),
|
||||||
|
defaultValue: true,
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on conflict",
|
||||||
|
positive: boolPtr(true),
|
||||||
|
negative: boolPtr(true),
|
||||||
|
defaultValue: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := resolveFlag(tt.positive, tt.negative, tt.defaultValue)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Fatalf("resolveFlag error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
if tt.wantErr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Fatalf("resolveFlag = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user