mirror of
https://github.com/go-acme/lego.git
synced 2024-12-23 01:07:23 +02:00
184 lines
3.4 KiB
Go
184 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
|
|
hcversion "github.com/hashicorp/go-version"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
const flgMode = "mode"
|
|
|
|
const (
|
|
modePatch = "patch"
|
|
modeMinor = "minor"
|
|
modeMajor = "major"
|
|
)
|
|
|
|
const versionSourceFile = "./cmd/lego/zz_gen_version.go"
|
|
|
|
const (
|
|
commentRelease = "release"
|
|
commentDetach = "detach"
|
|
)
|
|
|
|
func main() {
|
|
app := cli.NewApp()
|
|
app.Name = "lego-releaser"
|
|
app.Usage = "Lego releaser"
|
|
app.HelpName = "releaser"
|
|
app.Commands = []*cli.Command{
|
|
{
|
|
Name: "release",
|
|
Usage: "Update file for a release",
|
|
Action: release,
|
|
Before: func(ctx *cli.Context) error {
|
|
mode := ctx.String("mode")
|
|
switch mode {
|
|
case modePatch, modeMinor, modeMajor:
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("invalid mode: %s", mode)
|
|
}
|
|
},
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: flgMode,
|
|
Aliases: []string{"m"},
|
|
Value: modePatch,
|
|
Usage: fmt.Sprintf("The release mode: %s|%s|%s", modePatch, modeMinor, modeMajor),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "detach",
|
|
Usage: "Update file post release",
|
|
Action: detach,
|
|
},
|
|
}
|
|
|
|
err := app.Run(os.Args)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func release(ctx *cli.Context) error {
|
|
mode := ctx.String(flgMode)
|
|
|
|
currentVersion, err := readCurrentVersion(versionSourceFile)
|
|
if err != nil {
|
|
return fmt.Errorf("read current version: %w", err)
|
|
}
|
|
|
|
nextVersion, err := bumpVersion(mode, currentVersion)
|
|
if err != nil {
|
|
return fmt.Errorf("bump version: %w", err)
|
|
}
|
|
|
|
err = generate(nextVersion, commentRelease)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func detach(_ *cli.Context) error {
|
|
currentVersion, err := readCurrentVersion(versionSourceFile)
|
|
if err != nil {
|
|
return fmt.Errorf("read current version: %w", err)
|
|
}
|
|
|
|
v := currentVersion.Core().String()
|
|
|
|
err = generate(v, commentDetach)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func readCurrentVersion(filename string) (*hcversion.Version, error) {
|
|
fset := token.NewFileSet()
|
|
file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
v := visitor{data: make(map[string]string)}
|
|
ast.Walk(v, file)
|
|
|
|
current, err := hcversion.NewSemver(v.data["defaultVersion"])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return current, nil
|
|
}
|
|
|
|
type visitor struct {
|
|
data map[string]string
|
|
}
|
|
|
|
func (v visitor) Visit(n ast.Node) ast.Visitor {
|
|
if n == nil {
|
|
return nil
|
|
}
|
|
|
|
switch d := n.(type) {
|
|
case *ast.GenDecl:
|
|
if d.Tok == token.CONST {
|
|
for _, spec := range d.Specs {
|
|
valueSpec, ok := spec.(*ast.ValueSpec)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if len(valueSpec.Names) != 1 || len(valueSpec.Values) != 1 {
|
|
continue
|
|
}
|
|
|
|
va, ok := valueSpec.Values[0].(*ast.BasicLit)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if va.Kind != token.STRING {
|
|
continue
|
|
}
|
|
|
|
s, err := strconv.Unquote(va.Value)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
v.data[valueSpec.Names[0].String()] = s
|
|
}
|
|
}
|
|
default:
|
|
// noop
|
|
}
|
|
return v
|
|
}
|
|
|
|
func bumpVersion(mode string, v *hcversion.Version) (string, error) {
|
|
segments := v.Segments()
|
|
|
|
switch mode {
|
|
case modePatch:
|
|
return fmt.Sprintf("%d.%d.%d", segments[0], segments[1], segments[2]+1), nil
|
|
case modeMinor:
|
|
return fmt.Sprintf("%d.%d.0", segments[0], segments[1]+1), nil
|
|
case modeMajor:
|
|
return fmt.Sprintf("%d.0.0", segments[0]+1), nil
|
|
default:
|
|
return "", fmt.Errorf("invalid mode: %s", mode)
|
|
}
|
|
}
|