option to auto-cancel pending builds
This commit is contained in:
parent
3fcbf1c78f
commit
0b4e5156ae
10 changed files with 106 additions and 10 deletions
|
@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## Unreleased
|
||||
### Added
|
||||
- added nsswitch to docker images
|
||||
- option to auto-cancel pending builds when newer build enqueued, by [@bradrydzewski](https://github.com/bradrydzewski). [#1980](https://github.com/drone/drone/issues/1980).
|
||||
|
||||
## [1.5.1] - 2019-09-30
|
||||
### Added
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/drone/drone/livelog"
|
||||
"github.com/drone/drone/metric/sink"
|
||||
"github.com/drone/drone/pubsub"
|
||||
"github.com/drone/drone/service/canceler"
|
||||
"github.com/drone/drone/service/commit"
|
||||
contents "github.com/drone/drone/service/content"
|
||||
"github.com/drone/drone/service/content/cache"
|
||||
|
@ -46,6 +47,7 @@ import (
|
|||
|
||||
// wire set for loading the services.
|
||||
var serviceSet = wire.NewSet(
|
||||
canceler.New,
|
||||
commit.New,
|
||||
cron.New,
|
||||
livelog.New,
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/drone/drone/livelog"
|
||||
"github.com/drone/drone/operator/manager"
|
||||
"github.com/drone/drone/pubsub"
|
||||
"github.com/drone/drone/service/canceler"
|
||||
"github.com/drone/drone/service/commit"
|
||||
"github.com/drone/drone/service/hook/parser"
|
||||
"github.com/drone/drone/service/license"
|
||||
|
@ -47,17 +48,19 @@ func InitializeApplication(config2 config.Config) (application, error) {
|
|||
commitService := commit.New(client, renewer)
|
||||
cronStore := cron.New(db)
|
||||
repositoryStore := provideRepoStore(db)
|
||||
fileService := provideContentService(client, renewer)
|
||||
configService := provideConfigPlugin(client, fileService, config2)
|
||||
convertService := provideConvertPlugin(client, config2)
|
||||
statusService := provideStatusService(client, renewer, config2)
|
||||
buildStore := provideBuildStore(db)
|
||||
stageStore := provideStageStore(db)
|
||||
scheduler := provideScheduler(stageStore, config2)
|
||||
validateService := provideValidatePlugin(config2)
|
||||
statusService := provideStatusService(client, renewer, config2)
|
||||
stepStore := step.New(db)
|
||||
system := provideSystem(config2)
|
||||
webhookSender := provideWebhookPlugin(config2, system)
|
||||
triggerer := trigger.New(configService, convertService, commitService, statusService, buildStore, scheduler, repositoryStore, userStore, validateService, webhookSender)
|
||||
coreCanceler := canceler.New(buildStore, repositoryStore, scheduler, stageStore, statusService, stepStore, userStore, webhookSender)
|
||||
fileService := provideContentService(client, renewer)
|
||||
configService := provideConfigPlugin(client, fileService, config2)
|
||||
convertService := provideConvertPlugin(client, config2)
|
||||
validateService := provideValidatePlugin(config2)
|
||||
triggerer := trigger.New(coreCanceler, configService, convertService, commitService, statusService, buildStore, scheduler, repositoryStore, userStore, validateService, webhookSender)
|
||||
cronScheduler := cron2.New(commitService, cronStore, repositoryStore, userStore, triggerer)
|
||||
coreLicense := provideLicense(client, config2)
|
||||
datadog := provideDatadog(userStore, repositoryStore, buildStore, system, coreLicense, config2)
|
||||
|
@ -71,7 +74,6 @@ func InitializeApplication(config2 config.Config) (application, error) {
|
|||
}
|
||||
secretStore := secret.New(db, encrypter)
|
||||
globalSecretStore := global.New(db, encrypter)
|
||||
stepStore := step.New(db)
|
||||
buildManager := manager.New(buildStore, configService, convertService, corePubsub, logStore, logStream, netrcService, repositoryStore, scheduler, secretStore, globalSecretStore, statusService, stageStore, stepStore, system, userStore, webhookSender)
|
||||
secretService := provideSecretPlugin(config2)
|
||||
registryService := provideRegistryPlugin(config2)
|
||||
|
|
|
@ -52,7 +52,7 @@ type (
|
|||
IgnoreForks bool `json:"ignore_forks"`
|
||||
IgnorePulls bool `json:"ignore_pull_requests"`
|
||||
CancelPulls bool `json:"auto_cancel_pull_requests"`
|
||||
CancelPush bool `json:"auto_cancel_branch"`
|
||||
CancelPush bool `json:"auto_cancel_pushes"`
|
||||
Timeout int64 `json:"timeout"`
|
||||
Counter int64 `json:"counter"`
|
||||
Synced int64 `json:"synced"`
|
||||
|
|
|
@ -34,6 +34,8 @@ type (
|
|||
Protected *bool `json:"protected"`
|
||||
IgnoreForks *bool `json:"ignore_forks"`
|
||||
IgnorePulls *bool `json:"ignore_pull_requests"`
|
||||
CancelPulls *bool `json:"auto_cancel_pull_requests"`
|
||||
CancelPush *bool `json:"auto_cancel_pushes"`
|
||||
Timeout *int64 `json:"timeout"`
|
||||
Counter *int64 `json:"counter"`
|
||||
}
|
||||
|
@ -86,6 +88,12 @@ func HandleUpdate(repos core.RepositoryStore) http.HandlerFunc {
|
|||
if in.IgnorePulls != nil {
|
||||
repo.IgnorePulls = *in.IgnorePulls
|
||||
}
|
||||
if in.CancelPulls != nil {
|
||||
repo.CancelPulls = *in.CancelPulls
|
||||
}
|
||||
if in.CancelPush != nil {
|
||||
repo.CancelPush = *in.CancelPush
|
||||
}
|
||||
|
||||
//
|
||||
// system administrator only
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
package mock
|
||||
|
||||
//go:generate mockgen -package=mock -destination=mock_gen.go github.com/drone/drone/core ConvertService,ValidateService,NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService
|
||||
//go:generate mockgen -package=mock -destination=mock_gen.go github.com/drone/drone/core Canceler,ConvertService,ValidateService,NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/drone/drone/core (interfaces: ConvertService,ValidateService,NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService)
|
||||
// Source: github.com/drone/drone/core (interfaces: Canceler,ConvertService,ValidateService,NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
@ -13,6 +13,57 @@ import (
|
|||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockCanceler is a mock of Canceler interface
|
||||
type MockCanceler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCancelerMockRecorder
|
||||
}
|
||||
|
||||
// MockCancelerMockRecorder is the mock recorder for MockCanceler
|
||||
type MockCancelerMockRecorder struct {
|
||||
mock *MockCanceler
|
||||
}
|
||||
|
||||
// NewMockCanceler creates a new mock instance
|
||||
func NewMockCanceler(ctrl *gomock.Controller) *MockCanceler {
|
||||
mock := &MockCanceler{ctrl: ctrl}
|
||||
mock.recorder = &MockCancelerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockCanceler) EXPECT() *MockCancelerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Cancel mocks base method
|
||||
func (m *MockCanceler) Cancel(arg0 context.Context, arg1 *core.Repository, arg2 *core.Build) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Cancel", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Cancel indicates an expected call of Cancel
|
||||
func (mr *MockCancelerMockRecorder) Cancel(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cancel", reflect.TypeOf((*MockCanceler)(nil).Cancel), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// CancelPending mocks base method
|
||||
func (m *MockCanceler) CancelPending(arg0 context.Context, arg1 *core.Repository, arg2 *core.Build) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CancelPending", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CancelPending indicates an expected call of CancelPending
|
||||
func (mr *MockCancelerMockRecorder) CancelPending(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelPending", reflect.TypeOf((*MockCanceler)(nil).CancelPending), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// MockConvertService is a mock of ConvertService interface
|
||||
type MockConvertService struct {
|
||||
ctrl *gomock.Controller
|
||||
|
|
|
@ -16,6 +16,7 @@ package canceler
|
|||
|
||||
import (
|
||||
"context"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
|
@ -67,6 +68,19 @@ func (s *service) Cancel(ctx context.Context, repo *core.Repository, build *core
|
|||
// CancelPending cancels all pending builds of the same event
|
||||
// and reference with lower build numbers.
|
||||
func (s *service) CancelPending(ctx context.Context, repo *core.Repository, build *core.Build) error {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
// switch {
|
||||
// case repo.CancelPulls && build.Event == core.EventPullRequest:
|
||||
// case repo.CancelPush && build.Event == core.EventPush:
|
||||
// default:
|
||||
// return nil
|
||||
// }
|
||||
|
||||
switch build.Event {
|
||||
// on the push and pull request builds can be automatically
|
||||
// cancelled by the system.
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
)
|
||||
|
||||
type triggerer struct {
|
||||
canceler core.Canceler
|
||||
config core.ConfigService
|
||||
convert core.ConvertService
|
||||
commits core.CommitService
|
||||
|
@ -46,6 +47,7 @@ type triggerer struct {
|
|||
|
||||
// New returns a new build triggerer.
|
||||
func New(
|
||||
canceler core.Canceler,
|
||||
config core.ConfigService,
|
||||
convert core.ConvertService,
|
||||
commits core.CommitService,
|
||||
|
@ -58,6 +60,7 @@ func New(
|
|||
hooks core.WebhookSender,
|
||||
) core.Triggerer {
|
||||
return &triggerer{
|
||||
canceler: canceler,
|
||||
config: config,
|
||||
convert: convert,
|
||||
commits: commits,
|
||||
|
@ -459,6 +462,12 @@ func (t *triggerer) Trigger(ctx context.Context, repo *core.Repository, base *co
|
|||
logger = logger.WithError(err)
|
||||
logger.Warnln("trigger: cannot send webhook")
|
||||
}
|
||||
|
||||
if repo.CancelPush && build.Event == core.EventPush ||
|
||||
repo.CancelPulls && build.Event == core.EventPullRequest {
|
||||
go t.canceler.CancelPending(ctx, repo, build)
|
||||
}
|
||||
|
||||
// err = t.hooks.SendEndpoint(ctx, payload, repo.Endpoints.Webhook)
|
||||
// if err != nil {
|
||||
// logger.Warn().Err(err).
|
||||
|
|
|
@ -79,6 +79,7 @@ func TestTrigger(t *testing.T) {
|
|||
mockWebhooks.EXPECT().Send(gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
@ -115,6 +116,7 @@ func TestTrigger_SkipCI(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
dummyHookSkip := *dummyHook
|
||||
dummyHookSkip.Message = "foo [CI SKIP] bar"
|
||||
|
@ -140,6 +142,7 @@ func TestTrigger_NoOwner(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
mockUsers,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -164,6 +167,7 @@ func TestTrigger_MissingYaml(t *testing.T) {
|
|||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(nil, io.EOF)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -204,6 +208,7 @@ func TestTrigger_ErrorYaml(t *testing.T) {
|
|||
mockBuilds.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) // .Do(checkBuild).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
@ -251,6 +256,7 @@ func TestTrigger_SkipBranch(t *testing.T) {
|
|||
mockValidateService.EXPECT().Validate(gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
@ -288,6 +294,7 @@ func TestTrigger_SkipEvent(t *testing.T) {
|
|||
mockValidateService.EXPECT().Validate(gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
@ -325,6 +332,7 @@ func TestTrigger_SkipAction(t *testing.T) {
|
|||
mockValidateService.EXPECT().Validate(gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
@ -366,6 +374,7 @@ func TestTrigger_ErrorIncrement(t *testing.T) {
|
|||
mockValidateService.EXPECT().Validate(gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
triggerer := New(
|
||||
nil,
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
|
|
Loading…
Reference in a new issue