From 0aa37fcee8c7dc42d1a75c8753b8b6ee658889d9 Mon Sep 17 00:00:00 2001
From: cellarspoon <cellarspoon@riseup.net>
Date: Mon, 27 Dec 2021 19:56:27 +0100
Subject: [PATCH] refactor!: simplifying publish logic

---
 cli/catalogue/catalogue.go |  78 ++++++++++++++--------------
 cli/internal/common.go     |  45 ++++-------------
 cli/internal/recipe.go     |  28 ++++++----
 cli/recipe/release.go      | 101 +++++++++++++++----------------------
 cli/recipe/sync.go         |  20 ++++----
 cli/recipe/upgrade.go      |   4 +-
 pkg/git/commit.go          |   4 +-
 pkg/git/push.go            |   6 +--
 pkg/git/read.go            |  10 ++--
 pkg/recipe/recipe.go       |   9 ++--
 10 files changed, 137 insertions(+), 168 deletions(-)

diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go
index 6138d3b1f4..02f13cd11b 100644
--- a/cli/catalogue/catalogue.go
+++ b/cli/catalogue/catalogue.go
@@ -13,7 +13,6 @@ import (
 	gitPkg "coopcloud.tech/abra/pkg/git"
 	"coopcloud.tech/abra/pkg/limit"
 	"coopcloud.tech/abra/pkg/recipe"
-	"github.com/AlecAivazis/survey/v2"
 	"github.com/go-git/go-git/v5"
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli/v2"
@@ -59,11 +58,9 @@ var CatalogueSkipList = map[string]bool{
 var catalogueGenerateCommand = &cli.Command{
 	Name:    "generate",
 	Aliases: []string{"g"},
-	Usage:   "Generate a new copy of the recipe catalogue",
+	Usage:   "Generate the recipe catalogue",
 	Flags: []cli.Flag{
-		internal.PushFlag,
-		internal.CommitFlag,
-		internal.CommitMessageFlag,
+		internal.PublishFlag,
 		internal.DryFlag,
 		internal.SkipUpdatesFlag,
 		internal.RegistryUsernameFlag,
@@ -81,14 +78,13 @@ metadata and produces a recipes 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.
 
-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
-
 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
-"--username" and "--password".
+"--user" and "--pass".
+
+Push your new release git.coopcloud.tech with "-p/--publish". This requires
+that you have permission to git push to these repositories and have your SSH
+keys configured on your account.
 `,
 	ArgsUsage: "[<recipe>]",
 	Action: func(c *cli.Context) error {
@@ -197,37 +193,43 @@ If you have a Hub account you can have Abra log you in to avoid this. Pass
 
 		logrus.Infof("generated new recipe catalogue in %s", config.RECIPES_JSON)
 
-		if internal.Commit {
-			if internal.CommitMessage == "" && !internal.NoInput {
-				prompt := &survey.Input{
-					Message: "commit message",
-					Default: fmt.Sprintf("chore: publish catalogue changes"),
-				}
-				if err := survey.AskOne(prompt, &internal.CommitMessage); err != nil {
-					logrus.Fatal(err)
-				}
-			}
-
+		if internal.Publish {
 			cataloguePath := path.Join(config.ABRA_DIR, "catalogue")
-			if err := gitPkg.Commit(cataloguePath, "**.json", internal.CommitMessage, internal.Dry); err != nil {
+
+			isClean, err := gitPkg.IsClean(cataloguePath)
+			if err != nil {
 				logrus.Fatal(err)
 			}
 
-			if internal.Push {
-				repo, err := git.PlainOpen(cataloguePath)
-				if err != nil {
-					logrus.Fatal(err)
-				}
-
-				sshURL := fmt.Sprintf(config.SSH_URL_TEMPLATE, "recipes")
-				if err := gitPkg.CreateRemote(repo, "origin-ssh", sshURL, internal.Dry); err != nil {
-					logrus.Fatal(err)
-				}
-
-				if err := gitPkg.Push(cataloguePath, "origin-ssh", false, internal.Dry); err != nil {
-					logrus.Fatal(err)
-				}
+			if isClean {
+				logrus.Fatalf("no changes discovered in %s, nothing to publish?", cataloguePath)
 			}
+
+			msg := "chore: publish new catalogue release changes"
+			if err := gitPkg.Commit(cataloguePath, "**.json", msg, internal.Dry); err != nil {
+				logrus.Fatal(err)
+			}
+
+			repo, err := git.PlainOpen(cataloguePath)
+			if err != nil {
+				logrus.Fatal(err)
+			}
+
+			sshURL := fmt.Sprintf(config.SSH_URL_TEMPLATE, "recipes")
+			if err := gitPkg.CreateRemote(repo, "origin-ssh", sshURL, internal.Dry); err != nil {
+				logrus.Fatal(err)
+			}
+
+			if err := gitPkg.Push(cataloguePath, "origin-ssh", false, internal.Dry); err != nil {
+				logrus.Fatal(err)
+			}
+		}
+
+		if internal.Dry {
+			logrus.Info("dry run: no changes published")
+		} else {
+			url := fmt.Sprintf("%s/recipes", config.REPOS_BASE_URL)
+			logrus.Infof("new changes published: %s", url)
 		}
 
 		return nil
@@ -281,7 +283,7 @@ func updateRepositories(repos recipe.RepoCatalogue, recipeName string) error {
 				logrus.Fatal(err)
 			}
 
-			isClean, err := gitPkg.IsClean(rm.Name)
+			isClean, err := gitPkg.IsClean(recipeDir)
 			if err != nil {
 				logrus.Fatal(err)
 			}
diff --git a/cli/internal/common.go b/cli/internal/common.go
index b3833e9ba8..17a02fefb4 100644
--- a/cli/internal/common.go
+++ b/cli/internal/common.go
@@ -306,7 +306,7 @@ var PatchFlag = &cli.BoolFlag{
 	Name:        "patch",
 	Usage:       "Increase the patch part of the version",
 	Value:       false,
-	Aliases:     []string{"p", "z"},
+	Aliases:     []string{"pa", "z"},
 	Destination: &Patch,
 }
 
@@ -319,38 +319,13 @@ var DryFlag = &cli.BoolFlag{
 	Destination: &Dry,
 }
 
-var Push bool
-var PushFlag = &cli.BoolFlag{
-	Name:        "push",
-	Usage:       "Git push changes",
+var Publish bool
+var PublishFlag = &cli.BoolFlag{
+	Name:        "publish",
+	Usage:       "Publish changes to git.coopcloud.tech",
 	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:       "Commit new changes",
-	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,
+	Aliases:     []string{"p"},
+	Destination: &Publish,
 }
 
 var Domain string
@@ -439,14 +414,14 @@ var SkipUpdatesFlag = &cli.BoolFlag{
 	Name:        "skip-updates",
 	Aliases:     []string{"s"},
 	Value:       false,
-	Usage:       "Skip updating git repositories",
+	Usage:       "Skip updating recipe repositories",
 	Destination: &SkipUpdates,
 }
 
 var RegistryUsername string
 var RegistryUsernameFlag = &cli.StringFlag{
 	Name:        "username",
-	Aliases:     []string{"u"},
+	Aliases:     []string{"user"},
 	Value:       "",
 	Usage:       "Registry username",
 	EnvVars:     []string{"REGISTRY_USERNAME"},
@@ -456,7 +431,7 @@ var RegistryUsernameFlag = &cli.StringFlag{
 var RegistryPassword string
 var RegistryPasswordFlag = &cli.StringFlag{
 	Name:        "password",
-	Aliases:     []string{"p"},
+	Aliases:     []string{"pass"},
 	Value:       "",
 	Usage:       "Registry password",
 	EnvVars:     []string{"REGISTRY_PASSWORD"},
diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go
index 889bdc1d61..154afdcc70 100644
--- a/cli/internal/recipe.go
+++ b/cli/internal/recipe.go
@@ -6,6 +6,7 @@ import (
 
 	"coopcloud.tech/abra/pkg/recipe"
 	"github.com/AlecAivazis/survey/v2"
+	"github.com/docker/distribution/reference"
 	"github.com/sirupsen/logrus"
 )
 
@@ -64,20 +65,29 @@ func SetBumpType(bumpType string) {
 	}
 }
 
-// GetMainApp retrieves the main 'app' image name
-func GetMainApp(recipe recipe.Recipe) string {
-	var app string
+// GetMainAppImage retrieves the main 'app' image name
+func GetMainAppImage(recipe recipe.Recipe) (string, error) {
+	var path string
 
 	for _, service := range recipe.Config.Services {
-		name := service.Name
-		if name == "app" {
-			app = strings.Split(service.Image, ":")[0]
+		if service.Name == "app" {
+			img, err := reference.ParseNormalizedNamed(service.Image)
+			if err != nil {
+				return "", err
+			}
+
+			path = reference.Path(img)
+			if strings.Contains(path, "library") {
+				path = strings.Split(path, "/")[1]
+			}
+
+			return path, nil
 		}
 	}
 
-	if app == "" {
-		logrus.Fatalf("%s has no main 'app' service?", recipe.Name)
+	if path == "" {
+		return path, fmt.Errorf("%s has no main 'app' service?", recipe.Name)
 	}
 
-	return app
+	return path, nil
 }
diff --git a/cli/recipe/release.go b/cli/recipe/release.go
index 723a4052ee..97f6fccad4 100644
--- a/cli/recipe/release.go
+++ b/cli/recipe/release.go
@@ -47,20 +47,16 @@ Abra does its best to read the "a.b.c" version scheme and communicate what
 action needs to be taken when performing different operations such as an update
 or a rollback of an app.
 
-You may invoke this command in "wizard" mode and be prompted for input:
-
-    abra recipe release gitea
-
+Publish your new release git.coopcloud.tech with "-p/--publish". This requires
+that you have permission to git push to these repositories and have your SSH
+keys configured on your account.
 `,
 	Flags: []cli.Flag{
 		internal.DryFlag,
 		internal.MajorFlag,
 		internal.MinorFlag,
 		internal.PatchFlag,
-		internal.PushFlag,
-		internal.CommitFlag,
-		internal.CommitMessageFlag,
-		internal.TagMessageFlag,
+		internal.PublishFlag,
 	},
 	BashComplete: autocomplete.RecipeNameComplete,
 	Action: func(c *cli.Context) error {
@@ -71,7 +67,11 @@ You may invoke this command in "wizard" mode and be prompted for input:
 			logrus.Fatal(err)
 		}
 
-		mainApp := internal.GetMainApp(recipe)
+		mainApp, err := internal.GetMainAppImage(recipe)
+		if err != nil {
+			logrus.Fatal(err)
+		}
+
 		mainAppVersion := imagesTmp[mainApp]
 		if mainAppVersion == "" {
 			logrus.Fatalf("main app service version for %s is empty?", recipe.Name)
@@ -201,14 +201,14 @@ func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string
 		tag.MissingPatch = false
 	}
 
-	if err := commitRelease(recipe); err != nil {
-		logrus.Fatal(err)
-	}
-
 	if tagString == "" {
 		tagString = fmt.Sprintf("%s+%s", tag.String(), mainAppVersion)
 	}
 
+	if err := commitRelease(recipe, tagString); err != nil {
+		logrus.Fatal(err)
+	}
+
 	if err := tagRelease(tagString, repo); err != nil {
 		logrus.Fatal(err)
 	}
@@ -230,50 +230,30 @@ func btoi(b bool) int {
 }
 
 // getTagCreateOptions constructs git tag create options
-func getTagCreateOptions() (git.CreateTagOptions, error) {
-	if internal.TagMessage == "" && !internal.NoInput {
-		prompt := &survey.Input{
-			Message: "git tag message?",
-			Default: "chore: publish new release",
-		}
-
-		if err := survey.AskOne(prompt, &internal.TagMessage); err != nil {
-			return git.CreateTagOptions{}, err
-		}
-	}
-
-	return git.CreateTagOptions{Message: internal.TagMessage}, nil
+func getTagCreateOptions(tag string) (git.CreateTagOptions, error) {
+	msg := fmt.Sprintf("chore: publish %s release", tag)
+	return git.CreateTagOptions{Message: msg}, nil
 }
 
-func commitRelease(recipe recipe.Recipe) error {
+func commitRelease(recipe recipe.Recipe, tag string) error {
 	if internal.Dry {
-		logrus.Info("dry run: no changed committed")
+		logrus.Debugf("dry run: no changes committed")
 		return nil
 	}
 
-	if !internal.Commit && !internal.NoInput {
-		prompt := &survey.Confirm{
-			Message: "git commit changes?",
-		}
-
-		if err := survey.AskOne(prompt, &internal.Commit); err != nil {
-			return err
-		}
+	isClean, err := gitPkg.IsClean(recipe.Dir())
+	if err != nil {
+		return err
 	}
 
-	if internal.CommitMessage == "" && !internal.NoInput && internal.Commit {
-		prompt := &survey.Input{
-			Message: "git commit message?",
-			Default: "chore: publish new version",
-		}
-		if err := survey.AskOne(prompt, &internal.CommitMessage); err != nil {
-			return err
-		}
+	if isClean {
+		return fmt.Errorf("no changes discovered in %s, nothing to publish?", recipe.Dir())
 	}
 
-	if internal.Commit {
+	if internal.Publish {
+		msg := fmt.Sprintf("chore: publish %s release", tag)
 		repoPath := path.Join(config.RECIPES_DIR, recipe.Name)
-		if err := gitPkg.Commit(repoPath, "compose.**yml", internal.CommitMessage, internal.Dry); err != nil {
+		if err := gitPkg.Commit(repoPath, "compose.**yml", msg, internal.Dry); err != nil {
 			return err
 		}
 	}
@@ -283,7 +263,7 @@ func commitRelease(recipe recipe.Recipe) error {
 
 func tagRelease(tagString string, repo *git.Repository) error {
 	if internal.Dry {
-		logrus.Infof("dry run: no git tag created (%s)", tagString)
+		logrus.Debugf("dry run: no git tag created (%s)", tagString)
 		return nil
 	}
 
@@ -292,7 +272,7 @@ func tagRelease(tagString string, repo *git.Repository) error {
 		return err
 	}
 
-	createTagOptions, err := getTagCreateOptions()
+	createTagOptions, err := getTagCreateOptions(tagString)
 	if err != nil {
 		return err
 	}
@@ -303,33 +283,36 @@ func tagRelease(tagString string, repo *git.Repository) error {
 	}
 
 	hash := abraFormatter.SmallSHA(head.Hash().String())
-	logrus.Info(fmt.Sprintf("created tag %s at %s", tagString, hash))
+	logrus.Debugf(fmt.Sprintf("created tag %s at %s", tagString, hash))
 
 	return nil
 }
 
 func pushRelease(recipe recipe.Recipe) error {
 	if internal.Dry {
-		logrus.Info("dry run: no changes pushed")
+		logrus.Info("dry run: no changes published")
 		return nil
 	}
 
-	if !internal.Push && !internal.NoInput {
+	if !internal.Publish && !internal.NoInput {
 		prompt := &survey.Confirm{
-			Message: "git push changes?",
+			Message: "publish new release?",
 		}
 
-		if err := survey.AskOne(prompt, &internal.Push); err != nil {
+		if err := survey.AskOne(prompt, &internal.Publish); err != nil {
 			return err
 		}
 	}
 
-	if internal.Push {
+	if internal.Publish {
 		if err := recipe.Push(internal.Dry); err != nil {
 			return err
 		}
 	}
 
+	url := fmt.Sprintf("%s/%s/tags", config.REPOS_BASE_URL, recipe.Name)
+	logrus.Infof("new release published: %s", url)
+
 	return nil
 }
 
@@ -392,13 +375,13 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip
 		newTag.Major = strconv.Itoa(now + 1)
 	}
 
-	if err := commitRelease(recipe); err != nil {
-		logrus.Fatal(err)
-	}
-
 	newTag.Metadata = mainAppVersion
 	newTagString := newTag.String()
 
+	if err := commitRelease(recipe, newTagString); err != nil {
+		logrus.Fatal(err)
+	}
+
 	if err := tagRelease(newTagString, repo); err != nil {
 		logrus.Fatal(err)
 	}
@@ -422,7 +405,7 @@ func cleanUpTag(tag, recipeName string) error {
 		return err
 	}
 
-	logrus.Warnf("removed freshly created tag %s", tag)
+	logrus.Debugf("removed freshly created tag %s", tag)
 
 	return nil
 }
diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go
index aff5582447..002759e44d 100644
--- a/cli/recipe/sync.go
+++ b/cli/recipe/sync.go
@@ -18,7 +18,7 @@ import (
 
 var recipeSyncCommand = &cli.Command{
 	Name:      "sync",
-	Usage:     "Ensure recipe version labels are up-to-date",
+	Usage:     "Sync recipe version label",
 	Aliases:   []string{"s"},
 	ArgsUsage: "<recipe> [<version>]",
 	Flags: []cli.Flag{
@@ -29,23 +29,21 @@ var recipeSyncCommand = &cli.Command{
 	},
 	Description: `
 This command will generate labels for the main recipe service (i.e. by
-convention, the service named "app") which corresponds to the following format:
+convention, the service named 'app') which corresponds to the following format:
 
     coop-cloud.${STACK_NAME}.version=<version>
 
-The <version> is determined by the recipe maintainer and is specified on the
-command-line. The <recipe> configuration will be updated on the local file
-system.
-
-You may invoke this command in "wizard" mode and be prompted for input:
-
-    abra recipe sync
-
+Where <version> can be specifed on the command-line or Abra can attempt to
+auto-generate it for you. The <recipe> configuration will be updated on the
+local file system.
 `,
 	Action: func(c *cli.Context) error {
 		recipe := internal.ValidateRecipeWithPrompt(c)
 
-		mainApp := internal.GetMainApp(recipe)
+		mainApp, err := internal.GetMainAppImage(recipe)
+		if err != nil {
+			logrus.Fatal(err)
+		}
 
 		imagesTmp, err := getImageVersions(recipe)
 		if err != nil {
diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go
index 02e12a5bcb..908d523524 100644
--- a/cli/recipe/upgrade.go
+++ b/cli/recipe/upgrade.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 
 	"coopcloud.tech/abra/cli/internal"
+	"coopcloud.tech/abra/pkg/autocomplete"
 	"coopcloud.tech/abra/pkg/client"
 	"coopcloud.tech/abra/pkg/config"
 	recipePkg "coopcloud.tech/abra/pkg/recipe"
@@ -42,7 +43,8 @@ You may invoke this command in "wizard" mode and be prompted for input:
     abra recipe upgrade
 
 `,
-	ArgsUsage: "<recipe>",
+	BashComplete: autocomplete.RecipeNameComplete,
+	ArgsUsage:    "<recipe>",
 	Flags: []cli.Flag{
 		internal.PatchFlag,
 		internal.MinorFlag,
diff --git a/pkg/git/commit.go b/pkg/git/commit.go
index 3e1867173a..a3c6433fa2 100644
--- a/pkg/git/commit.go
+++ b/pkg/git/commit.go
@@ -47,9 +47,9 @@ func Commit(repoPath, glob, commitMessage string, dryRun bool) error {
 		if err != nil {
 			return err
 		}
-		logrus.Info("changes commited")
+		logrus.Debug("git changes commited")
 	} else {
-		logrus.Info("dry run: no changes commited")
+		logrus.Debug("dry run: no changes commited")
 	}
 
 	return nil
diff --git a/pkg/git/push.go b/pkg/git/push.go
index d0eeae9d7a..0430d57f1e 100644
--- a/pkg/git/push.go
+++ b/pkg/git/push.go
@@ -9,7 +9,7 @@ import (
 // Push pushes the latest changes & optionally tags to the default remote
 func Push(repoDir string, remote string, tags bool, dryRun bool) error {
 	if dryRun {
-		logrus.Infof("dry run: no git changes pushed in %s", repoDir)
+		logrus.Debugf("dry run: no git changes pushed in %s", repoDir)
 		return nil
 	}
 
@@ -27,7 +27,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error {
 		return err
 	}
 
-	logrus.Info("git changes pushed")
+	logrus.Debugf("git changes pushed")
 
 	if tags {
 		opts.RefSpecs = append(opts.RefSpecs, config.RefSpec("+refs/tags/*:refs/tags/*"))
@@ -36,7 +36,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error {
 			return err
 		}
 
-		logrus.Info("git tags pushed")
+		logrus.Debugf("git tags pushed")
 	}
 
 	return nil
diff --git a/pkg/git/read.go b/pkg/git/read.go
index 4081a6f229..47d74d3386 100644
--- a/pkg/git/read.go
+++ b/pkg/git/read.go
@@ -34,10 +34,8 @@ func GetRecipeHead(recipeName string) (*plumbing.Reference, error) {
 }
 
 // IsClean checks if a repo has unstaged changes
-func IsClean(recipeName string) (bool, error) {
-	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
-
-	repo, err := git.PlainOpen(recipeDir)
+func IsClean(repoPath string) (bool, error) {
+	repo, err := git.PlainOpen(repoPath)
 	if err != nil {
 		return false, err
 	}
@@ -62,9 +60,9 @@ func IsClean(recipeName string) (bool, error) {
 	}
 
 	if status.String() != "" {
-		logrus.Debugf("discovered git status for %s repository: %s", recipeName, status.String())
+		logrus.Debugf("discovered git status in %s: %s", repoPath, status.String())
 	} else {
-		logrus.Debugf("discovered clean git status for %s repository", recipeName)
+		logrus.Debugf("discovered clean git status in %s", repoPath)
 	}
 
 	return status.IsClean(), nil
diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go
index eff3d971b8..3622262f20 100644
--- a/pkg/recipe/recipe.go
+++ b/pkg/recipe/recipe.go
@@ -260,7 +260,7 @@ func EnsureExists(recipeName string) error {
 func EnsureVersion(recipeName, version string) error {
 	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 
-	isClean, err := gitPkg.IsClean(recipeName)
+	isClean, err := gitPkg.IsClean(recipeDir)
 	if err != nil {
 		return err
 	}
@@ -325,7 +325,7 @@ func EnsureVersion(recipeName, version string) error {
 func EnsureLatest(recipeName string) error {
 	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 
-	isClean, err := gitPkg.IsClean(recipeName)
+	isClean, err := gitPkg.IsClean(recipeDir)
 	if err != nil {
 		return err
 	}
@@ -380,7 +380,8 @@ func ChaosVersion(recipeName string) (string, error) {
 
 	version = head.String()[:8]
 
-	isClean, err := gitPkg.IsClean(recipeName)
+	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
+	isClean, err := gitPkg.IsClean(recipeDir)
 	if err != nil {
 		return version, err
 	}
@@ -556,7 +557,7 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err
 func EnsureUpToDate(recipeName string) error {
 	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 
-	isClean, err := gitPkg.IsClean(recipeName)
+	isClean, err := gitPkg.IsClean(recipeDir)
 	if err != nil {
 		return err
 	}