1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-29 21:47:01 +02:00

fix: skip aware semerrgroup ()

* fix: skip aware semerrgroup

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* fix: skip aware semerrgroup

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker 2019-10-06 14:58:33 -03:00 committed by GitHub
parent 50235f2974
commit d338cf7285
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 3 deletions
internal/semerrgroup

@ -2,7 +2,12 @@
// size, so you can control the number of tasks being executed simultaneously.
package semerrgroup
import "golang.org/x/sync/errgroup"
import (
"sync"
"github.com/goreleaser/goreleaser/internal/pipe"
"golang.org/x/sync/errgroup"
)
// Group is the Semphore ErrorGroup itself
type Group interface {
@ -47,7 +52,8 @@ func (s *parallelGroup) Wait() error {
var _ Group = &serialGroup{}
type serialGroup struct {
err error
err error
errOnce sync.Once
}
// Go execs runs `fn` and saves the result if no error has been encountered.
@ -55,10 +61,52 @@ func (s *serialGroup) Go(fn func() error) {
if s.err != nil {
return
}
s.err = fn()
if err := fn(); err != nil {
s.errOnce.Do(func() {
s.err = err
})
}
}
// Wait waits for Go to complete and returns the first error encountered.
func (s *serialGroup) Wait() error {
return s.err
}
var _ Group = &skipAwareGroup{}
// NewSkipAware returns a new Group of a given size and aware of pipe skips.
func NewSkipAware(g Group) Group {
return &skipAwareGroup{g: g}
}
type skipAwareGroup struct {
g Group
skipErr error
skipOnce sync.Once
}
// Go execs runs `fn` and saves the result if no error has been encountered.
func (s *skipAwareGroup) Go(fn func() error) {
s.g.Go(func() error {
var err = fn()
// if the err is a skip, set it for later, but return nil for now so the
// the group proceeds.
if pipe.IsSkip(err) {
s.skipOnce.Do(func() {
s.skipErr = err
})
return nil
}
return err
})
}
// Wait waits for Go to complete and returns the first error encountered.
func (s *skipAwareGroup) Wait() error {
// if we got a "real error", return it, otherwise return skipErr or nil.
if err := s.g.Wait(); err != nil {
return err
}
return s.skipErr
}

@ -6,6 +6,7 @@ import (
"testing"
"time"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/stretchr/testify/require"
)
@ -54,3 +55,35 @@ func TestSemaphoreOrderError(t *testing.T) {
require.EqualError(t, g.Wait(), "fake err")
require.Equal(t, []int{0}, output)
}
func TestSemaphoreSkipAware(t *testing.T) {
var g = NewSkipAware(New(1))
var lock sync.Mutex
var counter int
for i := 0; i < 10; i++ {
g.Go(func() error {
time.Sleep(10 * time.Millisecond)
lock.Lock()
counter++
lock.Unlock()
return pipe.Skip("fake skip")
})
}
require.EqualError(t, g.Wait(), "fake skip")
require.Equal(t, counter, 10)
}
func TestSemaphoreSkipAndRealError(t *testing.T) {
var g = NewSkipAware(New(10))
for i := 0; i < 100; i++ {
g.Go(func() error {
time.Sleep(10 * time.Millisecond)
return pipe.Skip("fake skip")
})
}
g.Go(func() error {
time.Sleep(10 * time.Millisecond)
return fmt.Errorf("errrrrr")
})
require.EqualError(t, g.Wait(), "errrrrr")
}