feat: support --major/-x --minor/-y --patch/-z for tag calculation
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
48d28c8dd1
commit
c0f92ca13d
|
@ -2,7 +2,6 @@ package recipe
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -10,6 +9,7 @@ import (
|
|||
"coopcloud.tech/abra/cli/internal"
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
"coopcloud.tech/tagcmp"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
|
@ -21,9 +21,34 @@ var Dry bool
|
|||
var DryFlag = &cli.BoolFlag{
|
||||
Name: "dry-run",
|
||||
Value: false,
|
||||
Aliases: []string{"d"},
|
||||
Destination: &Dry,
|
||||
}
|
||||
|
||||
var Major bool
|
||||
var MajorFlag = &cli.BoolFlag{
|
||||
Name: "major",
|
||||
Value: false,
|
||||
Aliases: []string{"ma", "x"},
|
||||
Destination: &Major,
|
||||
}
|
||||
|
||||
var Minor bool
|
||||
var MinorFlag = &cli.BoolFlag{
|
||||
Name: "minor",
|
||||
Value: false,
|
||||
Aliases: []string{"mi", "y"},
|
||||
Destination: &Minor,
|
||||
}
|
||||
|
||||
var Patch bool
|
||||
var PatchFlag = &cli.BoolFlag{
|
||||
Name: "patch",
|
||||
Value: false,
|
||||
Aliases: []string{"p", "z"},
|
||||
Destination: &Patch,
|
||||
}
|
||||
|
||||
var recipeReleaseCommand = &cli.Command{
|
||||
Name: "release",
|
||||
Usage: "tag a recipe",
|
||||
|
@ -31,25 +56,15 @@ var recipeReleaseCommand = &cli.Command{
|
|||
ArgsUsage: "<recipe> [<tag>]",
|
||||
Flags: []cli.Flag{
|
||||
DryFlag,
|
||||
PatchFlag,
|
||||
MinorFlag,
|
||||
MajorFlag,
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
recipe := internal.ValidateRecipe(c)
|
||||
|
||||
directory := path.Join(config.APPS_DIR, recipe.Name)
|
||||
if _, err := os.Stat(directory); os.IsNotExist(err) {
|
||||
logrus.Fatalf("recipe doesn't exist at path %s.", directory)
|
||||
return nil
|
||||
}
|
||||
|
||||
images := getImageVersions(recipe)
|
||||
tag := c.Args().Get(1)
|
||||
if tag == "" {
|
||||
for name, version := range images {
|
||||
if !isSemver(version) {
|
||||
logrus.Fatal(fmt.Sprintf("app %s: version number %s is not in the format x.y.z (where x,y,z are integers) - unable to generate tags, please specify a tag yourself.", name, version))
|
||||
}
|
||||
}
|
||||
}
|
||||
tagstring := c.Args().Get(1)
|
||||
imagesTmp := getImageVersions(recipe)
|
||||
|
||||
repo, err := git.PlainOpen(directory)
|
||||
if err != nil {
|
||||
|
@ -59,42 +74,107 @@ var recipeReleaseCommand = &cli.Command{
|
|||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
// get the latest tag with its hash, name etc
|
||||
if tag == "" {
|
||||
var lastTag *object.Tag
|
||||
iter, err := repo.Tags()
|
||||
|
||||
if tagstring != "" {
|
||||
repo, err := git.PlainOpen(directory)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
// TODO: This is some magic and I have no idea what's going on but it does the job. Re-write if this looks stupid to you. Copied from the docs /knoflook
|
||||
if err := iter.ForEach(func(ref *plumbing.Reference) error {
|
||||
obj, err := repo.TagObject(ref.Hash())
|
||||
switch err {
|
||||
case nil:
|
||||
lastTag = obj
|
||||
break
|
||||
case plumbing.ErrObjectNotFound:
|
||||
logrus.Fatal(err)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
head, err := repo.Head()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if Dry {
|
||||
logrus.Info(fmt.Sprintf("Dry run only. NOT creating tag %s at %s", tagstring, head.Hash()))
|
||||
return nil
|
||||
}
|
||||
|
||||
repo.CreateTag(tagstring, head.Hash(), nil) /* &git.CreateTagOptions{
|
||||
Message: tag,
|
||||
})*/
|
||||
logrus.Info(fmt.Sprintf("Created tag %s at %s.", tagstring, head.Hash()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bumpType is used to decide what part of the tag should be incremented
|
||||
bumpType := btoi(Major)*4 + btoi(Minor)*2 + btoi(Patch)
|
||||
if bumpType != 0 {
|
||||
// a bitwise check if the number is a power of 2
|
||||
if (bumpType & (bumpType - 1)) != 0 {
|
||||
logrus.Fatal("you can only use one of: --major, --minor, --patch.")
|
||||
}
|
||||
}
|
||||
|
||||
// get the latest tag with its hash, name etc
|
||||
var lastGitTag *object.Tag
|
||||
iter, err := repo.Tags()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if err := iter.ForEach(func(ref *plumbing.Reference) error {
|
||||
obj, err := repo.TagObject(ref.Hash())
|
||||
if err == nil {
|
||||
lastGitTag = obj
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
||||
}); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
newTag, err := tagcmp.Parse(lastGitTag.Name)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
var newTagString string
|
||||
if bumpType > 0 {
|
||||
if Patch {
|
||||
now, err := strconv.Atoi(newTag.Patch)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
newTag.Patch = strconv.Itoa(now + 1)
|
||||
} else if Minor {
|
||||
now, err := strconv.Atoi(newTag.Minor)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
newTag.Minor = strconv.Itoa(now + 1)
|
||||
} else if Major {
|
||||
now, err := strconv.Atoi(newTag.Major)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
newTag.Major = strconv.Itoa(now + 1)
|
||||
}
|
||||
newTagString = newTag.String()
|
||||
} else {
|
||||
// calculate the new tag
|
||||
var images = make(map[string]tagcmp.Tag)
|
||||
for name, version := range imagesTmp {
|
||||
t, err := tagcmp.Parse(version)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
images[name] = t
|
||||
}
|
||||
}
|
||||
|
||||
if Dry {
|
||||
logrus.Info(fmt.Sprintf("Dry run only. NOT creating tag %s at %s", tag, head.Hash()))
|
||||
logrus.Info(fmt.Sprintf("Dry run only. NOT creating tag %s at %s", newTagString, head.Hash()))
|
||||
return nil
|
||||
}
|
||||
|
||||
repo.CreateTag(tag, head.Hash(), nil) /* &git.CreateTagOptions{
|
||||
repo.CreateTag(newTagString, head.Hash(), nil) /* &git.CreateTagOptions{
|
||||
Message: tag,
|
||||
})*/
|
||||
logrus.Info(fmt.Sprintf("Created tag %s at %s.", tag, head.Hash()))
|
||||
logrus.Info(fmt.Sprintf("Created tag %s at %s.", newTagString, head.Hash()))
|
||||
|
||||
return nil
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -109,15 +189,9 @@ func getImageVersions(recipe recipe.Recipe) map[string]string {
|
|||
return services
|
||||
}
|
||||
|
||||
func isSemver(ver string) bool {
|
||||
numbers := strings.Split(ver, ".")
|
||||
if len(numbers) > 3 {
|
||||
return false
|
||||
func btoi(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
for _, part := range numbers {
|
||||
if _, err := strconv.Atoi(part); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return 0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue