access token is now optional

* fix some err checks
* github api url can be configured (e.g. point it at an enterprise instance)

[finishes #89638752 #89633744]

Signed-off-by: Chris Brown <cbrown@pivotal.io>
This commit is contained in:
Alex Suraci
2015-03-04 12:25:26 -08:00
committed by Chris Brown
parent 9e289b62c6
commit 4dbe94c715
9 changed files with 174 additions and 17 deletions

View File

@@ -4,14 +4,17 @@ Fetches and creates versioned GitHub resources.
## Source Configuration ## Source Configuration
* `access_token`: *Required.* The GitHub access token that should be used to
access the API.
* `user`: *Required.* The GitHub username or organization name for the * `user`: *Required.* The GitHub username or organization name for the
repository that the releases are in. repository that the releases are in.
* `repository`: *Required.* The repository name that contains the releases. * `repository`: *Required.* The repository name that contains the releases.
* `access_token`: *Optional.* The GitHub access token that should be used to
access the API. Only required for publishing releases.
* `github_api_url`: *Optional.* If you use a non-public GitHub deployment then
you can set your API URL here.
## Behavior ## Behavior
### `check`: Check for released versions. ### `check`: Check for released versions.

View File

@@ -11,7 +11,11 @@ func main() {
var request resource.CheckRequest var request resource.CheckRequest
inputRequest(&request) inputRequest(&request)
github := resource.NewGitHubClient(request.Source) github, err := resource.NewGitHubClient(request.Source)
if err != nil {
resource.Fatal("constructing github client", err)
}
command := resource.NewCheckCommand(github) command := resource.NewCheckCommand(github)
response, err := command.Run(request) response, err := command.Run(request)
if err != nil { if err != nil {

View File

@@ -18,7 +18,11 @@ func main() {
destDir := os.Args[1] destDir := os.Args[1]
github := resource.NewGitHubClient(request.Source) github, err := resource.NewGitHubClient(request.Source)
if err != nil {
resource.Fatal("constructing github client", err)
}
command := resource.NewInCommand(github, os.Stderr) command := resource.NewInCommand(github, os.Stderr)
response, err := command.Run(destDir, request) response, err := command.Run(destDir, request)
if err != nil { if err != nil {

View File

@@ -18,7 +18,11 @@ func main() {
sourceDir := os.Args[1] sourceDir := os.Args[1]
github := resource.NewGitHubClient(request.Source) github, err := resource.NewGitHubClient(request.Source)
if err != nil {
resource.Fatal("constructing github client", err)
}
command := resource.NewOutCommand(github, os.Stderr) command := resource.NewOutCommand(github, os.Stderr)
response, err := command.Run(sourceDir, request) response, err := command.Run(sourceDir, request)
if err != nil { if err != nil {

View File

@@ -2,6 +2,7 @@ package resource
import ( import (
"errors" "errors"
"net/url"
"os" "os"
"code.google.com/p/goauth2/oauth" "code.google.com/p/goauth2/oauth"
@@ -28,20 +29,34 @@ type GitHubClient struct {
repository string repository string
} }
func NewGitHubClient(source Source) *GitHubClient { func NewGitHubClient(source Source) (*GitHubClient, error) {
transport := &oauth.Transport{ transport := &oauth.Transport{
Token: &oauth.Token{ Token: &oauth.Token{
AccessToken: source.AccessToken, AccessToken: source.AccessToken,
}, },
} }
client := github.NewClient(transport.Client()) var client *github.Client
if transport.Token.AccessToken == "" {
client = github.NewClient(nil)
} else {
client = github.NewClient(transport.Client())
}
if source.GitHubAPIURL != "" {
var err error
client.BaseURL, err = url.Parse(source.GitHubAPIURL)
if err != nil {
return nil, err
}
}
return &GitHubClient{ return &GitHubClient{
client: client, client: client,
user: source.User, user: source.User,
repository: source.Repository, repository: source.Repository,
} }, nil
} }
func (g *GitHubClient) ListReleases() ([]github.RepositoryRelease, error) { func (g *GitHubClient) ListReleases() ([]github.RepositoryRelease, error) {

79
github_test.go Normal file
View File

@@ -0,0 +1,79 @@
package resource_test
import (
"net/http"
. "github.com/concourse/github-release-resource"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/ghttp"
)
var _ = Describe("GitHub Client", func() {
var server *ghttp.Server
var client *GitHubClient
var source Source
BeforeEach(func() {
server = ghttp.NewServer()
})
JustBeforeEach(func() {
source.GitHubAPIURL = server.URL()
var err error
client, err = NewGitHubClient(source)
Ω(err).ShouldNot(HaveOccurred())
})
AfterEach(func() {
server.Close()
})
Context("with an OAuth Token", func() {
BeforeEach(func() {
source = Source{
User: "concourse",
Repository: "concourse",
AccessToken: "abc123",
}
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/repos/concourse/concourse/releases"),
ghttp.RespondWith(200, "[]"),
ghttp.VerifyHeaderKV("Authorization", "Bearer abc123"),
),
)
})
It("sends one", func() {
_, err := client.ListReleases()
Ω(err).ShouldNot(HaveOccurred())
})
})
Context("without an OAuth Token", func() {
BeforeEach(func() {
source = Source{
User: "concourse",
Repository: "concourse",
}
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/repos/concourse/concourse/releases"),
ghttp.RespondWith(200, "[]"),
ghttp.VerifyHeader(http.Header{"Authorization": nil}),
),
)
})
It("sends one", func() {
_, err := client.ListReleases()
Ω(err).ShouldNot(HaveOccurred())
})
})
})

View File

@@ -25,9 +25,14 @@ func NewInCommand(github GitHub, writer io.Writer) *InCommand {
} }
func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) {
err := os.MkdirAll(destDir, 0755)
if err != nil {
return InResponse{}, err
}
releases, err := c.github.ListReleases() releases, err := c.github.ListReleases()
if err != nil { if err != nil {
return InResponse{}, nil return InResponse{}, err
} }
sort.Sort(byVersion(releases)) sort.Sort(byVersion(releases))
@@ -55,7 +60,7 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) {
assets, err := c.github.ListReleaseAssets(foundRelease) assets, err := c.github.ListReleaseAssets(foundRelease)
if err != nil { if err != nil {
return InResponse{}, nil return InResponse{}, err
} }
for _, asset := range assets { for _, asset := range assets {
@@ -87,7 +92,7 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) {
err := c.downloadFile(url, path) err := c.downloadFile(url, path)
if err != nil { if err != nil {
return InResponse{}, nil return InResponse{}, err
} }
} }

View File

@@ -1,6 +1,7 @@
package resource_test package resource_test
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@@ -25,6 +26,7 @@ var _ = Describe("In Command", func() {
inResponse resource.InResponse inResponse resource.InResponse
inErr error inErr error
tmpDir string
destDir string destDir string
) )
@@ -34,9 +36,11 @@ var _ = Describe("In Command", func() {
githubClient = &fakes.FakeGitHub{} githubClient = &fakes.FakeGitHub{}
command = resource.NewInCommand(githubClient, ioutil.Discard) command = resource.NewInCommand(githubClient, ioutil.Discard)
destDir, err = ioutil.TempDir("", "github-release") tmpDir, err = ioutil.TempDir("", "github-release")
Ω(err).ShouldNot(HaveOccurred()) Ω(err).ShouldNot(HaveOccurred())
destDir = filepath.Join(tmpDir, "destination")
server = ghttp.NewServer() server = ghttp.NewServer()
server.RouteToHandler("GET", "/example.txt", ghttp.RespondWith(200, "example.txt")) server.RouteToHandler("GET", "/example.txt", ghttp.RespondWith(200, "example.txt"))
server.RouteToHandler("GET", "/example.rtf", ghttp.RespondWith(200, "example.rtf")) server.RouteToHandler("GET", "/example.rtf", ghttp.RespondWith(200, "example.rtf"))
@@ -50,8 +54,11 @@ var _ = Describe("In Command", func() {
}) })
AfterEach(func() { AfterEach(func() {
if server != nil {
server.Close() server.Close()
Ω(os.RemoveAll(destDir)).Should(Succeed()) }
Ω(os.RemoveAll(tmpDir)).Should(Succeed())
}) })
buildRelease := func(id int, tag string) github.RepositoryRelease { buildRelease := func(id int, tag string) github.RepositoryRelease {
@@ -171,6 +178,29 @@ var _ = Describe("In Command", func() {
Ω(err).ShouldNot(HaveOccurred()) Ω(err).ShouldNot(HaveOccurred())
}) })
}) })
Context("when downloading an asset fails", func() {
BeforeEach(func() {
server.Close()
server = nil
})
It("returns an error", func() {
Ω(inErr).Should(HaveOccurred())
})
})
Context("when listing release assets fails", func() {
disaster := errors.New("nope")
BeforeEach(func() {
githubClient.ListReleaseAssetsReturns(nil, disaster)
})
It("returns the error", func() {
Ω(inErr).Should(Equal(disaster))
})
})
}) })
Context("when the specified version is not available", func() { Context("when the specified version is not available", func() {
@@ -228,4 +258,16 @@ var _ = Describe("In Command", func() {
Ω(inErr).Should(HaveOccurred()) Ω(inErr).Should(HaveOccurred())
}) })
}) })
Context("when listing releases fails", func() {
disaster := errors.New("nope")
BeforeEach(func() {
githubClient.ListReleasesReturns(nil, disaster)
})
It("returns the error", func() {
Ω(inErr).Should(Equal(disaster))
})
})
}) })

View File

@@ -1,10 +1,11 @@
package resource package resource
type Source struct { type Source struct {
AccessToken string `json:"access_token"`
User string `json:"user"` User string `json:"user"`
Repository string `json:"repository"` Repository string `json:"repository"`
GitHubAPIURL string `json:"github_api_url"`
AccessToken string `json:"access_token"`
} }
type CheckRequest struct { type CheckRequest struct {