From 7f7f7224c683f018fa7aadcc327a64982f084e3e Mon Sep 17 00:00:00 2001 From: decentral1se Date: Sun, 15 Oct 2023 13:39:04 +0200 Subject: [PATCH] feat: diff on release flow Also, don't commit unstaged files. --- cli/catalogue/catalogue.go | 2 +- cli/recipe/diff.go | 27 ++--------------- cli/recipe/release.go | 14 ++++++++- cli/recipe/sync.go | 12 ++++++++ cli/recipe/upgrade.go | 14 +++++++++ pkg/git/commit.go | 15 ++-------- pkg/git/diff.go | 42 +++++++++++++++++++++++++++ tests/integration/recipe_release.bats | 19 ++++++++++++ 8 files changed, 107 insertions(+), 38 deletions(-) create mode 100644 pkg/git/diff.go diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index 7c97372f..9a54342c 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -173,7 +173,7 @@ keys configured on your account. } msg := "chore: publish new catalogue release changes" - if err := gitPkg.Commit(cataloguePath, "**.json", msg, internal.Dry); err != nil { + if err := gitPkg.Commit(cataloguePath, msg, internal.Dry); err != nil { logrus.Fatal(err) } diff --git a/cli/recipe/diff.go b/cli/recipe/diff.go index 7067300d..f505bbe6 100644 --- a/cli/recipe/diff.go +++ b/cli/recipe/diff.go @@ -1,29 +1,16 @@ package recipe import ( - "fmt" - "os/exec" "path" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/config" + gitPkg "coopcloud.tech/abra/pkg/git" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) -// getGitDiffArgs builds the `git diff` invocation args -func getGitDiffArgs(repoPath string) []string { - return []string{ - "-C", - repoPath, - "--no-pager", - "-c", - "color.diff=always", - "diff", - } -} - var recipeDiffCommand = cli.Command{ Name: "diff", Usage: "Show unstaged changes in recipe config", @@ -43,19 +30,11 @@ var recipeDiffCommand = cli.Command{ internal.ValidateRecipe(c) } - _, err := exec.LookPath("git") - if err != nil { - logrus.Fatal("unable to locate 'git' command?") - } - - gitDiffArgs := getGitDiffArgs(path.Join(config.RECIPES_DIR, recipeName)) - diff, err := exec.Command("git", gitDiffArgs...).Output() - if err != nil { + recipeDir := path.Join(config.RECIPES_DIR, recipeName) + if err := gitPkg.DiffUnstaged(recipeDir); err != nil { logrus.Fatal(err) } - fmt.Print(string(diff)) - return nil }, } diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 3ce13ac6..74cc83bd 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -106,6 +106,18 @@ your SSH keys configured on your account. } } + isClean, err := gitPkg.IsClean(recipe.Dir()) + if err != nil { + logrus.Fatal(err) + } + + if !isClean { + logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) + if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { + logrus.Fatal(err) + } + } + if len(tags) > 0 { logrus.Warnf("previous git tags detected, assuming this is a new semver release") if err := createReleaseFromPreviousTag(tagString, mainAppVersion, recipe, tags); err != nil { @@ -244,7 +256,7 @@ func commitRelease(recipe recipe.Recipe, tag string) error { msg := fmt.Sprintf("chore: publish %s release", tag) repoPath := path.Join(config.RECIPES_DIR, recipe.Name) - if err := gitPkg.Commit(repoPath, ".", msg, internal.Dry); err != nil { + if err := gitPkg.Commit(repoPath, msg, internal.Dry); err != nil { return err } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 1085a193..d5b4ad00 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -8,6 +8,7 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/config" + gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" "github.com/go-git/go-git/v5" @@ -198,6 +199,17 @@ likely to change. logrus.Infof("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name) } + isClean, err := gitPkg.IsClean(recipe.Dir()) + if err != nil { + logrus.Fatal(err) + } + if !isClean { + logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) + if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { + logrus.Fatal(err) + } + } + return nil }, } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index aa258f16..4a4a33e2 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -14,6 +14,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" + gitPkg "coopcloud.tech/abra/pkg/git" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" @@ -326,6 +327,7 @@ You may invoke this command in "wizard" mode and be prompted for input: } fmt.Println(string(jsonstring)) + return nil } @@ -336,6 +338,18 @@ You may invoke this command in "wizard" mode and be prompted for input: } } } + + isClean, err := gitPkg.IsClean(recipeDir) + if err != nil { + logrus.Fatal(err) + } + if !isClean { + logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) + if err := gitPkg.DiffUnstaged(recipeDir); err != nil { + logrus.Fatal(err) + } + } + return nil }, } diff --git a/pkg/git/commit.go b/pkg/git/commit.go index a3c6433f..4b0e554b 100644 --- a/pkg/git/commit.go +++ b/pkg/git/commit.go @@ -8,7 +8,7 @@ import ( ) // Commit runs a git commit -func Commit(repoPath, glob, commitMessage string, dryRun bool) error { +func Commit(repoPath, commitMessage string, dryRun bool) error { if commitMessage == "" { return fmt.Errorf("no commit message specified?") } @@ -33,17 +33,8 @@ func Commit(repoPath, glob, commitMessage string, dryRun bool) error { } if !dryRun { - err = commitWorktree.AddGlob(glob) - if err != nil { - return err - } - logrus.Debugf("staged %s for commit", glob) - } else { - logrus.Debugf("dry run: did not stage %s for commit", glob) - } - - if !dryRun { - _, err = commitWorktree.Commit(commitMessage, &git.CommitOptions{}) + // NOTE(d1): `All: true` does not include untracked files + _, err = commitWorktree.Commit(commitMessage, &git.CommitOptions{All: true}) if err != nil { return err } diff --git a/pkg/git/diff.go b/pkg/git/diff.go new file mode 100644 index 00000000..65a658f8 --- /dev/null +++ b/pkg/git/diff.go @@ -0,0 +1,42 @@ +package git + +import ( + "fmt" + "os/exec" + + "github.com/sirupsen/logrus" +) + +// getGitDiffArgs builds the `git diff` invocation args. It removes the usage +// of a pager and ensures that colours are specified even when Git might detect +// otherwise. +func getGitDiffArgs(repoPath string) []string { + return []string{ + "-C", + repoPath, + "--no-pager", + "-c", + "color.diff=always", + "diff", + } +} + +// DiffUnstaged shows a `git diff`. Due to limitations in the underlying go-git +// library, this implementation requires the /usr/bin/git binary. It gracefully +// skips if it cannot find the command on the system. +func DiffUnstaged(path string) error { + if _, err := exec.LookPath("git"); err != nil { + logrus.Warnf("unable to locate git command, cannot output diff") + return nil + } + + gitDiffArgs := getGitDiffArgs(path) + diff, err := exec.Command("git", gitDiffArgs...).Output() + if err != nil { + return nil + } + + fmt.Print(string(diff)) + + return nil +} diff --git a/tests/integration/recipe_release.bats b/tests/integration/recipe_release.bats index a847206c..2ebe226c 100644 --- a/tests/integration/recipe_release.bats +++ b/tests/integration/recipe_release.bats @@ -84,3 +84,22 @@ setup(){ _reset_recipe "$TEST_RECIPE" } + +@test "unknown files not committed" { + run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch + assert_success + + run bash -c 'echo "unstaged changes" >> "$ABRA_DIR/recipes/$TEST_RECIPE/foo"' + assert_success + assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo" + + run $ABRA recipe release "$TEST_RECIPE" --no-input --patch + assert_success + assert_output --partial 'no -p/--publish passed, not publishing' + + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" rm foo + assert_failure + assert_output --partial "fatal: pathspec 'foo' did not match any files" + + _reset_recipe +}