feat: tag recipes with abra #99

Merged
decentral1se merged 5 commits from knoflook/abra:recipe-release into main 2021-09-29 12:39:36 +00:00
2 changed files with 124 additions and 0 deletions
Showing only changes of commit 48d28c8dd1 - Show all commits

View File

@ -18,6 +18,7 @@ Cloud community and you can use Abra to read them and create apps for you.
Subcommands: []*cli.Command{
recipeListCommand,
recipeVersionCommand,
recipeReleaseCommand,
recipeNewCommand,
recipeUpgradeCommand,
recipeSyncCommand,

123
cli/recipe/release.go Normal file
View File

@ -0,0 +1,123 @@
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)
knoflook marked this conversation as resolved Outdated

This block is all done in internal.ValidateRecipe(c) already.

This block is all done in `internal.ValidateRecipe(c)` already.
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) {
knoflook marked this conversation as resolved Outdated

The thing is, most versions are not strictly semver so we'd only be able to cover a tiny amount of the recipes we have. But we've already got tagcmp which can handle discovering what is a patch/minor/major upgrade and these formats are supported. So then we just need to check if it IsParsable?

The thing is, most versions are not strictly semver so we'd only be able to cover a tiny amount of the recipes we have. But we've already got `tagcmp` which can handle discovering what is a patch/minor/major upgrade and [these formats](https://git.coopcloud.tech/coop-cloud/tagcmp#types-of-versions-supported) are supported. So then we just need to check if it [`IsParsable`](https://git.coopcloud.tech/coop-cloud/tagcmp/src/branch/main/godoc.md#user-content-func-isparsable)?
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
knoflook marked this conversation as resolved Outdated

(from recipe.EnsureVersion)

repo, err := git.PlainOpen(directory)
if err != nil {
    return err
}

tags, err := repo.Tags()
if err != nil {
    return nil
}
(from `recipe.EnsureVersion`) ```golang repo, err := git.PlainOpen(directory) if err != nil { return err } tags, err := repo.Tags() if err != nil { return nil } ```
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
}