123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- // Copyright (C) 2025 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- //go:build tools
- // +build tools
- package main
- import (
- "flag"
- "fmt"
- "os"
- "os/exec"
- "strconv"
- "strings"
- "github.com/coreos/go-semver/semver"
- )
- const suffix = "rc"
- func main() {
- pre := flag.Bool("pre", false, "Create a prerelease")
- flag.Parse()
- // Get the latest "v1.22.3" or "v1.22.3-rc.1" style tag.
- latestTag, err := cmd("git", "describe", "--abbrev=0", "--match", "v[0-9].*")
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- latest, err := semver.NewVersion(latestTag[1:])
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- // Get the latest "v1.22.3" style tag, excludeing prereleases.
- latestStableTag, err := cmd("git", "describe", "--abbrev=0", "--match", "v[0-9].*", "--exclude", "*-*")
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- latestStable, err := semver.NewVersion(latestStableTag[1:])
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- // Get the commit logs since the latest stable tag.
- logsSinceLatest, err := cmd("git", "log", "--pretty=format:%s", latestStableTag+"..HEAD")
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- // Check if the next version should be a feature or a patch release
- nextIsFeature := false
- for _, line := range strings.Split(logsSinceLatest, "\n") {
- if strings.HasPrefix(line, "feat") {
- nextIsFeature = true
- break
- }
- }
- next := *latestStable
- if nextIsFeature {
- next.BumpMinor()
- } else {
- next.BumpPatch()
- }
- if latest.PreRelease != "" {
- if !*pre {
- // We want a stable release. Simply remove the prerelease
- // suffix.
- latest.PreRelease = ""
- fmt.Println("v" + latest.String())
- return
- }
- // We want the next prerelease. We are already on a prerelease. If
- // it's the correct prerelease compared to the logs we just got, or
- // newer, we should just bump the prerelease counter. We compare
- // against the latest without the prerelease part, as otherwise it
- // would compare less than next if they represent the same version
- // -- pre being less than stable.
- latestNoPre := *latest
- latestNoPre.PreRelease = ""
- if !latestNoPre.LessThan(next) {
- parts := latest.PreRelease.Slice()
- for i, p := range parts {
- if v, err := strconv.Atoi(p); err == nil {
- parts[i] = strconv.Itoa(v + 1)
- latest.PreRelease = semver.PreRelease(strings.Join(parts, "."))
- fmt.Println("v" + latest.String())
- return
- }
- }
- }
- // Otherwise we generate a new rc.1 for the correct next version.
- next.PreRelease = suffix + ".1"
- fmt.Println("v" + next.String())
- return
- }
- if nextIsFeature {
- latest.BumpMinor()
- } else {
- latest.BumpPatch()
- }
- if *pre {
- latest.PreRelease = suffix + ".1"
- }
- fmt.Println("v" + latest.String())
- }
- func cmd(name string, args ...string) (string, error) {
- cmd := exec.Command(name, args...)
- bs, err := cmd.CombinedOutput()
- if err != nil {
- return "", err
- }
- return strings.TrimSpace(string(bs)), nil
- }
|