From 0deda9939c2f525d8c3bd38fb84c0ecc29fac322 Mon Sep 17 00:00:00 2001 From: Chris Brown Date: Sun, 1 Feb 2015 12:37:29 +0000 Subject: [PATCH] implement check command --- check_command.go | 62 ++++++++++++++++++ check_command_test.go | 120 ++++++++++++++++++++++++++++++++++ cmd/check/check.go | 31 ++++++++- cmd/check/check_suite_test.go | 27 -------- cmd/check/check_test.go | 23 ------- fakes/fake_git_hub.go | 32 +++++++++ github.go | 12 +++- resources.go | 17 +++-- 8 files changed, 265 insertions(+), 59 deletions(-) create mode 100644 check_command.go create mode 100644 check_command_test.go delete mode 100644 cmd/check/check_suite_test.go delete mode 100644 cmd/check/check_test.go diff --git a/check_command.go b/check_command.go new file mode 100644 index 0000000..ca2cc37 --- /dev/null +++ b/check_command.go @@ -0,0 +1,62 @@ +package resource + +import ( + "errors" + + "github.com/google/go-github/github" +) + +type CheckCommand struct { + github GitHub +} + +func NewCheckCommand(github GitHub) *CheckCommand { + return &CheckCommand{ + github: github, + } +} + +func (c *CheckCommand) Run(request CheckRequest) ([]Version, error) { + releases, err := c.github.ListReleases() + if err != nil { + return []Version{}, err + } + + if len(releases) == 0 { + return []Version{}, errors.New("repository had no releases") + } + + latestVersion := *releases[0].TagName + + if request.Version.Tag == "" { + return []Version{ + {Tag: latestVersion}, + }, nil + } + + if latestVersion == request.Version.Tag { + return []Version{}, nil + } + + upToLatest := false + reversedVersions := []Version{} + for _, release := range reverse(releases) { + version := *release.TagName + + if upToLatest { + reversedVersions = append(reversedVersions, Version{Tag: version}) + } else { + upToLatest = request.Version.Tag == version + } + } + + return reversedVersions, nil +} + +func reverse(s []github.RepositoryRelease) []github.RepositoryRelease { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } + + return s +} diff --git a/check_command_test.go b/check_command_test.go new file mode 100644 index 0000000..22f9c37 --- /dev/null +++ b/check_command_test.go @@ -0,0 +1,120 @@ +package resource_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/google/go-github/github" + + "github.com/concourse/github-release-resource" + "github.com/concourse/github-release-resource/fakes" +) + +var _ = Describe("Check Command", func() { + var ( + githubClient *fakes.FakeGitHub + command *resource.CheckCommand + + returnedReleases []github.RepositoryRelease + ) + + BeforeEach(func() { + githubClient = &fakes.FakeGitHub{} + command = resource.NewCheckCommand(githubClient) + + returnedReleases = []github.RepositoryRelease{} + }) + + JustBeforeEach(func() { + githubClient.ListReleasesReturns(returnedReleases, nil) + }) + + Context("when this is the first time that the resource has been run", func() { + Context("when there are no releases", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{} + }) + + It("returns an error when there are no releases", func() { + _, err := command.Run(resource.CheckRequest{}) + Ω(err).Should(HaveOccurred()) + }) + }) + + Context("when there are releases", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + {TagName: github.String("0.4.0")}, + {TagName: github.String("0.1.3")}, + {TagName: github.String("0.1.2")}, + } + }) + + It("outputs the most recent version only", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{}) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(HaveLen(1)) + Ω(response[0]).Should(Equal(resource.Version{ + Tag: "0.4.0", + })) + }) + }) + }) + + Context("when there are prior versions", func() { + Context("when there are no releases", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{} + }) + + It("returns an error when there are no releases", func() { + _, err := command.Run(resource.CheckRequest{}) + Ω(err).Should(HaveOccurred()) + }) + }) + + Context("when there are releases", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + {TagName: github.String("0.4.0")}, + {TagName: github.String("0.1.4")}, + {TagName: github.String("0.1.3")}, + {TagName: github.String("0.1.2")}, + } + }) + + It("returns an empty list if the lastet version has been checked", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{ + Tag: "0.4.0", + }, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(BeEmpty()) + }) + + It("all of the versions that are newer", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{ + Tag: "0.1.3", + }, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(HaveLen(2)) + Ω(response).Should(Equal([]resource.Version{ + {Tag: "0.1.4"}, + {Tag: "0.4.0"}, + })) + }) + }) + }) +}) diff --git a/cmd/check/check.go b/cmd/check/check.go index 245c1f5..59c6293 100644 --- a/cmd/check/check.go +++ b/cmd/check/check.go @@ -1,7 +1,34 @@ package main -import "fmt" +import ( + "encoding/json" + "os" + + "github.com/concourse/github-release-resource" +) func main() { - fmt.Println("[]") + var request resource.CheckRequest + inputRequest(&request) + + github := resource.NewGitHubClient(request.Source) + command := resource.NewCheckCommand(github) + response, err := command.Run(request) + if err != nil { + resource.Fatal("running command", err) + } + + outputResponse(response) +} + +func inputRequest(request *resource.CheckRequest) { + if err := json.NewDecoder(os.Stdin).Decode(request); err != nil { + resource.Fatal("reading request from stdin", err) + } +} + +func outputResponse(response []resource.Version) { + if err := json.NewEncoder(os.Stdout).Encode(response); err != nil { + resource.Fatal("writing response to stdout", err) + } } diff --git a/cmd/check/check_suite_test.go b/cmd/check/check_suite_test.go deleted file mode 100644 index 228f4a9..0000000 --- a/cmd/check/check_suite_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package main_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/onsi/gomega/gexec" -) - -var checkPath string - -func TestCheck(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Check Suite") -} - -var _ = BeforeSuite(func() { - var err error - checkPath, err = gexec.Build("github.com/concourse/github-release-resource/cmd/check") - Ω(err).ShouldNot(HaveOccurred()) -}) - -var _ = AfterSuite(func() { - gexec.CleanupBuildArtifacts() -}) diff --git a/cmd/check/check_test.go b/cmd/check/check_test.go deleted file mode 100644 index 14330ca..0000000 --- a/cmd/check/check_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package main_test - -import ( - "os/exec" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/onsi/gomega/gbytes" - "github.com/onsi/gomega/gexec" -) - -var _ = Describe("Check", func() { - It("outputs an empty JSON array", func() { - command := exec.Command(checkPath) - - check, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) - Ω(err).ShouldNot(HaveOccurred()) - - Eventually(check).Should(gbytes.Say(`\[\]`)) - Eventually(check).Should(gexec.Exit(0)) - }) -}) diff --git a/fakes/fake_git_hub.go b/fakes/fake_git_hub.go index c0dfd0a..67dce0d 100644 --- a/fakes/fake_git_hub.go +++ b/fakes/fake_git_hub.go @@ -10,6 +10,13 @@ import ( ) type FakeGitHub struct { + ListReleasesStub func() ([]github.RepositoryRelease, error) + listReleasesMutex sync.RWMutex + listReleasesArgsForCall []struct{} + listReleasesReturns struct { + result1 []github.RepositoryRelease + result2 error + } CreateReleaseStub func(release *github.RepositoryRelease) (*github.RepositoryRelease, error) createReleaseMutex sync.RWMutex createReleaseArgsForCall []struct { @@ -31,6 +38,31 @@ type FakeGitHub struct { } } +func (fake *FakeGitHub) ListReleases() ([]github.RepositoryRelease, error) { + fake.listReleasesMutex.Lock() + fake.listReleasesArgsForCall = append(fake.listReleasesArgsForCall, struct{}{}) + fake.listReleasesMutex.Unlock() + if fake.ListReleasesStub != nil { + return fake.ListReleasesStub() + } else { + return fake.listReleasesReturns.result1, fake.listReleasesReturns.result2 + } +} + +func (fake *FakeGitHub) ListReleasesCallCount() int { + fake.listReleasesMutex.RLock() + defer fake.listReleasesMutex.RUnlock() + return len(fake.listReleasesArgsForCall) +} + +func (fake *FakeGitHub) ListReleasesReturns(result1 []github.RepositoryRelease, result2 error) { + fake.ListReleasesStub = nil + fake.listReleasesReturns = struct { + result1 []github.RepositoryRelease + result2 error + }{result1, result2} +} + func (fake *FakeGitHub) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) { fake.createReleaseMutex.Lock() fake.createReleaseArgsForCall = append(fake.createReleaseArgsForCall, struct { diff --git a/github.go b/github.go index a6aecfc..d227c2b 100644 --- a/github.go +++ b/github.go @@ -11,6 +11,7 @@ import ( //go:generate counterfeiter . GitHub type GitHub interface { + ListReleases() ([]github.RepositoryRelease, error) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) UploadReleaseAsset(release *github.RepositoryRelease, name string, file *os.File) error } @@ -22,7 +23,7 @@ type GitHubClient struct { repository string } -func NewGitHubClient(source OutSource) *GitHubClient { +func NewGitHubClient(source Source) *GitHubClient { transport := &oauth.Transport{ Token: &oauth.Token{ AccessToken: source.AccessToken, @@ -38,6 +39,15 @@ func NewGitHubClient(source OutSource) *GitHubClient { } } +func (g *GitHubClient) ListReleases() ([]github.RepositoryRelease, error) { + releases, _, err := g.client.Repositories.ListReleases(g.user, g.repository, nil) + if err != nil { + return []github.RepositoryRelease{}, err + } + + return releases, nil +} + func (g *GitHubClient) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) { createdRelease, _, err := g.client.Repositories.CreateRelease(g.user, g.repository, release) if err != nil { diff --git a/resources.go b/resources.go index 9dc3950..f2da72f 100644 --- a/resources.go +++ b/resources.go @@ -1,17 +1,22 @@ package resource -type OutRequest struct { - Source OutSource `json:"source"` - Params OutParams `json:"params"` -} - -type OutSource struct { +type Source struct { AccessToken string `json:"access_token"` User string `json:"user"` Repository string `json:"repository"` } +type CheckRequest struct { + Source Source `json:"source"` + Version Version `json:"version"` +} + +type OutRequest struct { + Source Source `json:"source"` + Params OutParams `json:"params"` +} + type OutParams struct { NamePath string `json:"name"` BodyPath string `json:"body"`