diff --git a/internal/hooks/hooks.go b/internal/hooks/hooks.go new file mode 100644 index 0000000..1b51195 --- /dev/null +++ b/internal/hooks/hooks.go @@ -0,0 +1,71 @@ +package hooks + +import ( + "bufio" + "os/exec" + "strings" + + "github.com/Nightapes/go-semantic-release/internal/shared" + "github.com/Nightapes/go-semantic-release/pkg/config" + log "github.com/sirupsen/logrus" +) + +//Hooks struct +type Hooks struct { + version *shared.ReleaseVersion + config *config.ReleaseConfig +} + +// New hooks struct +func New(config *config.ReleaseConfig, version *shared.ReleaseVersion) *Hooks { + return &Hooks{ + config: config, + version: version, + } +} + +// PreRelease runs before creating release +func (h *Hooks) PreRelease() error { + log.Infof("Run pre release hooks") + for _, cmd := range h.config.Hooks.PreRelease { + log.Debugf("Run %s", cmd) + err := h.runCommand(cmd) + if err != nil { + return err + } + } + return nil +} + +// PostRelease runs after creating release +func (h *Hooks) PostRelease() error { + log.Infof("Run post release hooks") + for _, cmd := range h.config.Hooks.PostRelease { + err := h.runCommand(cmd) + if err != nil { + return err + } + } + return nil +} + +func (h *Hooks) runCommand(command string) error { + + splittedCmd := strings.Split(strings.ReplaceAll(command, "$RELEASE_VERSION", h.version.Next.Version.String()), " ") + + cmd := exec.Command(splittedCmd[0], splittedCmd[1:]...) + + cmdReader, err := cmd.StdoutPipe() + if err != nil { + return err + } + + scanner := bufio.NewScanner(cmdReader) + go func() { + for scanner.Scan() { + log.WithField("cmd", splittedCmd[0]).Infof("%s\n", scanner.Text()) + } + }() + + return cmd.Run() +} diff --git a/internal/hooks/hooks_test.go b/internal/hooks/hooks_test.go new file mode 100644 index 0000000..c4b84ec --- /dev/null +++ b/internal/hooks/hooks_test.go @@ -0,0 +1,103 @@ +package hooks_test + +import ( + "os" + "testing" + + "github.com/Masterminds/semver" + "github.com/Nightapes/go-semantic-release/internal/hooks" + "github.com/Nightapes/go-semantic-release/internal/shared" + "github.com/Nightapes/go-semantic-release/pkg/config" + "github.com/stretchr/testify/assert" +) + +func TestPreReleaseHooks(t *testing.T) { + + os.Setenv("GO_WANT_HELPER_PROCESS", "1") + hooks := hooks.New(&config.ReleaseConfig{ + Hooks: config.Hooks{ + PreRelease: []string{ + "go test -test.run=TestHelperProcess -- " + "$RELEASE_VERSION", + }, + }, + }, + &shared.ReleaseVersion{ + Next: shared.ReleaseVersionEntry{ + Version: createVersion("1.0.0"), + }, + }) + err := hooks.PreRelease() + assert.NoError(t, err) + os.Unsetenv("GO_WANT_HELPER_PROCESS") + +} + +func TestPreReleaseHooksError(t *testing.T) { + + hooks := hooks.New(&config.ReleaseConfig{ + Hooks: config.Hooks{ + PreRelease: []string{ + "exit 1", + }, + }, + }, + &shared.ReleaseVersion{ + Next: shared.ReleaseVersionEntry{ + Version: createVersion("1.0.0"), + }, + }) + err := hooks.PreRelease() + assert.Error(t, err) +} + +func TestPostReleaseHooks(t *testing.T) { + + os.Setenv("GO_WANT_HELPER_PROCESS", "1") + hooks := hooks.New(&config.ReleaseConfig{ + Hooks: config.Hooks{ + PostRelease: []string{ + "go test -test.run=TestHelperProcess -- " + "$RELEASE_VERSION", + }, + }, + }, + &shared.ReleaseVersion{ + Next: shared.ReleaseVersionEntry{ + Version: createVersion("1.0.0"), + }, + }) + err := hooks.PostRelease() + assert.NoError(t, err) + os.Unsetenv("GO_WANT_HELPER_PROCESS") + +} + +func TestPostReleaseHooksError(t *testing.T) { + + hooks := hooks.New(&config.ReleaseConfig{ + Hooks: config.Hooks{ + PostRelease: []string{ + "exit 1", + }, + }, + }, + &shared.ReleaseVersion{ + Next: shared.ReleaseVersionEntry{ + Version: createVersion("1.0.0"), + }, + }) + err := hooks.PostRelease() + assert.Error(t, err) +} + +func TestHelperProcess(t *testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + + return + } + assert.Equal(t, "1.0.0", os.Args[3]) +} + +func createVersion(version string) *semver.Version { + ver, _ := semver.NewVersion(version) + return ver +}