1485 lines
43 KiB
Go
1485 lines
43 KiB
Go
package db_test
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/concourse/concourse/atc"
|
|
"github.com/concourse/concourse/atc/db"
|
|
"github.com/concourse/concourse/atc/db/algorithm"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Job", func() {
|
|
var (
|
|
job db.Job
|
|
pipeline db.Pipeline
|
|
team db.Team
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
team, err = teamFactory.CreateTeam(atc.Team{Name: "some-team"})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
var created bool
|
|
pipeline, created, err = team.SavePipeline("fake-pipeline", atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{
|
|
Name: "some-job",
|
|
|
|
Public: true,
|
|
|
|
Serial: true,
|
|
|
|
SerialGroups: []string{"serial-group"},
|
|
|
|
Plan: atc.PlanSequence{
|
|
{
|
|
Put: "some-resource",
|
|
Params: atc.Params{
|
|
"some-param": "some-value",
|
|
},
|
|
},
|
|
{
|
|
Get: "some-input",
|
|
Resource: "some-resource",
|
|
Params: atc.Params{
|
|
"some-param": "some-value",
|
|
},
|
|
Passed: []string{"job-1", "job-2"},
|
|
Trigger: true,
|
|
},
|
|
{
|
|
Task: "some-task",
|
|
Privileged: true,
|
|
TaskConfigPath: "some/config/path.yml",
|
|
TaskConfig: &atc.TaskConfig{
|
|
RootfsURI: "some-image",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "some-other-job",
|
|
},
|
|
{
|
|
Name: "some-private-job",
|
|
Public: false,
|
|
},
|
|
{
|
|
Name: "other-serial-group-job",
|
|
SerialGroups: []string{"serial-group", "really-different-group"},
|
|
},
|
|
{
|
|
Name: "different-serial-group-job",
|
|
SerialGroups: []string{"different-serial-group"},
|
|
},
|
|
},
|
|
Resources: atc.ResourceConfigs{
|
|
{
|
|
Name: "some-resource",
|
|
Type: "some-type",
|
|
},
|
|
{
|
|
Name: "some-other-resource",
|
|
Type: "some-type",
|
|
},
|
|
},
|
|
}, db.ConfigVersion(0), db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(created).To(BeTrue())
|
|
|
|
var found bool
|
|
job, found, err = pipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
Describe("Public", func() {
|
|
Context("when the config has public set to true", func() {
|
|
It("returns true", func() {
|
|
Expect(job.Public()).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("when the config has public set to false", func() {
|
|
It("returns false", func() {
|
|
privateJob, found, err := pipeline.Job("some-private-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(privateJob.Public()).To(BeFalse())
|
|
})
|
|
})
|
|
|
|
Context("when the config does not have public set", func() {
|
|
It("returns false", func() {
|
|
otherJob, found, err := pipeline.Job("some-other-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(otherJob.Public()).To(BeFalse())
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("Pause and Unpause", func() {
|
|
It("starts out as unpaused", func() {
|
|
Expect(job.Paused()).To(BeFalse())
|
|
})
|
|
|
|
It("can be paused", func() {
|
|
err := job.Pause()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
found, err := job.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(job.Paused()).To(BeTrue())
|
|
})
|
|
|
|
It("can be unpaused", func() {
|
|
err := job.Unpause()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
found, err := job.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(job.Paused()).To(BeFalse())
|
|
})
|
|
})
|
|
|
|
Describe("FinishedAndNextBuild", func() {
|
|
var otherPipeline db.Pipeline
|
|
var otherJob db.Job
|
|
|
|
BeforeEach(func() {
|
|
var created bool
|
|
var err error
|
|
otherPipeline, created, err = team.SavePipeline("other-pipeline", atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{Name: "some-job"},
|
|
},
|
|
}, db.ConfigVersion(0), db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(created).To(BeTrue())
|
|
|
|
var found bool
|
|
otherJob, found, err = otherPipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
It("can report a job's latest running and finished builds", func() {
|
|
finished, next, err := job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next).To(BeNil())
|
|
Expect(finished).To(BeNil())
|
|
|
|
finishedBuild, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = finishedBuild.Finish(db.BuildStatusSucceeded)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
otherFinishedBuild, err := otherJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = otherFinishedBuild.Finish(db.BuildStatusSucceeded)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
finished, next, err = job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next).To(BeNil())
|
|
Expect(finished.ID()).To(Equal(finishedBuild.ID()))
|
|
|
|
nextBuild, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
started, err := nextBuild.Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(started).To(BeTrue())
|
|
|
|
otherNextBuild, err := otherJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
otherStarted, err := otherNextBuild.Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(otherStarted).To(BeTrue())
|
|
|
|
finished, next, err = job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next.ID()).To(Equal(nextBuild.ID()))
|
|
Expect(finished.ID()).To(Equal(finishedBuild.ID()))
|
|
|
|
anotherRunningBuild, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
finished, next, err = job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next.ID()).To(Equal(nextBuild.ID())) // not anotherRunningBuild
|
|
Expect(finished.ID()).To(Equal(finishedBuild.ID()))
|
|
|
|
started, err = anotherRunningBuild.Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(started).To(BeTrue())
|
|
|
|
finished, next, err = job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next.ID()).To(Equal(nextBuild.ID())) // not anotherRunningBuild
|
|
Expect(finished.ID()).To(Equal(finishedBuild.ID()))
|
|
|
|
err = nextBuild.Finish(db.BuildStatusSucceeded)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
finished, next, err = job.FinishedAndNextBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(next.ID()).To(Equal(anotherRunningBuild.ID()))
|
|
Expect(finished.ID()).To(Equal(nextBuild.ID()))
|
|
})
|
|
})
|
|
|
|
Describe("UpdateFirstLoggedBuildID", func() {
|
|
It("updates FirstLoggedBuildID on a job", func() {
|
|
By("starting out as 0")
|
|
Expect(job.FirstLoggedBuildID()).To(BeZero())
|
|
|
|
By("increasing it to 57")
|
|
err := job.UpdateFirstLoggedBuildID(57)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
found, err := job.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(job.FirstLoggedBuildID()).To(Equal(57))
|
|
|
|
By("not erroring when it's called with the same number")
|
|
err = job.UpdateFirstLoggedBuildID(57)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("erroring when the number decreases")
|
|
err = job.UpdateFirstLoggedBuildID(56)
|
|
Expect(err).To(Equal(db.FirstLoggedBuildIDDecreasedError{
|
|
Job: "some-job",
|
|
OldID: 57,
|
|
NewID: 56,
|
|
}))
|
|
})
|
|
})
|
|
|
|
Describe("Builds", func() {
|
|
var (
|
|
builds [10]db.Build
|
|
someJob db.Job
|
|
someOtherJob db.Job
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
for i := 0; i < 10; i++ {
|
|
var found bool
|
|
var err error
|
|
someJob, found, err = pipeline.Job("some-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
someOtherJob, found, err = pipeline.Job("some-other-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
build, err := someJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
_, err = someOtherJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
builds[i] = build
|
|
}
|
|
})
|
|
|
|
Context("when there are no builds to be found", func() {
|
|
It("returns the builds, with previous/next pages", func() {
|
|
buildsPage, pagination, err := someOtherJob.Builds(db.Page{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{}))
|
|
Expect(pagination).To(Equal(db.Pagination{}))
|
|
})
|
|
})
|
|
|
|
Context("with no since/until", func() {
|
|
It("returns the first page, with the given limit, and a next page", func() {
|
|
buildsPage, pagination, err := someJob.Builds(db.Page{Limit: 2})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{builds[9], builds[8]}))
|
|
Expect(pagination.Previous).To(BeNil())
|
|
Expect(pagination.Next).To(Equal(&db.Page{Since: builds[8].ID(), Limit: 2}))
|
|
})
|
|
})
|
|
|
|
Context("with a since that places it in the middle of the builds", func() {
|
|
It("returns the builds, with previous/next pages", func() {
|
|
buildsPage, pagination, err := someJob.Builds(db.Page{Since: builds[6].ID(), Limit: 2})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{builds[5], builds[4]}))
|
|
Expect(pagination.Previous).To(Equal(&db.Page{Until: builds[5].ID(), Limit: 2}))
|
|
Expect(pagination.Next).To(Equal(&db.Page{Since: builds[4].ID(), Limit: 2}))
|
|
})
|
|
})
|
|
|
|
Context("with a since that places it at the end of the builds", func() {
|
|
It("returns the builds, with previous/next pages", func() {
|
|
buildsPage, pagination, err := someJob.Builds(db.Page{Since: builds[2].ID(), Limit: 2})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{builds[1], builds[0]}))
|
|
Expect(pagination.Previous).To(Equal(&db.Page{Until: builds[1].ID(), Limit: 2}))
|
|
Expect(pagination.Next).To(BeNil())
|
|
})
|
|
})
|
|
|
|
Context("with an until that places it in the middle of the builds", func() {
|
|
It("returns the builds, with previous/next pages", func() {
|
|
buildsPage, pagination, err := someJob.Builds(db.Page{Until: builds[6].ID(), Limit: 2})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{builds[8], builds[7]}))
|
|
Expect(pagination.Previous).To(Equal(&db.Page{Until: builds[8].ID(), Limit: 2}))
|
|
Expect(pagination.Next).To(Equal(&db.Page{Since: builds[7].ID(), Limit: 2}))
|
|
})
|
|
})
|
|
|
|
Context("with a until that places it at the beginning of the builds", func() {
|
|
It("returns the builds, with previous/next pages", func() {
|
|
buildsPage, pagination, err := someJob.Builds(db.Page{Until: builds[7].ID(), Limit: 2})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(buildsPage).To(Equal([]db.Build{builds[9], builds[8]}))
|
|
Expect(pagination.Previous).To(BeNil())
|
|
Expect(pagination.Next).To(Equal(&db.Page{Since: builds[8].ID(), Limit: 2}))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("BuildsWithTime", func() {
|
|
|
|
var (
|
|
pipeline db.Pipeline
|
|
builds = make([]db.Build, 4)
|
|
job db.Job
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var (
|
|
err error
|
|
found bool
|
|
)
|
|
|
|
config := atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{
|
|
Name: "some-job",
|
|
},
|
|
{
|
|
Name: "some-other-job",
|
|
},
|
|
},
|
|
}
|
|
pipeline, _, err = team.SavePipeline("some-pipeline", config, db.ConfigVersion(1), db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
job, found, err = pipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
for i := range builds {
|
|
builds[i], err = job.CreateBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
buildStart := time.Date(2020, 11, i+1, 0, 0, 0, 0, time.UTC)
|
|
_, err = dbConn.Exec("UPDATE builds SET start_time = to_timestamp($1) WHERE id = $2", buildStart.Unix(), builds[i].ID())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
builds[i], found, err = job.Build(builds[i].Name())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
}
|
|
})
|
|
|
|
Context("when not providing boundaries", func() {
|
|
Context("without a limit specified", func() {
|
|
It("returns no builds", func() {
|
|
returnedBuilds, _, err := job.BuildsWithTime(db.Page{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(returnedBuilds).To(BeEmpty())
|
|
})
|
|
})
|
|
|
|
Context("when a limit specified", func() {
|
|
It("returns a subset of the builds", func() {
|
|
returnedBuilds, _, err := job.BuildsWithTime(db.Page{
|
|
Limit: 2,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(returnedBuilds).To(ConsistOf(builds[3], builds[2]))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when providing boundaries", func() {
|
|
Context("only until", func() {
|
|
It("returns only those after until", func() {
|
|
returnedBuilds, _, err := job.BuildsWithTime(db.Page{
|
|
Until: int(builds[2].StartTime().Unix()),
|
|
Limit: 50,
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(returnedBuilds).To(ConsistOf(builds[0], builds[1], builds[2]))
|
|
})
|
|
})
|
|
|
|
Context("only since", func() {
|
|
It("returns only those before since", func() {
|
|
returnedBuilds, _, err := job.BuildsWithTime(db.Page{
|
|
Since: int(builds[1].StartTime().Unix()),
|
|
Limit: 50,
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(returnedBuilds).To(ConsistOf(builds[1], builds[2], builds[3]))
|
|
})
|
|
})
|
|
|
|
Context("since and until", func() {
|
|
It("returns only elements in the range", func() {
|
|
returnedBuilds, _, err := job.BuildsWithTime(db.Page{
|
|
Until: int(builds[2].StartTime().Unix()),
|
|
Since: int(builds[1].StartTime().Unix()),
|
|
Limit: 50,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(returnedBuilds).To(ConsistOf(builds[1], builds[2]))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("Build", func() {
|
|
var firstBuild db.Build
|
|
|
|
Context("when a build exists", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
firstBuild, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("finds the latest build", func() {
|
|
secondBuild, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
build, found, err := job.Build("latest")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(secondBuild.ID()))
|
|
Expect(build.Status()).To(Equal(secondBuild.Status()))
|
|
})
|
|
|
|
It("finds the build", func() {
|
|
build, found, err := job.Build(firstBuild.Name())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(firstBuild.ID()))
|
|
Expect(build.Status()).To(Equal(firstBuild.Status()))
|
|
})
|
|
})
|
|
|
|
Context("when the build does not exist", func() {
|
|
It("does not error", func() {
|
|
build, found, err := job.Build("bogus-build")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeFalse())
|
|
Expect(build).To(BeNil())
|
|
})
|
|
|
|
It("does not error finding the latest", func() {
|
|
build, found, err := job.Build("latest")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeFalse())
|
|
Expect(build).To(BeNil())
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GetRunningBuildsBySerialGroup", func() {
|
|
Describe("same job", func() {
|
|
var startedBuild, scheduledBuild db.Build
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
_, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
startedBuild, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
_, err = startedBuild.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
_, err = startedBuild.Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
scheduledBuild, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
scheduled, err := scheduledBuild.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(scheduled).To(BeTrue())
|
|
|
|
for _, s := range []db.BuildStatus{db.BuildStatusSucceeded, db.BuildStatusFailed, db.BuildStatusErrored, db.BuildStatusAborted} {
|
|
finishedBuild, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
scheduled, err = finishedBuild.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(scheduled).To(BeTrue())
|
|
|
|
err = finishedBuild.Finish(s)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
|
|
otherJob, found, err := pipeline.Job("some-other-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
_, err = otherJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("returns a list of running or schedule builds for said job", func() {
|
|
builds, err := job.GetRunningBuildsBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(builds)).To(Equal(2))
|
|
ids := []int{}
|
|
for _, build := range builds {
|
|
ids = append(ids, build.ID())
|
|
}
|
|
Expect(ids).To(ConsistOf([]int{startedBuild.ID(), scheduledBuild.ID()}))
|
|
})
|
|
})
|
|
|
|
Describe("multiple jobs with same serial group", func() {
|
|
var serialGroupBuild db.Build
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
_, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
otherSerialJob, found, err := pipeline.Job("other-serial-group-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
serialGroupBuild, err = otherSerialJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
scheduled, err := serialGroupBuild.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(scheduled).To(BeTrue())
|
|
|
|
differentSerialJob, found, err := pipeline.Job("different-serial-group-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
differentSerialGroupBuild, err := differentSerialJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
scheduled, err = differentSerialGroupBuild.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(scheduled).To(BeTrue())
|
|
})
|
|
|
|
It("returns a list of builds in the same serial group", func() {
|
|
builds, err := job.GetRunningBuildsBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(builds)).To(Equal(1))
|
|
Expect(builds[0].ID()).To(Equal(serialGroupBuild.ID()))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GetNextPendingBuildBySerialGroup", func() {
|
|
var job1, job2 db.Job
|
|
|
|
BeforeEach(func() {
|
|
var found bool
|
|
var err error
|
|
job1, found, err = pipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
job2, found, err = pipeline.Job("other-serial-group-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
Context("when some jobs have builds with inputs determined as false", func() {
|
|
var actualBuild db.Build
|
|
|
|
BeforeEach(func() {
|
|
_, err := job1.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
actualBuild, err = job2.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = job2.SaveNextInputMapping(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("should return the next most pending build in a group of jobs", func() {
|
|
build, found, err := job1.GetNextPendingBuildBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(actualBuild.ID()))
|
|
})
|
|
})
|
|
|
|
It("should return the next most pending build in a group of jobs", func() {
|
|
buildOne, err := job1.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildTwo, err := job1.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildThree, err := job2.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = job1.SaveNextInputMapping(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
err = job2.SaveNextInputMapping(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
build, found, err := job1.GetNextPendingBuildBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildOne.ID()))
|
|
|
|
err = job1.Pause()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
build, found, err = job1.GetNextPendingBuildBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildThree.ID()))
|
|
|
|
err = job1.Unpause()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
build, found, err = job2.GetNextPendingBuildBySerialGroup([]string{"serial-group", "really-different-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildOne.ID()))
|
|
|
|
Expect(buildOne.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
|
|
build, found, err = job1.GetNextPendingBuildBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildTwo.ID()))
|
|
|
|
build, found, err = job2.GetNextPendingBuildBySerialGroup([]string{"serial-group", "really-different-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildTwo.ID()))
|
|
|
|
scheduled, err := buildTwo.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(scheduled).To(BeTrue())
|
|
Expect(buildTwo.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
|
|
build, found, err = job1.GetNextPendingBuildBySerialGroup([]string{"serial-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildThree.ID()))
|
|
|
|
build, found, err = job2.GetNextPendingBuildBySerialGroup([]string{"serial-group", "really-different-group"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build.ID()).To(Equal(buildThree.ID()))
|
|
})
|
|
})
|
|
|
|
Describe("GetIndependentBuildInputs", func() {
|
|
var (
|
|
pipeline2 db.Pipeline
|
|
versions []atc.ResourceVersion
|
|
job db.Job
|
|
job2 db.Job
|
|
resourceConfigScope db.ResourceConfigScope
|
|
resource db.Resource
|
|
resource2 db.Resource
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
setupTx, err := dbConn.Begin()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
brt := db.BaseResourceType{
|
|
Name: "some-type",
|
|
}
|
|
|
|
_, err = brt.FindOrCreate(setupTx, false)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(setupTx.Commit()).To(Succeed())
|
|
|
|
var found bool
|
|
job, found, err = pipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
resource, found, err = pipeline.Resource("some-resource")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
resourceConfigScope, err = resource.SetResourceConfig(atc.Source{}, atc.VersionedResourceTypes{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = resourceConfigScope.SaveVersions([]atc.Version{
|
|
{"version": "v1"},
|
|
{"version": "v2"},
|
|
{"version": "v3"},
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// save metadata for v1
|
|
_, err = resource.SaveUncheckedVersion(atc.Version{"version": "v1"}, db.ResourceConfigMetadataFields{
|
|
db.ResourceConfigMetadataField{
|
|
Name: "name1",
|
|
Value: "value1",
|
|
},
|
|
}, resourceConfigScope.ResourceConfig(), atc.VersionedResourceTypes{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
reversions, _, found, err := resource.Versions(db.Page{Limit: 3})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
versions = []atc.ResourceVersion{reversions[2], reversions[1], reversions[0]}
|
|
|
|
config := atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{
|
|
Name: "some-job",
|
|
},
|
|
{
|
|
Name: "some-other-job",
|
|
},
|
|
},
|
|
Resources: atc.ResourceConfigs{
|
|
{
|
|
Name: "some-resource",
|
|
Type: "some-type",
|
|
},
|
|
},
|
|
}
|
|
|
|
pipeline2, _, err = team.SavePipeline("some-pipeline-2", config, 1, db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
resource2, found, err = pipeline2.Resource("some-resource")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
job2, found, err = pipeline2.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
Describe("independent build inputs", func() {
|
|
It("gets independent build inputs for the given job name", func() {
|
|
inputVersions := algorithm.InputMapping{
|
|
"some-input-1": algorithm.InputVersion{
|
|
VersionID: versions[0].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
"some-input-2": algorithm.InputVersion{
|
|
VersionID: versions[1].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
err := job.SaveIndependentInputMapping(inputVersions)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
pipeline2InputVersions := algorithm.InputMapping{
|
|
"some-input-3": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource2.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
}
|
|
err = job2.SaveIndependentInputMapping(pipeline2InputVersions)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildInputs := []db.BuildInput{
|
|
{
|
|
Name: "some-input-1",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v1"},
|
|
FirstOccurrence: false,
|
|
},
|
|
{
|
|
Name: "some-input-2",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v2"},
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
|
|
actualBuildInputs, err := job.GetIndependentBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(actualBuildInputs).To(ConsistOf(buildInputs))
|
|
|
|
By("updating the set of independent build inputs")
|
|
inputVersions2 := algorithm.InputMapping{
|
|
"some-input-2": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
"some-input-3": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
err = job.SaveIndependentInputMapping(inputVersions2)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildInputs2 := []db.BuildInput{
|
|
{
|
|
Name: "some-input-2",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v3"},
|
|
FirstOccurrence: false,
|
|
},
|
|
{
|
|
Name: "some-input-3",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v3"},
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
|
|
actualBuildInputs2, err := job.GetIndependentBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(actualBuildInputs2).To(ConsistOf(buildInputs2))
|
|
|
|
By("updating independent build inputs to an empty set when the mapping is nil")
|
|
err = job.SaveIndependentInputMapping(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
actualBuildInputs3, err := job.GetIndependentBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(actualBuildInputs3).To(BeEmpty())
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GetNextBuildInputs", func() {
|
|
var (
|
|
pipeline2 db.Pipeline
|
|
versions []atc.ResourceVersion
|
|
job db.Job
|
|
job2 db.Job
|
|
resourceConfigScope db.ResourceConfigScope
|
|
resource db.Resource
|
|
resource2 db.Resource
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
setupTx, err := dbConn.Begin()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
brt := db.BaseResourceType{
|
|
Name: "some-type",
|
|
}
|
|
|
|
_, err = brt.FindOrCreate(setupTx, false)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(setupTx.Commit()).To(Succeed())
|
|
|
|
var found bool
|
|
job, found, err = pipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
resource, found, err = pipeline.Resource("some-resource")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
resourceConfigScope, err = resource.SetResourceConfig(atc.Source{}, atc.VersionedResourceTypes{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = resourceConfigScope.SaveVersions([]atc.Version{
|
|
{"version": "v1"},
|
|
{"version": "v2"},
|
|
{"version": "v3"},
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// save metadata for v1
|
|
_, err = resource.SaveUncheckedVersion(atc.Version{"version": "v1"}, db.ResourceConfigMetadataFields{
|
|
db.ResourceConfigMetadataField{
|
|
Name: "name1",
|
|
Value: "value1",
|
|
},
|
|
}, resourceConfigScope.ResourceConfig(), atc.VersionedResourceTypes{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
reversions, _, found, err := resource.Versions(db.Page{Limit: 3})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
versions = []atc.ResourceVersion{reversions[2], reversions[1], reversions[0]}
|
|
|
|
config := atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{
|
|
Name: "some-job",
|
|
},
|
|
{
|
|
Name: "some-other-job",
|
|
},
|
|
},
|
|
Resources: atc.ResourceConfigs{
|
|
{
|
|
Name: "some-resource",
|
|
Type: "some-type",
|
|
},
|
|
},
|
|
}
|
|
|
|
pipeline2, _, err = team.SavePipeline("some-pipeline-2", config, 1, db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
resource2, found, err = pipeline2.Resource("some-resource")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
job2, found, err = pipeline2.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
It("gets next build inputs for the given job name", func() {
|
|
inputVersions := algorithm.InputMapping{
|
|
"some-input-1": algorithm.InputVersion{
|
|
VersionID: versions[0].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
"some-input-2": algorithm.InputVersion{
|
|
VersionID: versions[1].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
err := job.SaveNextInputMapping(inputVersions)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
pipeline2InputVersions := algorithm.InputMapping{
|
|
"some-input-3": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource2.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
}
|
|
err = job2.SaveNextInputMapping(pipeline2InputVersions)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildInputs := []db.BuildInput{
|
|
{
|
|
Name: "some-input-1",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v1"},
|
|
FirstOccurrence: false,
|
|
},
|
|
{
|
|
Name: "some-input-2",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v2"},
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
|
|
actualBuildInputs, found, err := job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(actualBuildInputs).To(ConsistOf(buildInputs))
|
|
|
|
By("updating the set of next build inputs")
|
|
inputVersions2 := algorithm.InputMapping{
|
|
"some-input-2": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: false,
|
|
},
|
|
"some-input-3": algorithm.InputVersion{
|
|
VersionID: versions[2].ID,
|
|
ResourceID: resource.ID(),
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
err = job.SaveNextInputMapping(inputVersions2)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
buildInputs2 := []db.BuildInput{
|
|
{
|
|
Name: "some-input-2",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v3"},
|
|
FirstOccurrence: false,
|
|
},
|
|
{
|
|
Name: "some-input-3",
|
|
ResourceID: resource.ID(),
|
|
Version: atc.Version{"version": "v3"},
|
|
FirstOccurrence: true,
|
|
},
|
|
}
|
|
|
|
actualBuildInputs2, found, err := job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(actualBuildInputs2).To(ConsistOf(buildInputs2))
|
|
|
|
By("updating next build inputs to an empty set when the mapping is nil")
|
|
err = job.SaveNextInputMapping(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
actualBuildInputs3, found, err := job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(actualBuildInputs3).To(BeEmpty())
|
|
})
|
|
|
|
It("distinguishes between a job with no inputs and a job with missing inputs", func() {
|
|
By("initially returning not found")
|
|
_, found, err := job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeFalse())
|
|
|
|
By("returning found when an empty input mapping is saved")
|
|
err = job.SaveNextInputMapping(algorithm.InputMapping{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
_, found, err = job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
By("returning not found when the input mapping is deleted")
|
|
err = job.DeleteNextInputMapping()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
_, found, err = job.GetNextBuildInputs()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeFalse())
|
|
})
|
|
})
|
|
|
|
Describe("a build is created for a job", func() {
|
|
var (
|
|
build1DB db.Build
|
|
otherPipeline db.Pipeline
|
|
otherJob db.Job
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
pipelineConfig := atc.Config{
|
|
Jobs: atc.JobConfigs{
|
|
{
|
|
Name: "some-job",
|
|
},
|
|
},
|
|
Resources: atc.ResourceConfigs{
|
|
{
|
|
Name: "some-other-resource",
|
|
Type: "some-type",
|
|
},
|
|
},
|
|
}
|
|
var err error
|
|
otherPipeline, _, err = team.SavePipeline("some-other-pipeline", pipelineConfig, db.ConfigVersion(1), db.PipelineUnpaused)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
build1DB, err = job.CreateBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(build1DB.ID()).NotTo(BeZero())
|
|
Expect(build1DB.JobName()).To(Equal("some-job"))
|
|
Expect(build1DB.Name()).To(Equal("1"))
|
|
Expect(build1DB.Status()).To(Equal(db.BuildStatusPending))
|
|
Expect(build1DB.IsScheduled()).To(BeFalse())
|
|
Expect(build1DB.CreateTime()).To(BeTemporally("~", time.Now(), 100*time.Millisecond))
|
|
|
|
var found bool
|
|
otherJob, found, err = otherPipeline.Job("some-job")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
It("becomes the next pending build for job", func() {
|
|
nextPendings, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
//time.Sleep(10 * time.Hour)
|
|
Expect(nextPendings).NotTo(BeEmpty())
|
|
Expect(nextPendings[0].ID()).To(Equal(build1DB.ID()))
|
|
})
|
|
|
|
It("is in the list of pending builds", func() {
|
|
nextPendingBuilds, err := pipeline.GetAllPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds["some-job"]).To(HaveLen(1))
|
|
Expect(nextPendingBuilds["some-job"]).To(Equal([]db.Build{build1DB}))
|
|
})
|
|
|
|
Context("and another build for a different pipeline is created with the same job name", func() {
|
|
BeforeEach(func() {
|
|
otherBuild, err := otherJob.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(otherBuild.ID()).NotTo(BeZero())
|
|
Expect(otherBuild.JobName()).To(Equal("some-job"))
|
|
Expect(otherBuild.Name()).To(Equal("1"))
|
|
Expect(otherBuild.Status()).To(Equal(db.BuildStatusPending))
|
|
Expect(otherBuild.IsScheduled()).To(BeFalse())
|
|
})
|
|
|
|
It("does not change the next pending build for job", func() {
|
|
nextPendingBuilds, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds).To(Equal([]db.Build{build1DB}))
|
|
})
|
|
|
|
It("does not change pending builds", func() {
|
|
nextPendingBuilds, err := pipeline.GetAllPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds["some-job"]).To(HaveLen(1))
|
|
Expect(nextPendingBuilds["some-job"]).To(Equal([]db.Build{build1DB}))
|
|
})
|
|
})
|
|
|
|
Context("when scheduled", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
var found bool
|
|
found, err = build1DB.Schedule()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
})
|
|
|
|
It("remains the next pending build for job", func() {
|
|
nextPendingBuilds, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds).NotTo(BeEmpty())
|
|
Expect(nextPendingBuilds[0].ID()).To(Equal(build1DB.ID()))
|
|
})
|
|
|
|
It("remains in the list of pending builds", func() {
|
|
nextPendingBuilds, err := pipeline.GetAllPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds["some-job"]).To(HaveLen(1))
|
|
Expect(nextPendingBuilds["some-job"][0].ID()).To(Equal(build1DB.ID()))
|
|
})
|
|
})
|
|
|
|
Context("when started", func() {
|
|
BeforeEach(func() {
|
|
started, err := build1DB.Start(atc.Plan{ID: "some-id"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(started).To(BeTrue())
|
|
})
|
|
|
|
It("saves the updated status, and the schema and private plan", func() {
|
|
found, err := build1DB.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build1DB.Status()).To(Equal(db.BuildStatusStarted))
|
|
Expect(build1DB.Schema()).To(Equal("exec.v2"))
|
|
Expect(build1DB.PrivatePlan()).To(Equal(atc.Plan{ID: "some-id"}))
|
|
})
|
|
|
|
It("saves the build's start time", func() {
|
|
found, err := build1DB.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build1DB.StartTime().Unix()).To(BeNumerically("~", time.Now().Unix(), 3))
|
|
})
|
|
})
|
|
|
|
Context("when the build finishes", func() {
|
|
BeforeEach(func() {
|
|
err := build1DB.Finish(db.BuildStatusSucceeded)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("sets the build's status and end time", func() {
|
|
found, err := build1DB.Reload()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(build1DB.Status()).To(Equal(db.BuildStatusSucceeded))
|
|
Expect(build1DB.EndTime().Unix()).To(BeNumerically("~", time.Now().Unix(), 3))
|
|
})
|
|
})
|
|
|
|
Context("and another is created for the same job", func() {
|
|
var build2DB db.Build
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
build2DB, err = job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(build2DB.ID()).NotTo(BeZero())
|
|
Expect(build2DB.ID()).NotTo(Equal(build1DB.ID()))
|
|
Expect(build2DB.Name()).To(Equal("2"))
|
|
Expect(build2DB.Status()).To(Equal(db.BuildStatusPending))
|
|
})
|
|
|
|
Describe("the first build", func() {
|
|
It("remains the next pending build", func() {
|
|
nextPendingBuilds, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds).To(HaveLen(2))
|
|
Expect(nextPendingBuilds[0].ID()).To(Equal(build1DB.ID()))
|
|
Expect(nextPendingBuilds[1].ID()).To(Equal(build2DB.ID()))
|
|
})
|
|
|
|
It("remains in the list of pending builds", func() {
|
|
nextPendingBuilds, err := pipeline.GetAllPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(nextPendingBuilds["some-job"]).To(HaveLen(2))
|
|
Expect(nextPendingBuilds["some-job"]).To(ConsistOf(build1DB, build2DB))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("EnsurePendingBuildExists", func() {
|
|
Context("when only a started build exists", func() {
|
|
BeforeEach(func() {
|
|
build1, err := job.CreateBuild()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
started, err := build1.Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(started).To(BeTrue())
|
|
})
|
|
|
|
It("creates a build", func() {
|
|
err := job.EnsurePendingBuildExists()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
pendingBuilds, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(pendingBuilds).To(HaveLen(1))
|
|
})
|
|
|
|
It("doesn't create another build the second time it's called", func() {
|
|
err := job.EnsurePendingBuildExists()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = job.EnsurePendingBuildExists()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
builds2, err := job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(builds2).To(HaveLen(1))
|
|
|
|
started, err := builds2[0].Start(atc.Plan{})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(started).To(BeTrue())
|
|
|
|
builds2, err = job.GetPendingBuilds()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(builds2).To(HaveLen(0))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("Clear task cache", func() {
|
|
Context("when task cache exists", func() {
|
|
var (
|
|
someOtherJob db.Job
|
|
rowsDeleted int64
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var (
|
|
err error
|
|
found bool
|
|
)
|
|
|
|
usedTaskCache, err := taskCacheFactory.FindOrCreate(job.ID(), "some-task", "some-path")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
_, err = workerTaskCacheFactory.FindOrCreate(db.WorkerTaskCache{
|
|
TaskCache: usedTaskCache,
|
|
WorkerName: defaultWorker.Name(),
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
someOtherJob, found, err = pipeline.Job("some-other-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(someOtherJob).ToNot(BeNil())
|
|
|
|
otherUsedTaskCache, err := taskCacheFactory.FindOrCreate(someOtherJob.ID(), "some-other-task", "some-other-path")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
_, err = workerTaskCacheFactory.FindOrCreate(db.WorkerTaskCache{
|
|
TaskCache: otherUsedTaskCache,
|
|
WorkerName: defaultWorker.Name(),
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
})
|
|
|
|
Context("when a path is provided", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
rowsDeleted, err = job.ClearTaskCache("some-task", "some-path")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("deletes a row from the task_caches table", func() {
|
|
Expect(rowsDeleted).To(Equal(int64(1)))
|
|
})
|
|
|
|
It("removes the task cache", func() {
|
|
usedTaskCache, found, err := taskCacheFactory.Find(job.ID(), "some-task", "some-path")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(usedTaskCache).To(BeNil())
|
|
Expect(found).To(BeFalse())
|
|
})
|
|
|
|
It("doesn't remove other jobs caches", func() {
|
|
otherUsedTaskCache, found, err := taskCacheFactory.Find(someOtherJob.ID(), "some-other-task", "some-other-path")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
_, err = workerTaskCacheFactory.FindOrCreate(db.WorkerTaskCache{
|
|
TaskCache: otherUsedTaskCache,
|
|
WorkerName: defaultWorker.Name(),
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
Context("but the cache path doesn't exist", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
rowsDeleted, err = job.ClearTaskCache("some-task", "some-nonexistent-path")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
It("deletes 0 rows", func() {
|
|
Expect(rowsDeleted).To(Equal(int64(0)))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when a path is not provided", func() {
|
|
Context("when a non-existent step-name is provided", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
rowsDeleted, err = job.ClearTaskCache("some-nonexistent-task", "")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("does not delete any rows from the task_caches table", func() {
|
|
Expect(rowsDeleted).To(BeZero())
|
|
})
|
|
|
|
It("should not delete any task steps", func() {
|
|
usedTaskCache, found, err := taskCacheFactory.Find(job.ID(), "some-task", "some-path")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
_, found, err = workerTaskCacheFactory.Find(db.WorkerTaskCache{
|
|
TaskCache: usedTaskCache,
|
|
WorkerName: defaultWorker.Name(),
|
|
})
|
|
Expect(found).To(BeTrue())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
})
|
|
|
|
Context("when an existing step-name is provided", func() {
|
|
BeforeEach(func() {
|
|
var err error
|
|
rowsDeleted, err = job.ClearTaskCache("some-task", "")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("deletes a row from the task_caches table", func() {
|
|
Expect(rowsDeleted).To(Equal(int64(1)))
|
|
})
|
|
|
|
It("removes the task cache", func() {
|
|
_, found, err := taskCacheFactory.Find(job.ID(), "some-task", "some-path")
|
|
Expect(found).To(BeFalse())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("doesn't remove other jobs caches", func() {
|
|
_, found, err := taskCacheFactory.Find(someOtherJob.ID(), "some-other-task", "some-other-path")
|
|
Expect(found).To(BeTrue())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("New Inputs", func() {
|
|
It("starts out as false", func() {
|
|
Expect(job.HasNewInputs()).To(BeFalse())
|
|
})
|
|
|
|
It("can be set to true then back to false", func() {
|
|
job.SetHasNewInputs(true)
|
|
|
|
found, err := job.Reload()
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(job.HasNewInputs()).To(BeTrue())
|
|
|
|
job.SetHasNewInputs(false)
|
|
|
|
found, err = job.Reload()
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
Expect(job.HasNewInputs()).To(BeFalse())
|
|
})
|
|
|
|
})
|
|
})
|