Skip to content
This repository has been archived by the owner on Mar 24, 2022. It is now read-only.

Commit

Permalink
Merge branch 'kurtmc-fly-abort'
Browse files Browse the repository at this point in the history
  • Loading branch information
Topher Bullock committed Jul 20, 2017
2 parents dd0a471 + 8b5e25d commit cb333b5
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 55 deletions.
15 changes: 11 additions & 4 deletions commands/abort_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"fmt"
"strconv"

"github.com/concourse/atc"
"github.com/concourse/fly/commands/internal/flaghelpers"
"github.com/concourse/fly/rc"
)

type AbortBuildCommand struct {
Job flaghelpers.JobFlag `short:"j" long:"job" required:"true" value-name:"PIPELINE/JOB" description:"Name of a job to cancel"`
Build string `short:"b" long:"build" required:"true" description:"Name of the build to cancel"`
Job flaghelpers.JobFlag `short:"j" long:"job" value-name:"PIPELINE/JOB" description:"Name of a job to cancel"`
Build string `short:"b" long:"build" required:"true" description:"If job is specified: build number to cancel. If job not specified: build id"`
}

func (command *AbortBuildCommand) Execute([]string) error {
Expand All @@ -24,13 +25,19 @@ func (command *AbortBuildCommand) Execute([]string) error {
return err
}

build, exists, err := target.Team().JobBuild(command.Job.PipelineName, command.Job.JobName, command.Build)
var build atc.Build
var exists bool
if command.Job.PipelineName == "" && command.Job.JobName == "" {
build, exists, err = target.Client().Build(command.Build)
} else {
build, exists, err = target.Team().JobBuild(command.Job.PipelineName, command.Job.JobName, command.Build)
}
if err != nil {
return err
}

if !exists {
return fmt.Errorf("job build does not exist")
return fmt.Errorf("build does not exist")
}

if err := target.Client().AbortBuild(strconv.Itoa(build.ID)); err != nil {
Expand Down
191 changes: 140 additions & 51 deletions integration/abort_build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,82 +15,171 @@ import (
)

var _ = Describe("AbortBuild", func() {
BeforeEach(func() {
expectedBuild := atc.Build{
ID: 23,
Name: "42",
Status: "running",
JobName: "myjob",
URL: "/pipelines/my-pipeline/jobs/my-job/builds/42",
APIURL: "api/v1/builds/123",
}

expectedJobBuildURL := "/api/v1/teams/main/pipelines/my-pipeline/jobs/my-job/builds/42"
expectedAbortURL := "/api/v1/builds/23/abort"

atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedJobBuildURL),
ghttp.RespondWithJSONEncoded(http.StatusOK, expectedBuild),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("PUT", expectedAbortURL),
ghttp.RespondWith(http.StatusNoContent, ""),
),
)
})
var expectedAbortURL = "/api/v1/builds/23/abort"

var expectedBuild = atc.Build{
ID: 23,
Name: "42",
Status: "running",
JobName: "myjob",
URL: "/pipelines/my-pipeline/jobs/my-job/builds/42",
APIURL: "api/v1/builds/123",
}

Context("when the job name is not specified", func() {
It("asks the user to specifiy a job name", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-b", "some-build-name")
Context("and the build id is specified", func() {
BeforeEach(func() {
expectedURL := "/api/v1/builds/23"

atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedURL),
ghttp.RespondWithJSONEncoded(http.StatusOK, expectedBuild),
),

ghttp.CombineHandlers(
ghttp.VerifyRequest("PUT", expectedAbortURL),
ghttp.RespondWith(http.StatusNoContent, ""),
),
)
})

It("aborts the build", func() {
Expect(func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-b", "23")

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(0))

Expect(sess.Out).To(gbytes.Say("build successfully aborted"))
}).To(Change(func() int {
return len(atcServer.ReceivedRequests())
}).By(3))
})
})

