From 1467ae50071dac2a42330209183bd0c9c1bdb038 Mon Sep 17 00:00:00 2001 From: decentral1se Date: Sun, 7 Nov 2021 00:03:01 +0100 Subject: [PATCH] feat: teach catalogue generate to use git --- cli/catalogue/generate.go | 120 ++++++++++++++++++++++++++++++++------ cli/internal/recipe.go | 34 +++++++++++ cli/recipe/release.go | 68 ++++++--------------- 3 files changed, 152 insertions(+), 70 deletions(-) diff --git a/cli/catalogue/generate.go b/cli/catalogue/generate.go index 795d2187d..d58289806 100644 --- a/cli/catalogue/generate.go +++ b/cli/catalogue/generate.go @@ -8,10 +8,13 @@ import ( "path" "coopcloud.tech/abra/cli/formatter" + "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/catalogue" "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/git" + gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/limit" + "github.com/AlecAivazis/survey/v2" + "github.com/go-git/go-git/v5" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -48,26 +51,52 @@ var CatalogueSkipList = map[string]bool{ "tyop": true, } +var commit bool +var commitFlag = &cli.BoolFlag{ + Name: "commit", + Usage: "Commits new generated catalogue changes", + Value: false, + Aliases: []string{"c"}, + Destination: &commit, +} + var catalogueGenerateCommand = &cli.Command{ - Name: "generate", - Aliases: []string{"g"}, - Usage: "Generate a new copy of the catalogue", - ArgsUsage: "[]", - BashComplete: func(c *cli.Context) { - catl, err := catalogue.ReadRecipeCatalogue() - if err != nil { - logrus.Warn(err) - } - if c.NArg() > 0 { - return - } - for name := range catl { - fmt.Println(name) - } + Name: "generate", + Aliases: []string{"g"}, + Usage: "Generate a new copy of the catalogue", + Flags: []cli.Flag{ + internal.PushFlag, + commitFlag, + internal.CommitMessageFlag, }, + Description: ` +This command generates a new copy of the recipe catalogue which can be found on: + + https://recipes.coopcloud.tech + +It polls the entire git.coopcloud.tech/coop-cloud/... recipe repository +listing, parses README and tags to produce recipe metadata and produces a +apps.json file which is placed in your ~/.abra/catalogue/recipes.json. + +It is possible to generate new metadata for a single recipe by passing +. The existing local catalogue will be updated, not overwritten. + +A new catalogue copy can be published to the recipes repository by passing the +"--commit" and "--push" flags. The recipes repository is available here: + + https://git.coopcloud.tech/coop-cloud/recipes + +`, + ArgsUsage: "[]", Action: func(c *cli.Context) error { recipeName := c.Args().First() + catalogueDir := path.Join(config.ABRA_DIR, "catalogue") + url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, "recipes") + if err := gitPkg.Clone(catalogueDir, url); err != nil { + return err + } + repos, err := catalogue.ReadReposMetadata() if err != nil { logrus.Fatal(err) @@ -96,11 +125,11 @@ var catalogueGenerateCommand = &cli.Command{ recipeDir := path.Join(config.ABRA_DIR, "apps", rm.Name) - if err := git.Clone(recipeDir, rm.SSHURL); err != nil { + if err := gitPkg.Clone(recipeDir, rm.SSHURL); err != nil { logrus.Fatal(err) } - if err := git.EnsureUpToDate(recipeDir); err != nil { + if err := gitPkg.EnsureUpToDate(recipeDir); err != nil { logrus.Fatal(err) } @@ -172,8 +201,61 @@ var catalogueGenerateCommand = &cli.Command{ } } - logrus.Infof("generated new recipe catalogue in '%s'", config.APPS_JSON) + cataloguePath := path.Join(config.ABRA_DIR, "catalogue", "recipes.json") + logrus.Infof("generated new recipe catalogue in %s", cataloguePath) + + if commit { + repoPath := path.Join(config.ABRA_DIR, "catalogue") + commitRepo, err := git.PlainOpen(repoPath) + if err != nil { + logrus.Fatal(err) + } + + commitWorktree, err := commitRepo.Worktree() + if err != nil { + logrus.Fatal(err) + } + + if internal.CommitMessage == "" { + prompt := &survey.Input{ + Message: "commit message", + Default: "chore: publish new catalogue changes", + } + if err := survey.AskOne(prompt, &internal.CommitMessage); err != nil { + logrus.Fatal(err) + } + } + + err = commitWorktree.AddGlob("**.json") + if err != nil { + logrus.Fatal(err) + } + logrus.Debug("staged **.json for commit") + + _, err = commitWorktree.Commit(internal.CommitMessage, &git.CommitOptions{}) + if err != nil { + logrus.Fatal(err) + } + logrus.Info("changes commited") + + if err := commitRepo.Push(&git.PushOptions{}); err != nil { + logrus.Fatal(err) + } + logrus.Info("changes pushed") + } return nil }, + BashComplete: func(c *cli.Context) { + catl, err := catalogue.ReadRecipeCatalogue() + if err != nil { + logrus.Warn(err) + } + if c.NArg() > 0 { + return + } + for name := range catl { + fmt.Println(name) + } + }, } diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go index 3e9424e9f..f3c87074c 100644 --- a/cli/internal/recipe.go +++ b/cli/internal/recipe.go @@ -46,6 +46,40 @@ var DryFlag = &cli.BoolFlag{ Destination: &Dry, } +var Push bool +var PushFlag = &cli.BoolFlag{ + Name: "push", + Usage: "Git push changes", + Value: false, + Aliases: []string{"P"}, + Destination: &Push, +} + +var CommitMessage string +var CommitMessageFlag = &cli.StringFlag{ + Name: "commit-message", + Usage: "Commit message (implies --commit)", + Aliases: []string{"cm"}, + Destination: &CommitMessage, +} + +var Commit bool +var CommitFlag = &cli.BoolFlag{ + Name: "commit", + Usage: "Commits compose.**yml file changes to recipe repository", + Value: false, + Aliases: []string{"c"}, + Destination: &Commit, +} + +var TagMessage string +var TagMessageFlag = &cli.StringFlag{ + Name: "tag-comment", + Usage: "Description for release tag", + Aliases: []string{"t", "tm"}, + Destination: &TagMessage, +} + // PromptBumpType prompts for version bump type func PromptBumpType(tagString string) error { if (!Major && !Minor && !Patch) && tagString == "" { diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 461797e1a..ab696f3aa 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -20,40 +20,6 @@ import ( "github.com/urfave/cli/v2" ) -var Push bool -var PushFlag = &cli.BoolFlag{ - Name: "push", - Usage: "Git push changes", - Value: false, - Aliases: []string{"P"}, - Destination: &Push, -} - -var CommitMessage string -var CommitMessageFlag = &cli.StringFlag{ - Name: "commit-message", - Usage: "Commit message (implies --commit)", - Aliases: []string{"cm"}, - Destination: &CommitMessage, -} - -var Commit bool -var CommitFlag = &cli.BoolFlag{ - Name: "commit", - Usage: "Commits compose.**yml file changes to recipe repository", - Value: false, - Aliases: []string{"c"}, - Destination: &Commit, -} - -var TagMessage string -var TagMessageFlag = &cli.StringFlag{ - Name: "tag-comment", - Usage: "Description for release tag", - Aliases: []string{"t", "tm"}, - Destination: &TagMessage, -} - var recipeReleaseCommand = &cli.Command{ Name: "release", Usage: "Release a new recipe version", @@ -90,10 +56,10 @@ You may invoke this command in "wizard" mode and be prompted for input: internal.MajorFlag, internal.MinorFlag, internal.PatchFlag, - PushFlag, - CommitFlag, - CommitMessageFlag, - TagMessageFlag, + internal.PushFlag, + internal.CommitFlag, + internal.CommitMessageFlag, + internal.TagMessageFlag, }, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipeWithPrompt(c) @@ -142,38 +108,38 @@ You may invoke this command in "wizard" mode and be prompted for input: logrus.Fatal(err) } - if TagMessage == "" { + if internal.TagMessage == "" { prompt := &survey.Input{ Message: "tag message", Default: fmt.Sprintf("chore: publish new %s version", internal.GetBumpType()), } - if err := survey.AskOne(prompt, &TagMessage); err != nil { + if err := survey.AskOne(prompt, &internal.TagMessage); err != nil { logrus.Fatal(err) } } var createTagOptions git.CreateTagOptions - createTagOptions.Message = TagMessage + createTagOptions.Message = internal.TagMessage - if !Commit { + if !internal.Commit { prompt := &survey.Confirm{ Message: "git commit changes also?", } - if err := survey.AskOne(prompt, &Commit); err != nil { + if err := survey.AskOne(prompt, &internal.Commit); err != nil { return err } } - if !Push { + if !internal.Push { prompt := &survey.Confirm{ Message: "git push changes also?", } - if err := survey.AskOne(prompt, &Push); err != nil { + if err := survey.AskOne(prompt, &internal.Push); err != nil { return err } } - if Commit || CommitMessage != "" { + if internal.Commit || internal.CommitMessage != "" { commitRepo, err := git.PlainOpen(directory) if err != nil { logrus.Fatal(err) @@ -183,12 +149,12 @@ You may invoke this command in "wizard" mode and be prompted for input: logrus.Fatal(err) } - if CommitMessage == "" { + if internal.CommitMessage == "" { prompt := &survey.Input{ Message: "commit message", Default: fmt.Sprintf("chore: publish new %s version", internal.GetBumpType()), } - if err := survey.AskOne(prompt, &CommitMessage); err != nil { + if err := survey.AskOne(prompt, &internal.CommitMessage); err != nil { logrus.Fatal(err) } } @@ -200,7 +166,7 @@ You may invoke this command in "wizard" mode and be prompted for input: logrus.Debug("staged compose.**yml for commit") if !internal.Dry { - _, err = commitWorktree.Commit(CommitMessage, &git.CommitOptions{}) + _, err = commitWorktree.Commit(internal.CommitMessage, &git.CommitOptions{}) if err != nil { logrus.Fatal(err) } @@ -242,7 +208,7 @@ You may invoke this command in "wizard" mode and be prompted for input: repo.CreateTag(tagString, head.Hash(), &createTagOptions) hash := abraFormatter.SmallSHA(head.Hash().String()) logrus.Info(fmt.Sprintf("created tag %s at %s", tagString, hash)) - if Push && !internal.Dry { + if internal.Push && !internal.Dry { if err := repo.Push(&git.PushOptions{}); err != nil { logrus.Fatal(err) } @@ -317,7 +283,7 @@ You may invoke this command in "wizard" mode and be prompted for input: repo.CreateTag(newtagString, head.Hash(), &createTagOptions) hash := abraFormatter.SmallSHA(head.Hash().String()) logrus.Info(fmt.Sprintf("created tag %s at %s", newtagString, hash)) - if Push && !internal.Dry { + if internal.Push && !internal.Dry { if err := repo.Push(&git.PushOptions{}); err != nil { logrus.Fatal(err) }