diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 74cc83bd..c1c0b61d 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -1,7 +1,9 @@ package recipe import ( + "errors" "fmt" + "os" "path" "strconv" "strings" @@ -140,7 +142,7 @@ your SSH keys configured on your account. // getImageVersions retrieves image versions for a recipe func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { - var services = make(map[string]string) + services := make(map[string]string) missingTag := false for _, service := range recipe.Config.Services { @@ -207,6 +209,10 @@ func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string tagString = fmt.Sprintf("%s+%s", tag.String(), mainAppVersion) } + if err := addReleaseNotes(recipe, tagString); err != nil { + logrus.Fatal(err) + } + if err := commitRelease(recipe, tagString); err != nil { logrus.Fatal(err) } @@ -237,6 +243,70 @@ func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { return git.CreateTagOptions{Message: msg}, nil } +// addReleaseNotes checks if the release/next release note exists and moves the +// file to release/. +func addReleaseNotes(recipe recipe.Recipe, tag string) error { + repoPath := path.Join(config.RECIPES_DIR, recipe.Name) + tagReleaseNotePath := path.Join(repoPath, "release", tag) + if _, err := os.Stat(tagReleaseNotePath); err == nil { + // Release note for current tag already exist exists. + return nil + } else if !errors.Is(err, os.ErrNotExist) { + return err + } + + nextReleaseNotePath := path.Join(repoPath, "release", "next") + if _, err := os.Stat(nextReleaseNotePath); err == nil { + // release/next note exists. Move it to release/ + if internal.Dry { + logrus.Debugf("dry run: move release note from 'next' to %s", tag) + return nil + } + err := os.Rename(nextReleaseNotePath, tagReleaseNotePath) + if err != nil { + return err + } + err = gitPkg.Add(repoPath, path.Join("release", "next"), internal.Dry) + if err != nil { + return err + } + err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry) + if err != nil { + return err + } + } else if !errors.Is(err, os.ErrNotExist) { + return err + } + + // No release note exists for the current release. + if internal.NoInput { + return nil + } + prompt := &survey.Input{ + Message: "Release Note (leave empty for no release note)", + } + + var releaseNote string + if err := survey.AskOne(prompt, &releaseNote); err != nil { + return err + } + + if releaseNote == "" { + return nil + } + + err := os.WriteFile(tagReleaseNotePath, []byte(releaseNote), 0644) + if err != nil { + return err + } + err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry) + if err != nil { + return err + } + + return nil +} + func commitRelease(recipe recipe.Recipe, tag string) error { if internal.Dry { logrus.Debugf("dry run: no changes committed") @@ -404,6 +474,10 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip } } + if err := addReleaseNotes(recipe, tagString); err != nil { + logrus.Fatal(err) + } + if err := commitRelease(recipe, tagString); err != nil { logrus.Fatalf("failed to commit changes: %s", err.Error()) } diff --git a/pkg/git/add.go b/pkg/git/add.go new file mode 100644 index 00000000..ead6dd00 --- /dev/null +++ b/pkg/git/add.go @@ -0,0 +1,27 @@ +package git + +import ( + "github.com/go-git/go-git/v5" + "github.com/sirupsen/logrus" +) + +// Add adds a file to the git index. +func Add(repoPath, path string, dryRun bool) error { + repo, err := git.PlainOpen(repoPath) + if err != nil { + return err + } + + worktree, err := repo.Worktree() + if err != nil { + return err + } + + if dryRun { + logrus.Debug("dry run: adding %s", path) + } else { + worktree.Add(path) + } + + return nil +} diff --git a/tests/integration/recipe_release.bats b/tests/integration/recipe_release.bats index 2ebe226c..196b5e59 100644 --- a/tests/integration/recipe_release.bats +++ b/tests/integration/recipe_release.bats @@ -29,6 +29,11 @@ setup(){ # NOTE(d1): relies on only 3 versions being published for the $TEST_RECIPE. @test "release patch bump" { + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.email test@example.com + assert_success + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.name test + assert_success + run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch assert_success @@ -59,6 +64,11 @@ setup(){ # version which could be anything in the future. so, we do our best with # --regexp. @test "release minor bump" { + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.email test@example.com + assert_success + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.name test + assert_success + run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --minor assert_success @@ -86,6 +96,11 @@ setup(){ } @test "unknown files not committed" { + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.email test@example.com + assert_success + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.name test + assert_success + run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch assert_success @@ -103,3 +118,26 @@ setup(){ _reset_recipe } + +# NOTE: relies on 0.2.x being the last minor version +@test "release with next release note" { + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.email test@example.com + assert_success + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" config --local user.name test + assert_success + + run bash -c "echo 'those are some release notes for the next release' >> $ABRA_DIR/recipes/$TEST_RECIPE/release/next" + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" add release/next + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" commit -m "added some release notes" + assert_success + + run $ABRA recipe release "$TEST_RECIPE" --no-input --minor + assert_success + assert_output --partial 'no -p/--publish passed, not publishing' + + assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/release/next" + assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/release/0.3.0+1.21.0" + assert_file_contains "$ABRA_DIR/recipes/$TEST_RECIPE/release/0.3.0+1.21.0" "those are some release notes for the next release" + + _reset_recipe "$TEST_RECIPE" +}