Context("and the build id does not exist", func() {
BeforeEach(func() {
expectedURL := "/api/v1/builds/42"

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedURL),
ghttp.RespondWith(http.StatusNotFound, ""),
),
)
})

Eventually(sess).Should(gexec.Exit(1))
It("asks the user to specifiy a build id", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-b", "42")

Expect(sess.Err).To(gbytes.Say("error: the required flag `" + osFlag("j", "job") + "' was not specified"))
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(1))

Expect(sess.Err).To(gbytes.Say("error: build does not exist"))
})
})
})

Context("when the build name is not specified", func() {
It("asks the user to specifiy a build name", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-j", "some-pipeline-name/some-job-name")
Context("and the build id is not specified", func() {
It("asks the user to specifiy a build id", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build")

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(1))
Eventually(sess).Should(gexec.Exit(1))

Expect(sess.Err).To(gbytes.Say("error: the required flag `" + osFlag("b", "build") + "' was not specified"))
Expect(sess.Err).To(gbytes.Say("error: the required flag `" + osFlag("b", "build") + "' was not specified"))
})
})
})

Context("when the pipeline/build exists", func() {
It("aborts the build", func() {
Expect(func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-j", "my-pipeline/my-job", "-b", "42")
Context("and the build name is specified", func() {
BeforeEach(func() {
expectedURL := "/api/v1/teams/main/pipelines/my-pipeline/jobs/my-job/builds/42"

atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedURL),
ghttp.RespondWithJSONEncoded(http.StatusOK, expectedBuild),
),

ghttp.CombineHandlers(
ghttp.VerifyRequest("PUT", expectedAbortURL),
ghttp.RespondWith(http.StatusNoContent, ""),
),
)
})

It("aborts the build", func() {
Expect(func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-j", "my-pipeline/my-job", "-b", "42")

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(0))

Expect(sess.Out).To(gbytes.Say("build successfully aborted"))
}).To(Change(func() int {
return len(atcServer.ReceivedRequests())
}).By(3))
})
})

Context("and the build number does not exist", func() {
BeforeEach(func() {
expectedURL := "/api/v1/teams/main/pipelines/my-pipeline/jobs/my-job/builds/23"

atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedURL),
ghttp.RespondWith(http.StatusNotFound, ""),
),
)
})

It("asks the user to specifiy a build name", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-j", "my-pipeline/my-job", "-b", "23")

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(0))
Eventually(sess).Should(gexec.Exit(1))

Expect(sess.Out).To(gbytes.Say("build successfully aborted"))
}).To(Change(func() int {
return len(atcServer.ReceivedRequests())
}).By(3))
Expect(sess.Err).To(gbytes.Say("error: build does not exist"))
})
})

Context("and the build name is not specified", func() {
It("asks the user to specifiy a build name", func() {
flyCmd := exec.Command(flyPath, "-t", targetName, "abort-build", "-j", "some-pipeline-name/some-job-name")

sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(1))

Expect(sess.Err).To(gbytes.Say("error: the required flag `" + osFlag("b", "build") + "' was not specified"))
})
})
})

Context("when the build or pipeline does not exist", func() {
BeforeEach(func() {
expectedJobBuildURL := "/api/v1/teams/main/pipelines/my-pipeline/jobs/my-job/builds/42"

atcServer.SetHandler(4, ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedJobBuildURL),
ghttp.RespondWith(http.StatusNotFound, "{}"),
))
atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", expectedJobBuildURL),
ghttp.RespondWith(http.StatusNotFound, "{}"),
),
)
})

It("returns a helpful error message", func() {
Expand All @@ -100,7 +189,7 @@ var _ = Describe("AbortBuild", func() {
Expect(err).NotTo(HaveOccurred())

Eventually(sess).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say("error: job build does not exist"))
Expect(sess.Err).To(gbytes.Say("error: build does not exist"))
}).To(Change(func() int {
return len(atcServer.ReceivedRequests())
}).By(2))
Expand Down

0 comments on commit cb333b5

Please sign in to comment.