forked from toolshed/abra
Merge pull request 'feat: tag recipes with abra' (#99) from knoflook/abra:recipe-release into main
Reviewed-on: coop-cloud/abra#99
This commit is contained in:
commit
2076c566bb
@ -18,6 +18,7 @@ Cloud community and you can use Abra to read them and create apps for you.
|
|||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
recipeListCommand,
|
recipeListCommand,
|
||||||
recipeVersionCommand,
|
recipeVersionCommand,
|
||||||
|
recipeReleaseCommand,
|
||||||
recipeNewCommand,
|
recipeNewCommand,
|
||||||
recipeUpgradeCommand,
|
recipeUpgradeCommand,
|
||||||
recipeSyncCommand,
|
recipeSyncCommand,
|
||||||
|
228
cli/recipe/release.go
Normal file
228
cli/recipe/release.go
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
package recipe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Push bool
|
||||||
|
var PushFlag = &cli.BoolFlag{
|
||||||
|
Name: "push",
|
||||||
|
Value: false,
|
||||||
|
Destination: &Push,
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
Aliases: []string{"rl"},
|
||||||
|
ArgsUsage: "<recipe> [<tag>]",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
DryFlag,
|
||||||
|
PatchFlag,
|
||||||
|
MinorFlag,
|
||||||
|
MajorFlag,
|
||||||
|
PushFlag,
|
||||||
|
},
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
recipe := internal.ValidateRecipe(c)
|
||||||
|
directory := path.Join(config.APPS_DIR, recipe.Name)
|
||||||
|
tagstring := c.Args().Get(1)
|
||||||
|
imagesTmp := getImageVersions(recipe)
|
||||||
|
mainApp := getMainApp(recipe)
|
||||||
|
mainAppVersion := imagesTmp[mainApp]
|
||||||
|
if mainAppVersion == "" {
|
||||||
|
logrus.Fatal("Main app's version is empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := git.PlainOpen(directory)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
head, err := repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tagstring != "" {
|
||||||
|
if bumpType > 0 {
|
||||||
|
logrus.Warn("User specified a version number and --major/--minor/--patch at the same time! Using version number.")
|
||||||
|
}
|
||||||
|
tagstring = fmt.Sprintf("%s+%s", tagstring, mainAppVersion)
|
||||||
|
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()))
|
||||||
|
if Push {
|
||||||
|
if err := repo.Push(&git.PushOptions{}); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
logrus.Info(fmt.Sprintf("Pushed tag %s to remote.", tagstring))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newTagString = fmt.Sprintf("%s+%s", newTagString, mainAppVersion)
|
||||||
|
if Dry {
|
||||||
|
logrus.Info(fmt.Sprintf("Dry run only. NOT creating tag %s at %s", newTagString, head.Hash()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.CreateTag(newTagString, head.Hash(), nil) /* &git.CreateTagOptions{
|
||||||
|
Message: tag,
|
||||||
|
})*/
|
||||||
|
logrus.Info(fmt.Sprintf("Created tag %s at %s.", newTagString, head.Hash()))
|
||||||
|
if Push {
|
||||||
|
if err := repo.Push(&git.PushOptions{}); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
logrus.Info(fmt.Sprintf("Pushed tag %s to remote.", newTagString))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageVersions(recipe recipe.Recipe) map[string]string {
|
||||||
|
|
||||||
|
var services = make(map[string]string)
|
||||||
|
for _, service := range recipe.Config.Services {
|
||||||
|
srv := strings.Split(service.Image, ":")
|
||||||
|
services[srv[0]] = srv[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMainApp(recipe recipe.Recipe) string {
|
||||||
|
for _, service := range recipe.Config.Services {
|
||||||
|
name := service.Name
|
||||||
|
if name == "app" {
|
||||||
|
return strings.Split(service.Image, ":")[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func btoi(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user