1
0
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:
CrazyMax 2020-12-22 14:41:08 +01:00 committed by GitHub
parent 9423da1b60
commit d8a0f253d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 113 additions and 12 deletions

View File

@ -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')

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)
})

View File

@ -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.

View File

@ -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)

View File

@ -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.

View File

@ -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,

View File

@ -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) {

View File

@ -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.