move to gitea actions
This commit is contained in:
60
.gitea/workflows/build.yml
Normal file
60
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
name: Gitbump CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: [ubuntu-latest, amd64]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.26'
|
||||||
|
|
||||||
|
- name: Test & Build
|
||||||
|
run: |
|
||||||
|
just vet test
|
||||||
|
just build-linux-amd64
|
||||||
|
/bin/gitbump_linux_amd64 --version
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: [ubuntu-latest, amd64]
|
||||||
|
needs: test-build
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
persist-credentials: true
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.26'
|
||||||
|
|
||||||
|
- name: Bump & Tag
|
||||||
|
run: go run main.go
|
||||||
|
|
||||||
|
notify-failure:
|
||||||
|
runs-on: go-executor
|
||||||
|
needs: [test, build]
|
||||||
|
if: always() && contains(needs.*.result, 'failure')
|
||||||
|
steps:
|
||||||
|
- name: ntfy-failed-notifications
|
||||||
|
uses: niniyas/ntfy-action@master
|
||||||
|
with:
|
||||||
|
url: 'https://ntfy.zlymeda.dynu.net'
|
||||||
|
topic: ${{ secrets.NTFY_TOPIC || 'errors' }}
|
||||||
|
priority: 5
|
||||||
|
tags: flying_saucer,warning,🚨,🛠️,action,failed
|
||||||
|
details: Workflow has failed!
|
||||||
|
actions: 'default'
|
||||||
|
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
gitbump
|
||||||
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# gitbump
|
||||||
|
|
||||||
|
Automatically bump version and tag based on commit messages.
|
||||||
|
|
||||||
|
## Usage as Gitea/GitHub Action
|
||||||
|
|
||||||
|
Add this to your workflow:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
bump:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.23'
|
||||||
|
- uses: https://gitea.com/your-user/gitbump@master
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inputs
|
||||||
|
|
||||||
|
| Input | Description | Default |
|
||||||
|
|-------|-------------|---------|
|
||||||
|
| `dry-run` | Show what would be done without making changes | `false` |
|
||||||
|
| `bump` | Force specific bump type (`major`, `minor`, or `patch`) | |
|
||||||
|
| `prefix` | Version prefix | `v` |
|
||||||
|
| `no-push` | Create tag but don't push to remote | `false` |
|
||||||
|
| `major-patterns` | Comma-separated list for major version bumps | `bump major,breaking change` |
|
||||||
|
| `minor-patterns` | Comma-separated list for minor version bumps | `bump minor,feat` |
|
||||||
|
| `patch-patterns` | Comma-separated list for patch version bumps | `bump patch,fix` |
|
||||||
|
| `chore-patterns` | Comma-separated list for commits that should be ignored | `chore,bump:skip` |
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- consider using https://github.com/go-git/go-git
|
||||||
|
- could read changelog or something to create an annotated tag
|
||||||
37
action.yml
Normal file
37
action.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: 'Gitbump'
|
||||||
|
description: 'Automatically bump version and tag based on commit messages'
|
||||||
|
inputs:
|
||||||
|
dry-run:
|
||||||
|
description: 'Show what would be done without making changes'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
bump:
|
||||||
|
description: 'Force specific bump type (major, minor, or patch)'
|
||||||
|
required: false
|
||||||
|
prefix:
|
||||||
|
description: 'Version prefix (default "v")'
|
||||||
|
required: false
|
||||||
|
default: 'v'
|
||||||
|
no-push:
|
||||||
|
description: 'Create tag but dont push to remote'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
major-patterns:
|
||||||
|
description: 'Comma-separated list for major version bumps'
|
||||||
|
required: false
|
||||||
|
default: 'bump major,breaking change'
|
||||||
|
minor-patterns:
|
||||||
|
description: 'Comma-separated list for minor version bumps'
|
||||||
|
required: false
|
||||||
|
default: 'bump minor,feat'
|
||||||
|
patch-patterns:
|
||||||
|
description: 'Comma-separated list for patch version bumps'
|
||||||
|
required: false
|
||||||
|
default: 'bump patch,fix'
|
||||||
|
chore-patterns:
|
||||||
|
description: 'Comma-separated list for commits that should be ignored'
|
||||||
|
required: false
|
||||||
|
default: 'chore,bump:skip'
|
||||||
|
runs:
|
||||||
|
using: 'go'
|
||||||
|
main: 'main.go'
|
||||||
119
justfile
Normal file
119
justfile
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
set fallback
|
||||||
|
|
||||||
|
default:
|
||||||
|
just --choose
|
||||||
|
|
||||||
|
list:
|
||||||
|
just --list
|
||||||
|
|
||||||
|
|
||||||
|
import? 'justfile.custom'
|
||||||
|
|
||||||
|
# Variables with defaults
|
||||||
|
CGO_ENABLED := env_var_or_default('CGO_ENABLED', '0')
|
||||||
|
GO111MODULE := env_var_or_default('GO111MODULE', 'on')
|
||||||
|
GOFLAGS := env_var_or_default('GOFLAGS', '"-mod=mod"')
|
||||||
|
SUFFIX := env_var_or_default('SUFFIX', '')
|
||||||
|
|
||||||
|
# Determine project name
|
||||||
|
NAME := if env_var_or_default('GITEA_REPO_NAME', '') != '' {
|
||||||
|
env_var('GITEA_REPO_NAME')
|
||||||
|
} else {
|
||||||
|
file_name(justfile_directory())
|
||||||
|
}
|
||||||
|
|
||||||
|
OUTBIN := env_var_or_default('OUTBIN', NAME)
|
||||||
|
|
||||||
|
# Build metadata
|
||||||
|
VERSION := env_var_or_default('VERSION', `git describe --tags --always --dirty 2> /dev/null || echo dev`)
|
||||||
|
BUILD_TIME := env_var_or_default('BUILD_TIME', `/bin/date +%FT%T%z`)
|
||||||
|
PKG := `GOWORK=off go list -m`
|
||||||
|
LD_FLAGS_OPTIMIZE := env_var_or_default('LD_FLAGS_OPTIMIZE', '-s -w')
|
||||||
|
LD_FLAGS := '"-X main.Version=' + VERSION + ' -X main.BuildTime=' + BUILD_TIME + ' ' + LD_FLAGS_OPTIMIZE + '"'
|
||||||
|
GO_OPTS := env_var_or_default('GO_OPTS', '-trimpath')
|
||||||
|
OPTIMIZE := env_var_or_default('OPTIMIZE', 'false')
|
||||||
|
|
||||||
|
# Display version information
|
||||||
|
version:
|
||||||
|
@echo {{NAME}} {{VERSION}} {{BUILD_TIME}} {{PKG}} {{LD_FLAGS}}
|
||||||
|
|
||||||
|
# Build for all platforms
|
||||||
|
all-build: build-linux-amd64 build-linux-arm64 build-linux-386
|
||||||
|
|
||||||
|
# Download dependencies
|
||||||
|
download:
|
||||||
|
@echo Download go.mod dependencies
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
# Generate code
|
||||||
|
generate:
|
||||||
|
GOWORK=off go generate -mod=mod ./...
|
||||||
|
|
||||||
|
# Run wire dependency injection
|
||||||
|
wire:
|
||||||
|
go generate -x ./di
|
||||||
|
|
||||||
|
# Build for specific platform
|
||||||
|
build GOOS GOARCH:
|
||||||
|
GOOS={{GOOS}} GOARCH={{GOARCH}} CGO_ENABLED={{CGO_ENABLED}} go build \
|
||||||
|
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
||||||
|
-mod mod \
|
||||||
|
-o bin/{{OUTBIN}}{{SUFFIX}}_{{GOOS}}_{{GOARCH}} \
|
||||||
|
./main.go
|
||||||
|
build-race:
|
||||||
|
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -race \
|
||||||
|
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
||||||
|
-mod mod \
|
||||||
|
-o bin/{{OUTBIN}}{{SUFFIX}}_linux_amd64 \
|
||||||
|
./main.go
|
||||||
|
|
||||||
|
# Install binaries
|
||||||
|
install:
|
||||||
|
CGO_ENABLED={{CGO_ENABLED}} go install \
|
||||||
|
-ldflags {{LD_FLAGS}} \
|
||||||
|
./...
|
||||||
|
|
||||||
|
# Build for Linux ARM64
|
||||||
|
build-linux-arm64: (build "linux" "arm64")
|
||||||
|
|
||||||
|
# Build for Linux AMD64
|
||||||
|
build-linux-amd64: (build "linux" "amd64")
|
||||||
|
|
||||||
|
# Build for Linux 386
|
||||||
|
build-linux-386: (build "linux" "386")
|
||||||
|
|
||||||
|
# Pre-push checks
|
||||||
|
prepush: generate vet fmt tidy test
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test:
|
||||||
|
CGO_ENABLED=0 go build -mod=mod ./...
|
||||||
|
CGO_ENABLED=1 go test -race -cover -v -mod=mod ./... && echo -e "\033[32mSUCCESS\033[0m" || (echo -e "\033[31mFAILED\033[0m" && exit 1)
|
||||||
|
|
||||||
|
# Run benchmarks
|
||||||
|
bench:
|
||||||
|
go test -test.timeout=30m -benchmem -run ^$$ -benchtime=20s -bench . ./... && echo -e "\033[32mSUCCESS\033[0m" || (echo -e "\033[31mFAILED\033[0m" && exit 1)
|
||||||
|
|
||||||
|
# Run go vet
|
||||||
|
vet:
|
||||||
|
go vet ./...
|
||||||
|
|
||||||
|
# Format code
|
||||||
|
fmt:
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
# Tidy dependencies
|
||||||
|
tidy:
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
verify:
|
||||||
|
go mod verify
|
||||||
|
|
||||||
|
# List all modules
|
||||||
|
go_list:
|
||||||
|
go list -u -m all
|
||||||
|
|
||||||
|
# Update all dependencies
|
||||||
|
go_update_all:
|
||||||
|
go get -t -u ./...
|
||||||
|
|
||||||
337
main.go
Normal file
337
main.go
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Version = "UNKNOWN"
|
||||||
|
var BuildTime = "UNKNOWN"
|
||||||
|
|
||||||
|
const DefaultVersion = "v0.0.0"
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
printVersion bool
|
||||||
|
dryRun bool
|
||||||
|
forcedBump string
|
||||||
|
versionPrefix string
|
||||||
|
patterns Patterns
|
||||||
|
noPush bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Patterns struct {
|
||||||
|
major []string
|
||||||
|
minor []string
|
||||||
|
patch []string
|
||||||
|
chore []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("version: %s\n", Version)
|
||||||
|
fmt.Printf("built: %s\n", BuildTime)
|
||||||
|
|
||||||
|
config := parseFlags()
|
||||||
|
|
||||||
|
if config.printVersion {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("fetching tags:")
|
||||||
|
if err := fetchTags(); err != nil {
|
||||||
|
log.Fatalf("Error fetching tags: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("DRONE") == "true" || os.Getenv("GITEA_ACTIONS") == "true" || os.Getenv("GITHUB_ACTIONS") == "true" {
|
||||||
|
must(git("config user.email zlymeda@gmail.com"))
|
||||||
|
must(git("config user.name \"gitbump\""))
|
||||||
|
}
|
||||||
|
|
||||||
|
tag, err := getLatestTag()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error getting latest tag: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("latest tag:", tag)
|
||||||
|
|
||||||
|
commits, err := getCommitsSinceTag(tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error getting commits: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("\nCommits since last tag:")
|
||||||
|
for _, commit := range commits {
|
||||||
|
fmt.Printf("- %s\n", commit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(commits) == 0 {
|
||||||
|
fmt.Println("No commits found since last tag. No version bump needed.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
major, minor, patch, err := parseVersion(tag, config.versionPrefix)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error parsing version: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("version:", major, minor, patch)
|
||||||
|
|
||||||
|
bumpType := getBumpType(commits, config)
|
||||||
|
fmt.Println("bump type:", bumpType)
|
||||||
|
if bumpType == "chore" {
|
||||||
|
fmt.Println("Only chore commits found -> no version bump needed.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newVersion := calculateNewVersion(major, minor, patch, bumpType, config.versionPrefix)
|
||||||
|
fmt.Println("new version:", newVersion)
|
||||||
|
|
||||||
|
if config.dryRun {
|
||||||
|
fmt.Printf("Dry run: Would bump version from %s to %s (bump type: %s)\n", tag, newVersion, bumpType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Trying to bump version from %s to %s\n", tag, newVersion)
|
||||||
|
err = createAndPushTag(newVersion, config.noPush)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error creating/pushing tag: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully bumped version from %s to %s\n", tag, newVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFlags() Config {
|
||||||
|
config := Config{}
|
||||||
|
|
||||||
|
flag.BoolVar(&config.printVersion, "version", false, "Just print version")
|
||||||
|
flag.BoolVar(&config.dryRun, "dry-run", getEnvBool("DRY_RUN", false), "Show what would be done without making changes")
|
||||||
|
flag.StringVar(&config.forcedBump, "bump", os.Getenv("BUMP"), "Force specific bump type (major, minor, or patch)")
|
||||||
|
flag.StringVar(&config.versionPrefix, "prefix", getEnv("PREFIX", "v"), "Version prefix (default 'v')")
|
||||||
|
flag.BoolVar(&config.noPush, "no-push", getEnvBool("NO_PUSH", false), "Create tag but don't push to remote")
|
||||||
|
|
||||||
|
majorPatterns := flag.String("major-patterns", getEnv("MAJOR_PATTERNS", "bump major,breaking change"), "Comma-separated list will be joined with '|' for major version bumps")
|
||||||
|
minorPatterns := flag.String("minor-patterns", getEnv("MINOR_PATTERNS", "bump minor,feat"), "Comma-separated list will be joined with '|' for minor version bumps")
|
||||||
|
patchPatterns := flag.String("patch-patterns", getEnv("PATCH_PATTERNS", "bump patch,fix"), "Comma-separated list will be joined with '|' for patch version bumps")
|
||||||
|
chorePatterns := flag.String("chore-patterns", getEnv("CHORE_PATTERNS", "chore,bump:skip"), "Comma-separated list will be joined with '|' for commits that should be ignored")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
config.patterns = Patterns{
|
||||||
|
major: strings.Split(*majorPatterns, ","),
|
||||||
|
minor: strings.Split(*minorPatterns, ","),
|
||||||
|
patch: strings.Split(*patchPatterns, ","),
|
||||||
|
chore: strings.Split(*chorePatterns, ","),
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.forcedBump != "" && !contains([]string{"major", "minor", "patch"}, config.forcedBump) {
|
||||||
|
log.Fatalf("Invalid bump type: %s. Must be one of: major, minor, patch", config.forcedBump)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnv(key, fallback string) string {
|
||||||
|
if value, ok := os.LookupEnv(key); ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
// Check for Gitea/GitHub Actions input prefix
|
||||||
|
inputKey := "INPUT_" + strings.ReplaceAll(strings.ToUpper(key), "-", "_")
|
||||||
|
if value, ok := os.LookupEnv(inputKey); ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnvBool(key string, fallback bool) bool {
|
||||||
|
if value, ok := os.LookupEnv(key); ok {
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
// Check for Gitea/GitHub Actions input prefix
|
||||||
|
inputKey := "INPUT_" + strings.ReplaceAll(strings.ToUpper(key), "-", "_")
|
||||||
|
if value, ok := os.LookupEnv(inputKey); ok {
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(slice []string, item string) bool {
|
||||||
|
for _, s := range slice {
|
||||||
|
if s == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLatestTag() (string, error) {
|
||||||
|
output, err := git("describe --tags --abbrev=0")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
if strings.Contains(err.Error(), "No names found") {
|
||||||
|
return DefaultVersion, nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchTags() error {
|
||||||
|
_, err := git("fetch --tags")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCommitsSinceTag(tag string) ([]string, error) {
|
||||||
|
var cmd string
|
||||||
|
|
||||||
|
if tag == DefaultVersion {
|
||||||
|
cmd = "log --pretty=format:%s"
|
||||||
|
} else {
|
||||||
|
cmd = "log --pretty=format:%s " + tag + "..HEAD"
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := git(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
commits := strings.Split(output, "\n")
|
||||||
|
if len(commits) == 1 && commits[0] == "" {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
return commits, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseVersion(tag, prefix string) (int, int, int, error) {
|
||||||
|
tag = strings.TrimPrefix(tag, prefix)
|
||||||
|
|
||||||
|
parts := strings.Split(tag, ".")
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return 0, 0, 0, fmt.Errorf("invalid version format: %s", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
major, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
minor, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
patch, err := strconv.Atoi(parts[2])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return major, minor, patch, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBumpType(commits []string, config Config) string {
|
||||||
|
// If bump type is forced via flag, use that
|
||||||
|
if config.forcedBump != "" {
|
||||||
|
return config.forcedBump
|
||||||
|
}
|
||||||
|
|
||||||
|
majorPattern := regexp.MustCompile(`(?i)(` + strings.Join(config.patterns.major, "|") + `)`)
|
||||||
|
minorPattern := regexp.MustCompile(`(?i)(` + strings.Join(config.patterns.minor, "|") + `)`)
|
||||||
|
patchPattern := regexp.MustCompile(`(?i)(` + strings.Join(config.patterns.patch, "|") + `)`)
|
||||||
|
chorePattern := regexp.MustCompile(`(?i)(` + strings.Join(config.patterns.chore, "|") + `)`)
|
||||||
|
|
||||||
|
chores := 0
|
||||||
|
for _, commit := range commits {
|
||||||
|
if majorPattern.MatchString(commit) {
|
||||||
|
return "major"
|
||||||
|
}
|
||||||
|
if minorPattern.MatchString(commit) {
|
||||||
|
return "minor"
|
||||||
|
}
|
||||||
|
if patchPattern.MatchString(commit) {
|
||||||
|
return "patch"
|
||||||
|
}
|
||||||
|
if chorePattern.MatchString(commit) {
|
||||||
|
chores++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to patch bump if there are any non-chore commits
|
||||||
|
if len(commits) > chores {
|
||||||
|
return "patch"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "chore"
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateNewVersion(major, minor, patch int, bumpType, prefix string) string {
|
||||||
|
switch bumpType {
|
||||||
|
case "major":
|
||||||
|
major++
|
||||||
|
minor = 0
|
||||||
|
patch = 0
|
||||||
|
case "minor":
|
||||||
|
minor++
|
||||||
|
patch = 0
|
||||||
|
case "patch":
|
||||||
|
patch++
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%d.%d.%d", prefix, major, minor, patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAndPushTag(version string, noPush bool) error {
|
||||||
|
if out, err := git("tag " + version); err != nil {
|
||||||
|
return fmt.Errorf("error creating tag: %v; stdout: %v", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if noPush {
|
||||||
|
fmt.Println("pushing disabled")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := git("push origin " + version); err != nil {
|
||||||
|
return fmt.Errorf("error pushing tag: %v; stdout: %v", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func git(command string) (string, error) {
|
||||||
|
parts := strings.Split(command, " ")
|
||||||
|
|
||||||
|
cmd := exec.Command("git", parts...)
|
||||||
|
fmt.Printf("running %s\n", cmd)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
var ee *exec.ExitError
|
||||||
|
if errors.As(err, &ee) {
|
||||||
|
stderr := strings.TrimSpace(string(ee.Stderr))
|
||||||
|
fmt.Println(stderr)
|
||||||
|
return "", fmt.Errorf("git command: %v: %s", err, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("git command: %v", err)
|
||||||
|
}
|
||||||
|
result := strings.TrimSpace(string(output))
|
||||||
|
fmt.Printf("output: %s\n", result)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func must(_ string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
14
main_test.go
Normal file
14
main_test.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestParseVersion(t *testing.T) {
|
||||||
|
major, minor, patch, err := parseVersion("v0.0.0", "v")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if major != 0 || minor != 0 || patch != 0 {
|
||||||
|
t.Fatal("version does not match")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user