124 lines
2.8 KiB
Go
124 lines
2.8 KiB
Go
|
package recipe
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"coopcloud.tech/abra/cli/internal"
|
||
|
"coopcloud.tech/abra/pkg/config"
|
||
|
"coopcloud.tech/abra/pkg/recipe"
|
||
|
"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 Dry bool
|
||
|
var DryFlag = &cli.BoolFlag{
|
||
|
Name: "dry-run",
|
||
|
Value: false,
|
||
|
Destination: &Dry,
|
||
|
}
|
||
|
|
||
|
var recipeReleaseCommand = &cli.Command{
|
||
|
Name: "release",
|
||
|
Usage: "tag a recipe",
|
||
|
Aliases: []string{"rl"},
|
||
|
ArgsUsage: "<recipe> [<tag>]",
|
||
|
Flags: []cli.Flag{
|
||
|
DryFlag,
|
||
|
},
|
||
|
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))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
repo, err := git.PlainOpen(directory)
|
||
|
if err != nil {
|
||
|
logrus.Fatal(err)
|
||
|
}
|
||
|
head, err := repo.Head()
|
||
|
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 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 {
|
||
|
logrus.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if Dry {
|
||
|
logrus.Info(fmt.Sprintf("Dry run only. NOT creating tag %s at %s", tag, head.Hash()))
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
repo.CreateTag(tag, head.Hash(), nil) /* &git.CreateTagOptions{
|
||
|
Message: tag,
|
||
|
})*/
|
||
|
logrus.Info(fmt.Sprintf("Created tag %s at %s.", tag, head.Hash()))
|
||
|
|
||
|
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 isSemver(ver string) bool {
|
||
|
numbers := strings.Split(ver, ".")
|
||
|
if len(numbers) > 3 {
|
||
|
return false
|
||
|
}
|
||
|
for _, part := range numbers {
|
||
|
if _, err := strconv.Atoi(part); err != nil {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|