mirror of
https://github.com/goreleaser/goreleaser.git
synced 2024-12-31 01:53:50 +02:00
feat: allow automatic snapshot on dirty state (#1958)
Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
9423da1b60
commit
d8a0f253d1
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -78,15 +78,11 @@ jobs:
|
||||
snapcraft login --with <(echo "$SNAPCRAFT_LOGIN")
|
||||
-
|
||||
name: GoReleaser
|
||||
if: success()
|
||||
if: success() && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/v* ]]; then
|
||||
./goreleaser
|
||||
elif [[ $GITHUB_REF == refs/heads/master ]]; then
|
||||
./goreleaser --snapshot
|
||||
fi
|
||||
./goreleaser --snapshot-auto
|
||||
-
|
||||
name: Clear
|
||||
if: always() && startsWith(github.ref, 'refs/tags/v')
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/apex/log"
|
||||
"github.com/caarlos0/ctrlc"
|
||||
"github.com/fatih/color"
|
||||
"github.com/goreleaser/goreleaser/internal/git"
|
||||
"github.com/goreleaser/goreleaser/internal/middleware"
|
||||
"github.com/goreleaser/goreleaser/internal/pipeline"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
@ -20,6 +21,7 @@ type buildCmd struct {
|
||||
type buildOpts struct {
|
||||
config string
|
||||
snapshot bool
|
||||
snapshotAuto bool
|
||||
skipValidate bool
|
||||
skipPostHooks bool
|
||||
rmDist bool
|
||||
@ -59,6 +61,7 @@ func newBuildCmd() *buildCmd {
|
||||
|
||||
cmd.Flags().StringVarP(&root.opts.config, "config", "f", "", "Load configuration from file")
|
||||
cmd.Flags().BoolVar(&root.opts.snapshot, "snapshot", false, "Generate an unversioned snapshot build, skipping all validations and without publishing any artifacts")
|
||||
cmd.Flags().BoolVar(&root.opts.snapshotAuto, "snapshot-auto", false, "Same as snapshot but only if Git is currently in a dirty state")
|
||||
cmd.Flags().BoolVar(&root.opts.skipValidate, "skip-validate", false, "Skips several sanity checks")
|
||||
cmd.Flags().BoolVar(&root.opts.skipPostHooks, "skip-post-hooks", false, "Skips all post-build hooks")
|
||||
cmd.Flags().BoolVar(&root.opts.rmDist, "rm-dist", false, "Remove the dist folder before building")
|
||||
@ -97,6 +100,9 @@ func setupBuildContext(ctx *context.Context, options buildOpts) *context.Context
|
||||
ctx.Parallelism = options.parallelism
|
||||
log.Debugf("parallelism: %v", ctx.Parallelism)
|
||||
ctx.Snapshot = options.snapshot
|
||||
if _, gitDirty := git.Status(); options.snapshotAuto && gitDirty {
|
||||
ctx.Snapshot = true
|
||||
}
|
||||
ctx.SkipValidate = ctx.Snapshot || options.skipValidate
|
||||
ctx.SkipPostBuildHooks = options.skipPostHooks
|
||||
ctx.RmDist = options.rmDist
|
||||
|
@ -1,8 +1,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -45,6 +48,37 @@ func TestBuildFlags(t *testing.T) {
|
||||
require.True(t, ctx.SkipTokenCheck)
|
||||
})
|
||||
|
||||
t.Run("snapshot auto clean", func(t *testing.T) {
|
||||
testlib.Mktmp(t)
|
||||
testlib.GitInit(t)
|
||||
testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
|
||||
|
||||
var ctx = setup(buildOpts{
|
||||
snapshotAuto: true,
|
||||
})
|
||||
|
||||
require.False(t, ctx.Snapshot)
|
||||
require.False(t, ctx.SkipValidate)
|
||||
})
|
||||
|
||||
t.Run("snapshot auto dirty", func(t *testing.T) {
|
||||
var folder = testlib.Mktmp(t)
|
||||
testlib.GitInit(t)
|
||||
testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
|
||||
testlib.GitAdd(t)
|
||||
testlib.GitCommit(t, "whatever")
|
||||
testlib.GitTag(t, "v0.0.1")
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(folder, "foo"), []byte("foobar"), 0644))
|
||||
|
||||
var ctx = setup(buildOpts{
|
||||
snapshotAuto: true,
|
||||
})
|
||||
|
||||
require.True(t, ctx.Snapshot)
|
||||
require.True(t, ctx.SkipValidate)
|
||||
require.True(t, ctx.SkipTokenCheck)
|
||||
})
|
||||
|
||||
t.Run("skips", func(t *testing.T) {
|
||||
var ctx = setup(buildOpts{
|
||||
skipValidate: true,
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/apex/log"
|
||||
"github.com/caarlos0/ctrlc"
|
||||
"github.com/fatih/color"
|
||||
"github.com/goreleaser/goreleaser/internal/git"
|
||||
"github.com/goreleaser/goreleaser/internal/middleware"
|
||||
"github.com/goreleaser/goreleaser/internal/pipeline"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
@ -23,6 +24,7 @@ type releaseOpts struct {
|
||||
releaseHeader string
|
||||
releaseFooter string
|
||||
snapshot bool
|
||||
snapshotAuto bool
|
||||
skipPublish bool
|
||||
skipSign bool
|
||||
skipValidate bool
|
||||
@ -66,6 +68,7 @@ func newReleaseCmd() *releaseCmd {
|
||||
cmd.Flags().StringVar(&root.opts.releaseHeader, "release-header", "", "Load custom release notes header from a markdown file")
|
||||
cmd.Flags().StringVar(&root.opts.releaseFooter, "release-footer", "", "Load custom release notes footer from a markdown file")
|
||||
cmd.Flags().BoolVar(&root.opts.snapshot, "snapshot", false, "Generate an unversioned snapshot release, skipping all validations and without publishing any artifacts")
|
||||
cmd.Flags().BoolVar(&root.opts.snapshotAuto, "snapshot-auto", false, "Same as snapshot but only if Git is currently in a dirty state")
|
||||
cmd.Flags().BoolVar(&root.opts.skipPublish, "skip-publish", false, "Skips publishing artifacts")
|
||||
cmd.Flags().BoolVar(&root.opts.skipSign, "skip-sign", false, "Skips signing the artifacts")
|
||||
cmd.Flags().BoolVar(&root.opts.skipValidate, "skip-validate", false, "Skips several sanity checks")
|
||||
@ -108,6 +111,9 @@ func setupReleaseContext(ctx *context.Context, options releaseOpts) *context.Con
|
||||
ctx.ReleaseHeader = options.releaseHeader
|
||||
ctx.ReleaseFooter = options.releaseFooter
|
||||
ctx.Snapshot = options.snapshot
|
||||
if _, gitDirty := git.Status(); options.snapshotAuto && gitDirty {
|
||||
ctx.Snapshot = true
|
||||
}
|
||||
ctx.SkipPublish = ctx.Snapshot || options.skipPublish
|
||||
ctx.SkipValidate = ctx.Snapshot || options.skipValidate
|
||||
ctx.SkipSign = options.skipSign
|
||||
|
@ -1,8 +1,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -42,6 +45,35 @@ func TestReleaseFlags(t *testing.T) {
|
||||
})
|
||||
require.True(t, ctx.Snapshot)
|
||||
require.True(t, ctx.SkipPublish)
|
||||
})
|
||||
|
||||
t.Run("snapshot auto clean", func(t *testing.T) {
|
||||
testlib.Mktmp(t)
|
||||
testlib.GitInit(t)
|
||||
testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
|
||||
|
||||
var ctx = setup(releaseOpts{
|
||||
snapshotAuto: true,
|
||||
})
|
||||
|
||||
require.False(t, ctx.Snapshot)
|
||||
require.False(t, ctx.SkipPublish)
|
||||
})
|
||||
|
||||
t.Run("snapshot auto dirty", func(t *testing.T) {
|
||||
var folder = testlib.Mktmp(t)
|
||||
testlib.GitInit(t)
|
||||
testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
|
||||
testlib.GitAdd(t)
|
||||
testlib.GitCommit(t, "whatever")
|
||||
testlib.GitTag(t, "v0.0.1")
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(folder, "foo"), []byte("foobar"), 0644))
|
||||
|
||||
var ctx = setup(releaseOpts{
|
||||
snapshotAuto: true,
|
||||
})
|
||||
|
||||
require.True(t, ctx.Snapshot)
|
||||
require.True(t, ctx.SkipPublish)
|
||||
})
|
||||
|
||||
|
@ -16,6 +16,12 @@ func IsRepo() bool {
|
||||
return err == nil && strings.TrimSpace(out) == "true"
|
||||
}
|
||||
|
||||
// Status returns git status in its current state.
|
||||
func Status() (string, bool) {
|
||||
out, err := Run("status", "--porcelain")
|
||||
return out, strings.TrimSpace(out) != "" || err != nil
|
||||
}
|
||||
|
||||
// RunEnv runs a git command with the specified env vars and returns its output or errors.
|
||||
func RunEnv(env map[string]string, args ...string) (string, error) {
|
||||
// TODO: use exex.CommandContext here and refactor.
|
||||
|
@ -1,7 +1,9 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/git"
|
||||
@ -46,6 +48,21 @@ func TestRepo(t *testing.T) {
|
||||
require.False(t, git.IsRepo(), os.TempDir()+" folder should be a git repo")
|
||||
}
|
||||
|
||||
func TestStatus(t *testing.T) {
|
||||
var folder = testlib.Mktmp(t)
|
||||
testlib.GitInit(t)
|
||||
testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
|
||||
dummy, err := os.Create(filepath.Join(folder, "dummy"))
|
||||
require.NoError(t, err)
|
||||
testlib.GitAdd(t)
|
||||
testlib.GitCommit(t, "commit2")
|
||||
testlib.GitTag(t, "v0.0.1")
|
||||
require.NoError(t, ioutil.WriteFile(dummy.Name(), []byte("lorem ipsum"), 0644))
|
||||
status, dirty := git.Status()
|
||||
require.True(t, dirty, "git is currently in a dirty state")
|
||||
require.NotEmpty(t, status, "git status")
|
||||
}
|
||||
|
||||
func TestClean(t *testing.T) {
|
||||
out, err := git.Clean("asdasd 'ssadas'\nadasd", nil)
|
||||
require.NoError(t, err)
|
||||
|
@ -25,7 +25,7 @@ func (e ErrWrongRef) Error() string {
|
||||
|
||||
// ErrNoTag happens if the underlying git repository doesn't contain any tags
|
||||
// but no snapshot-release was requested.
|
||||
var ErrNoTag = errors.New("git doesn't contain any tags. Either add a tag or use --snapshot")
|
||||
var ErrNoTag = errors.New("git doesn't contain any tags. Either add a tag or use --snapshot or --snapshot-auto")
|
||||
|
||||
// ErrNotRepository happens if you try to run goreleaser against a folder
|
||||
// which is not a git repository.
|
||||
|
@ -116,11 +116,12 @@ func validate(ctx *context.Context) error {
|
||||
if ctx.SkipValidate {
|
||||
return pipe.ErrSkipValidateEnabled
|
||||
}
|
||||
out, err := git.Run("status", "--porcelain")
|
||||
if strings.TrimSpace(out) != "" || err != nil {
|
||||
return ErrDirty{status: out}
|
||||
if status, dirty := git.Status(); dirty {
|
||||
return ErrDirty{
|
||||
status: status,
|
||||
}
|
||||
}
|
||||
_, err = git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag))
|
||||
_, err := git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag))
|
||||
if err != nil {
|
||||
return ErrWrongRef{
|
||||
commit: ctx.Git.Commit,
|
||||
|
@ -84,7 +84,7 @@ func TestNoTagsNoSnapshot(t *testing.T) {
|
||||
testlib.GitCommit(t, "first")
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.Snapshot = false
|
||||
require.EqualError(t, Pipe{}.Run(ctx), `git doesn't contain any tags. Either add a tag or use --snapshot`)
|
||||
require.EqualError(t, Pipe{}.Run(ctx), `git doesn't contain any tags. Either add a tag or use --snapshot or --snapshot-auto`)
|
||||
}
|
||||
|
||||
func TestDirty(t *testing.T) {
|
||||
|
@ -34,3 +34,6 @@ get the snapshot version.
|
||||
Note that the idea behind GoReleaser's snapshots if mostly for local builds
|
||||
or to validate your build on the CI pipeline. Artifacts shouldn't be uploaded
|
||||
anywhere, and will only be generated to the `dist` folder.
|
||||
|
||||
You can also use the `--snapshot-auto` flag to automatically switch to snapshot
|
||||
if Git is currently in a dirty state.
|
||||
|
Loading…
Reference in New Issue
Block a user