mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-03-03 15:02:35 +02:00
add package for Jenkins interactions (#2296)
This commit is contained in:
parent
19e90f04f2
commit
8d682abc83
1
go.mod
1
go.mod
@ -12,6 +12,7 @@ require (
|
||||
github.com/Microsoft/hcsshim v0.8.10 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
|
||||
github.com/bmatcuk/doublestar v1.3.2
|
||||
github.com/bndr/gojenkins v1.0.1
|
||||
github.com/containerd/containerd v1.4.1 // indirect
|
||||
github.com/docker/docker v1.4.2-0.20200114201811-16a3519d870b // indirect
|
||||
github.com/elliotchance/orderedmap v1.3.0
|
||||
|
2
go.sum
2
go.sum
@ -125,6 +125,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmatcuk/doublestar v1.3.2 h1:mzUncgFmpzNUhIITFqGdZ8nUU0O7JTJzRO8VdkeLCSo=
|
||||
github.com/bmatcuk/doublestar v1.3.2/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/bndr/gojenkins v1.0.1 h1:DFIuamRSmXoI/CwB44txuRf8xaHZNejZge/Lui4RYD4=
|
||||
github.com/bndr/gojenkins v1.0.1/go.mod h1:J2FxlujWW87NJJrdysyctcDllRVYUONGGlHX16134P4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
32
pkg/jenkins/artifact.go
Normal file
32
pkg/jenkins/artifact.go
Normal file
@ -0,0 +1,32 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"github.com/bndr/gojenkins"
|
||||
)
|
||||
|
||||
// Artifact is an interface to abstract gojenkins.Artifact.
|
||||
type Artifact interface {
|
||||
SaveToDir(dir string) (bool, error)
|
||||
GetData() ([]byte, error)
|
||||
FileName() string
|
||||
}
|
||||
|
||||
// ArtifactImpl is a wrapper struct for gojenkins.Artifact that respects the Artifact interface.
|
||||
type ArtifactImpl struct {
|
||||
artifact gojenkins.Artifact
|
||||
}
|
||||
|
||||
// SaveToDir refers to the gojenkins.Artifact.SaveToDir function.
|
||||
func (a *ArtifactImpl) SaveToDir(dir string) (bool, error) {
|
||||
return a.artifact.SaveToDir(dir)
|
||||
}
|
||||
|
||||
// GetData refers to the gojenkins.Artifact.GetData function.
|
||||
func (a *ArtifactImpl) GetData() ([]byte, error) {
|
||||
return a.artifact.GetData()
|
||||
}
|
||||
|
||||
// FileName refers to the gojenkins.Artifact.FileName field.
|
||||
func (a *ArtifactImpl) FileName() string {
|
||||
return a.artifact.FileName
|
||||
}
|
38
pkg/jenkins/build.go
Normal file
38
pkg/jenkins/build.go
Normal file
@ -0,0 +1,38 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bndr/gojenkins"
|
||||
)
|
||||
|
||||
// Build is an interface to abstract gojenkins.Build.
|
||||
type Build interface {
|
||||
GetArtifacts() []gojenkins.Artifact
|
||||
IsRunning() bool
|
||||
}
|
||||
|
||||
// WaitForBuildToFinish waits till a build is finished.
|
||||
func WaitForBuildToFinish(build Build, pollInterval time.Duration) {
|
||||
//TODO: handle timeout?
|
||||
for build.IsRunning() {
|
||||
time.Sleep(pollInterval)
|
||||
//TODO: build.Poll() needed?
|
||||
}
|
||||
}
|
||||
|
||||
// FetchBuildArtifact is fetching a build artifact from a finished build with a certain name.
|
||||
// Fails if build is running or no artifact is with the given name is found.
|
||||
func FetchBuildArtifact(build Build, fileName string) (Artifact, error) {
|
||||
if build.IsRunning() {
|
||||
return &ArtifactImpl{}, errors.New("Failed to fetch artifact: Job is still running")
|
||||
}
|
||||
for _, artifact := range build.GetArtifacts() {
|
||||
if artifact.FileName == fileName {
|
||||
return &ArtifactImpl{artifact: artifact}, nil
|
||||
}
|
||||
}
|
||||
return &ArtifactImpl{}, fmt.Errorf("Failed to fetch artifact: Artifact '%s' not found", fileName)
|
||||
}
|
80
pkg/jenkins/build_test.go
Normal file
80
pkg/jenkins/build_test.go
Normal file
@ -0,0 +1,80 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/jenkins/mocks"
|
||||
"github.com/bndr/gojenkins"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestWaitForBuildToFinish(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
// init
|
||||
build := &mocks.Build{}
|
||||
build.
|
||||
On("IsRunning").Return(true).Once().
|
||||
On("IsRunning").Return(false)
|
||||
// test
|
||||
WaitForBuildToFinish(build, time.Millisecond)
|
||||
// asserts
|
||||
build.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFetchBuildArtifact(t *testing.T) {
|
||||
fileName := "artifactFile.xml"
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
// init
|
||||
build := &mocks.Build{}
|
||||
build.On("IsRunning").Return(false)
|
||||
build.On("GetArtifacts").Return(
|
||||
[]gojenkins.Artifact{
|
||||
gojenkins.Artifact{FileName: mock.Anything},
|
||||
gojenkins.Artifact{FileName: fileName},
|
||||
},
|
||||
)
|
||||
// test
|
||||
artifact, err := FetchBuildArtifact(build, fileName)
|
||||
// asserts
|
||||
build.AssertExpectations(t)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, fileName, artifact.FileName())
|
||||
})
|
||||
t.Run("error - job running", func(t *testing.T) {
|
||||
// init
|
||||
build := &mocks.Build{}
|
||||
build.On("IsRunning").Return(true)
|
||||
// test
|
||||
_, err := FetchBuildArtifact(build, fileName)
|
||||
// asserts
|
||||
build.AssertExpectations(t)
|
||||
assert.EqualError(t, err, "Failed to fetch artifact: Job is still running")
|
||||
})
|
||||
t.Run("error - no artifacts", func(t *testing.T) {
|
||||
// init
|
||||
build := &mocks.Build{}
|
||||
build.On("IsRunning").Return(false)
|
||||
build.On("GetArtifacts").Return([]gojenkins.Artifact{})
|
||||
// test
|
||||
_, err := FetchBuildArtifact(build, fileName)
|
||||
// asserts
|
||||
build.AssertExpectations(t)
|
||||
assert.EqualError(t, err, fmt.Sprintf("Failed to fetch artifact: Artifact '%s' not found", fileName))
|
||||
})
|
||||
t.Run("error - artifact not found", func(t *testing.T) {
|
||||
// init
|
||||
build := &mocks.Build{}
|
||||
build.On("IsRunning").Return(false)
|
||||
build.On("GetArtifacts").Return([]gojenkins.Artifact{gojenkins.Artifact{FileName: mock.Anything}})
|
||||
// test
|
||||
_, err := FetchBuildArtifact(build, fileName)
|
||||
// asserts
|
||||
build.AssertExpectations(t)
|
||||
assert.EqualError(t, err, fmt.Sprintf("Failed to fetch artifact: Artifact '%s' not found", fileName))
|
||||
})
|
||||
}
|
55
pkg/jenkins/jenkins.go
Normal file
55
pkg/jenkins/jenkins.go
Normal file
@ -0,0 +1,55 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bndr/gojenkins"
|
||||
)
|
||||
|
||||
// Jenkins is an interface to abstract gojenkins.Jenkins.
|
||||
type Jenkins interface {
|
||||
BuildJob(name string, options ...interface{}) (int64, error)
|
||||
GetQueueItem(id int64) (*gojenkins.Task, error)
|
||||
GetBuild(jobName string, number int64) (*gojenkins.Build, error)
|
||||
}
|
||||
|
||||
// Instance connects to a Jenkins instance and returns a handler.
|
||||
func Instance(client *http.Client, jenkinsURL, user, token string) (*gojenkins.Jenkins, error) {
|
||||
return gojenkins.
|
||||
CreateJenkins(client, jenkinsURL, user, token).
|
||||
Init()
|
||||
}
|
||||
|
||||
// TriggerJob starts a build for a given job name.
|
||||
func TriggerJob(jenkins Jenkins, jobName string, parameters map[string]string) (*gojenkins.Task, error) {
|
||||
// get job id
|
||||
jobID := strings.ReplaceAll(jobName, "/", "/job/")
|
||||
// start job
|
||||
queueID, startBuildErr := jenkins.BuildJob(jobID, parameters)
|
||||
if startBuildErr != nil {
|
||||
return nil, startBuildErr
|
||||
}
|
||||
if queueID == 0 {
|
||||
// handle rare error case where queueID is not set
|
||||
// see https://github.com/bndr/gojenkins/issues/205
|
||||
return nil, fmt.Errorf("Unable to queue build")
|
||||
}
|
||||
// get task
|
||||
return jenkins.GetQueueItem(queueID)
|
||||
}
|
||||
|
||||
// WaitForBuildToStart waits till a build is started.
|
||||
func WaitForBuildToStart(jenkins Jenkins, jobName string, taskWrapper Task, pollInterval time.Duration) (*gojenkins.Build, error) {
|
||||
// wait for job to start
|
||||
buildNumber, taskTimedOutErr := taskWrapper.WaitToStart(pollInterval)
|
||||
if taskTimedOutErr != nil {
|
||||
return nil, taskTimedOutErr
|
||||
}
|
||||
// get job id
|
||||
jobID := strings.ReplaceAll(jobName, "/", "/job/")
|
||||
// get build
|
||||
return jenkins.GetBuild(jobID, buildNumber)
|
||||
}
|
87
pkg/jenkins/jenkins_test.go
Normal file
87
pkg/jenkins/jenkins_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/jenkins/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestTriggerJob(t *testing.T) {
|
||||
jobName := "ContinuousDelivery/piper-library"
|
||||
jobID := strings.ReplaceAll(jobName, "/", "/job/")
|
||||
jobParameters := map[string]string{}
|
||||
|
||||
t.Run("error - task not started", func(t *testing.T) {
|
||||
// init
|
||||
queueID := int64(0)
|
||||
jenkins := &mocks.Jenkins{}
|
||||
jenkins.
|
||||
On("BuildJob", jobID, map[string]string{}).
|
||||
Return(queueID, fmt.Errorf(mock.Anything))
|
||||
// test
|
||||
task, err := TriggerJob(jenkins, jobName, jobParameters)
|
||||
// asserts
|
||||
jenkins.AssertExpectations(t)
|
||||
assert.EqualError(t, err, mock.Anything)
|
||||
assert.Nil(t, task)
|
||||
})
|
||||
t.Run("error - task already queued", func(t *testing.T) {
|
||||
// init
|
||||
queueID := int64(0)
|
||||
jenkins := &mocks.Jenkins{}
|
||||
jenkins.
|
||||
On("BuildJob", jobID, map[string]string{}).
|
||||
Return(queueID, nil)
|
||||
// test
|
||||
task, err := TriggerJob(jenkins, jobName, jobParameters)
|
||||
// asserts
|
||||
jenkins.AssertExpectations(t)
|
||||
assert.EqualError(t, err, "Unable to queue build")
|
||||
assert.Nil(t, task)
|
||||
})
|
||||
t.Run("error - task not queued", func(t *testing.T) {
|
||||
// init
|
||||
queueID := int64(43)
|
||||
jenkins := &mocks.Jenkins{}
|
||||
jenkins.Test(t)
|
||||
jenkins.
|
||||
On("BuildJob", jobID, map[string]string{}).
|
||||
Return(queueID, nil).
|
||||
On("GetQueueItem", queueID).
|
||||
Return(nil, fmt.Errorf(mock.Anything))
|
||||
// test
|
||||
task, err := TriggerJob(jenkins, jobName, jobParameters)
|
||||
// asserts
|
||||
jenkins.AssertExpectations(t)
|
||||
assert.EqualError(t, err, mock.Anything)
|
||||
assert.Nil(t, task)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWaitForBuildToStart(t *testing.T) {
|
||||
jobName := "ContinuousDelivery/piper-library"
|
||||
jobID := strings.ReplaceAll(jobName, "/", "/job/")
|
||||
|
||||
t.Run("error - build not started", func(t *testing.T) {
|
||||
// init
|
||||
buildNumber := int64(43)
|
||||
task := &mocks.Task{}
|
||||
task.On("WaitToStart", time.Millisecond).Return(buildNumber, nil)
|
||||
jenkins := &mocks.Jenkins{}
|
||||
jenkins.
|
||||
On("GetBuild", jobID, buildNumber).
|
||||
Return(nil, fmt.Errorf("Build not started"))
|
||||
// test
|
||||
build, err := WaitForBuildToStart(jenkins, jobName, task, time.Millisecond)
|
||||
// asserts
|
||||
task.AssertExpectations(t)
|
||||
jenkins.AssertExpectations(t)
|
||||
assert.EqualError(t, err, "Build not started")
|
||||
assert.Nil(t, build)
|
||||
})
|
||||
}
|
68
pkg/jenkins/mocks/Artifact.go
Normal file
68
pkg/jenkins/mocks/Artifact.go
Normal file
@ -0,0 +1,68 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// Artifact is an autogenerated mock type for the Artifact type
|
||||
type Artifact struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// FileName provides a mock function with given fields:
|
||||
func (_m *Artifact) FileName() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetData provides a mock function with given fields:
|
||||
func (_m *Artifact) GetData() ([]byte, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []byte
|
||||
if rf, ok := ret.Get(0).(func() []byte); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SaveToDir provides a mock function with given fields: dir
|
||||
func (_m *Artifact) SaveToDir(dir string) (bool, error) {
|
||||
ret := _m.Called(dir)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(dir)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(dir)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
44
pkg/jenkins/mocks/Build.go
Normal file
44
pkg/jenkins/mocks/Build.go
Normal file
@ -0,0 +1,44 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
gojenkins "github.com/bndr/gojenkins"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// Build is an autogenerated mock type for the Build type
|
||||
type Build struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GetArtifacts provides a mock function with given fields:
|
||||
func (_m *Build) GetArtifacts() []gojenkins.Artifact {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []gojenkins.Artifact
|
||||
if rf, ok := ret.Get(0).(func() []gojenkins.Artifact); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]gojenkins.Artifact)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// IsRunning provides a mock function with given fields:
|
||||
func (_m *Build) IsRunning() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
84
pkg/jenkins/mocks/Jenkins.go
Normal file
84
pkg/jenkins/mocks/Jenkins.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
gojenkins "github.com/bndr/gojenkins"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// Jenkins is an autogenerated mock type for the Jenkins type
|
||||
type Jenkins struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// BuildJob provides a mock function with given fields: name, options
|
||||
func (_m *Jenkins) BuildJob(name string, options ...interface{}) (int64, error) {
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, name)
|
||||
_ca = append(_ca, options...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func(string, ...interface{}) int64); ok {
|
||||
r0 = rf(name, options...)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, ...interface{}) error); ok {
|
||||
r1 = rf(name, options...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetBuild provides a mock function with given fields: jobName, number
|
||||
func (_m *Jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build, error) {
|
||||
ret := _m.Called(jobName, number)
|
||||
|
||||
var r0 *gojenkins.Build
|
||||
if rf, ok := ret.Get(0).(func(string, int64) *gojenkins.Build); ok {
|
||||
r0 = rf(jobName, number)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*gojenkins.Build)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, int64) error); ok {
|
||||
r1 = rf(jobName, number)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetQueueItem provides a mock function with given fields: id
|
||||
func (_m *Jenkins) GetQueueItem(id int64) (*gojenkins.Task, error) {
|
||||
ret := _m.Called(id)
|
||||
|
||||
var r0 *gojenkins.Task
|
||||
if rf, ok := ret.Get(0).(func(int64) *gojenkins.Task); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*gojenkins.Task)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(int64) error); ok {
|
||||
r1 = rf(id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
91
pkg/jenkins/mocks/Task.go
Normal file
91
pkg/jenkins/mocks/Task.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// Task is an autogenerated mock type for the Task type
|
||||
type Task struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// BuildNumber provides a mock function with given fields:
|
||||
func (_m *Task) BuildNumber() (int64, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// HasStarted provides a mock function with given fields:
|
||||
func (_m *Task) HasStarted() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Poll provides a mock function with given fields:
|
||||
func (_m *Task) Poll() (int, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int
|
||||
if rf, ok := ret.Get(0).(func() int); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// WaitToStart provides a mock function with given fields: pollInterval
|
||||
func (_m *Task) WaitToStart(pollInterval time.Duration) (int64, error) {
|
||||
ret := _m.Called(pollInterval)
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func(time.Duration) int64); ok {
|
||||
r0 = rf(pollInterval)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(time.Duration) error); ok {
|
||||
r1 = rf(pollInterval)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
52
pkg/jenkins/task.go
Normal file
52
pkg/jenkins/task.go
Normal file
@ -0,0 +1,52 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bndr/gojenkins"
|
||||
)
|
||||
|
||||
// Task is an interface to abstract gojenkins.Task.
|
||||
type Task interface {
|
||||
Poll() (int, error)
|
||||
BuildNumber() (int64, error)
|
||||
HasStarted() bool
|
||||
WaitToStart(pollInterval time.Duration) (int64, error)
|
||||
}
|
||||
|
||||
// TaskImpl is a wrapper struct for gojenkins.Task that respects the Task interface.
|
||||
type TaskImpl struct {
|
||||
Task *gojenkins.Task
|
||||
}
|
||||
|
||||
// Poll refers to the gojenkins.Task.Poll function.
|
||||
func (t *TaskImpl) Poll() (int, error) {
|
||||
return t.Task.Poll()
|
||||
}
|
||||
|
||||
// HasStarted checks if the wrapped gojenkins.Task has started by checking the assigned executable URL.
|
||||
func (t *TaskImpl) HasStarted() bool {
|
||||
return t.Task.Raw.Executable.URL != ""
|
||||
}
|
||||
|
||||
// BuildNumber returns the assigned build number or an error if the build has not yet started.
|
||||
func (t *TaskImpl) BuildNumber() (int64, error) {
|
||||
if !t.HasStarted() {
|
||||
return 0, fmt.Errorf("build did not start yet")
|
||||
}
|
||||
return t.Task.Raw.Executable.Number, nil
|
||||
}
|
||||
|
||||
// WaitToStart waits till the build has started.
|
||||
func (t *TaskImpl) WaitToStart(pollInterval time.Duration) (int64, error) {
|
||||
for retry := 0; retry < 15; {
|
||||
if t.HasStarted() {
|
||||
return t.BuildNumber()
|
||||
}
|
||||
time.Sleep(pollInterval)
|
||||
t.Poll()
|
||||
retry++
|
||||
}
|
||||
return 0, fmt.Errorf("build did not start in a reasonable amount of time")
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user