abra/cli/catalogue/catalogue.go

224 lines
5.8 KiB
Go
Raw Normal View History

package catalogue
import (
"encoding/json"
"fmt"
"io/ioutil"
"path"
"coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/catalogue"
"coopcloud.tech/abra/pkg/config"
2021-12-28 00:24:23 +00:00
"coopcloud.tech/abra/pkg/formatter"
gitPkg "coopcloud.tech/abra/pkg/git"
"coopcloud.tech/abra/pkg/recipe"
"github.com/go-git/go-git/v5"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var catalogueGenerateCommand = cli.Command{
Name: "generate",
Aliases: []string{"g"},
2021-12-27 18:56:27 +00:00
Usage: "Generate the recipe catalogue",
Flags: []cli.Flag{
internal.DebugFlag,
internal.NoInputFlag,
2021-12-27 18:56:27 +00:00
internal.PublishFlag,
internal.DryFlag,
internal.SkipUpdatesFlag,
2023-09-07 16:50:25 +00:00
internal.ChaosFlag,
internal.OfflineFlag,
},
Before: internal.SubCommandBefore,
Description: `
2022-05-13 14:44:49 +00:00
Generate a new copy of the recipe catalogue which can be found on:
2022-05-03 15:08:40 +00:00
https://recipes.coopcloud.tech (website that humans read)
https://recipes.coopcloud.tech/recipes.json (JSON that Abra reads)
It polls the entire git.coopcloud.tech/coop-cloud/... recipe repository
2022-05-13 14:44:49 +00:00
listing, parses README.md and git tags to produce recipe metadata which is
loaded into the catalogue JSON file.
It is possible to generate new metadata for a single recipe by passing
<recipe>. The existing local catalogue will be updated, not overwritten.
2021-12-27 02:27:05 +00:00
It is quite easy to get rate limited by Docker Hub when running this command.
If you have a Hub account you can have Abra log you in to avoid this. Pass
2021-12-27 18:56:27 +00:00
"--user" and "--pass".
2023-01-23 17:48:51 +00:00
Push your new release to git.coopcloud.tech with "-p/--publish". This requires
2021-12-27 18:56:27 +00:00
that you have permission to git push to these repositories and have your SSH
keys configured on your account.
`,
2023-09-07 16:50:25 +00:00
ArgsUsage: "[<recipe>]",
BashComplete: autocomplete.RecipeNameComplete,
Action: func(c *cli.Context) error {
recipeName := c.Args().First()
if recipeName != "" {
2023-09-07 16:50:25 +00:00
internal.ValidateRecipe(c)
}
2023-09-07 16:50:25 +00:00
if !internal.Chaos {
if err := catalogue.EnsureIsClean(); err != nil {
logrus.Fatal(err)
}
}
2023-09-07 16:50:25 +00:00
repos, err := recipe.ReadReposMetadata()
if err != nil {
logrus.Fatal(err)
}
2021-12-19 22:23:46 +00:00
var barLength int
var logMsg string
2021-12-19 22:23:46 +00:00
if recipeName != "" {
barLength = 1
2021-12-28 02:42:44 +00:00
logMsg = fmt.Sprintf("ensuring %v recipe is cloned & up-to-date", barLength)
2021-12-19 22:23:46 +00:00
} else {
barLength = len(repos)
2021-12-27 17:06:46 +00:00
logMsg = fmt.Sprintf("ensuring %v recipes are cloned & up-to-date, this could take some time...", barLength)
2021-12-19 22:23:46 +00:00
}
if !internal.SkipUpdates {
logrus.Warn(logMsg)
2023-09-07 16:50:25 +00:00
if err := recipe.UpdateRepositories(repos, recipeName); err != nil {
logrus.Fatal(err)
}
}
catl := make(recipe.RecipeCatalogue)
2021-12-19 22:23:46 +00:00
catlBar := formatter.CreateProgressbar(barLength, "generating catalogue metadata...")
for _, recipeMeta := range repos {
if recipeName != "" && recipeName != recipeMeta.Name {
catlBar.Add(1)
continue
}
2023-09-07 16:50:25 +00:00
versions, err := recipe.GetRecipeVersions(recipeMeta.Name, internal.Offline)
if err != nil {
logrus.Warn(err)
}
features, category, err := recipe.GetRecipeFeaturesAndCategory(recipeMeta.Name)
if err != nil {
logrus.Warn(err)
}
catl[recipeMeta.Name] = recipe.RecipeMeta{
Name: recipeMeta.Name,
Repository: recipeMeta.CloneURL,
SSHURL: recipeMeta.SSHURL,
Icon: recipeMeta.AvatarURL,
DefaultBranch: recipeMeta.DefaultBranch,
Description: recipeMeta.Description,
Website: recipeMeta.Website,
Versions: versions,
Category: category,
Features: features,
}
catlBar.Add(1)
}
recipesJSON, err := json.MarshalIndent(catl, "", " ")
if err != nil {
logrus.Fatal(err)
}
if recipeName == "" {
2021-12-25 13:04:07 +00:00
if err := ioutil.WriteFile(config.RECIPES_JSON, recipesJSON, 0764); err != nil {
logrus.Fatal(err)
}
} else {
2023-09-07 16:50:25 +00:00
catlFS, err := recipe.ReadRecipeCatalogue(internal.Offline)
if err != nil {
logrus.Fatal(err)
}
catlFS[recipeName] = catl[recipeName]
updatedRecipesJSON, err := json.MarshalIndent(catlFS, "", " ")
if err != nil {
logrus.Fatal(err)
}
if err := ioutil.WriteFile(config.RECIPES_JSON, updatedRecipesJSON, 0764); err != nil {
logrus.Fatal(err)
}
}
2021-12-25 13:04:07 +00:00
logrus.Infof("generated new recipe catalogue in %s", config.RECIPES_JSON)
2021-12-28 01:37:35 +00:00
cataloguePath := path.Join(config.ABRA_DIR, "catalogue")
2021-12-27 18:56:27 +00:00
if internal.Publish {
isClean, err := gitPkg.IsClean(cataloguePath)
if err != nil {
logrus.Fatal(err)
}
2021-12-27 18:56:27 +00:00
if isClean {
if !internal.Dry {
logrus.Fatalf("no changes discovered in %s, nothing to publish?", cataloguePath)
}
2021-12-27 18:56:27 +00:00
}
msg := "chore: publish new catalogue release changes"
if err := gitPkg.Commit(cataloguePath, msg, internal.Dry); err != nil {
logrus.Fatal(err)
}
2021-12-23 01:24:43 +00:00
2021-12-27 18:56:27 +00:00
repo, err := git.PlainOpen(cataloguePath)
if err != nil {
logrus.Fatal(err)
}
2022-02-07 23:57:31 +00:00
sshURL := fmt.Sprintf(config.SSH_URL_TEMPLATE, config.CATALOGUE_JSON_REPO_NAME)
2021-12-27 18:56:27 +00:00
if err := gitPkg.CreateRemote(repo, "origin-ssh", sshURL, internal.Dry); err != nil {
logrus.Fatal(err)
}
2021-12-27 18:56:27 +00:00
if err := gitPkg.Push(cataloguePath, "origin-ssh", false, internal.Dry); err != nil {
logrus.Fatal(err)
2021-12-23 01:24:43 +00:00
}
}
2021-12-28 01:37:35 +00:00
repo, err := git.PlainOpen(cataloguePath)
if err != nil {
logrus.Fatal(err)
}
head, err := repo.Head()
if err != nil {
logrus.Fatal(err)
}
if !internal.Dry && internal.Publish {
2022-02-07 23:57:31 +00:00
url := fmt.Sprintf("%s/%s/commit/%s", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME, head.Hash())
2021-12-27 18:56:27 +00:00
logrus.Infof("new changes published: %s", url)
}
if internal.Dry {
logrus.Info("dry run: no changes published")
2021-12-27 18:56:27 +00:00
}
return nil
},
}
// CatalogueCommand defines the `abra catalogue` command and sub-commands.
var CatalogueCommand = cli.Command{
Name: "catalogue",
2021-12-19 23:15:42 +00:00
Usage: "Manage the recipe catalogue",
Aliases: []string{"c"},
ArgsUsage: "<recipe>",
Description: "This command helps recipe packagers interact with the recipe catalogue",
Subcommands: []cli.Command{
catalogueGenerateCommand,
},
}