diff --git a/cmd/out/out.go b/cmd/out/out.go new file mode 100644 index 0000000..43fa2f8 --- /dev/null +++ b/cmd/out/out.go @@ -0,0 +1,41 @@ +package main + +import ( + "encoding/json" + "os" + + "github.com/concourse/github-release-resource" +) + +func main() { + if len(os.Args) < 2 { + resource.Sayf("usage: %s \n", os.Args[0]) + os.Exit(1) + } + + var request resource.OutRequest + inputRequest(&request) + + sourceDir := os.Args[1] + + github := resource.NewGitHubClient(request.Source) + command := resource.NewOutCommand(github) + response, err := command.Run(sourceDir, request) + if err != nil { + resource.Fatal("running command", err) + } + + outputResponse(response) +} + +func inputRequest(request *resource.OutRequest) { + if err := json.NewDecoder(os.Stdin).Decode(request); err != nil { + resource.Fatal("reading request from stdin", err) + } +} + +func outputResponse(response resource.OutResponse) { + if err := json.NewEncoder(os.Stdout).Encode(response); err != nil { + resource.Fatal("writing response to stdout", err) + } +} diff --git a/fakes/fake_git_hub.go b/fakes/fake_git_hub.go new file mode 100644 index 0000000..bedb108 --- /dev/null +++ b/fakes/fake_git_hub.go @@ -0,0 +1,89 @@ +// This file was generated by counterfeiter +package fakes + +import ( + "os" + "sync" + + "github.com/concourse/github-release-resource" + "github.com/google/go-github/github" +) + +type FakeGitHub struct { + CreateReleaseStub func(release github.RepositoryRelease) (github.RepositoryRelease, error) + createReleaseMutex sync.RWMutex + createReleaseArgsForCall []struct { + release github.RepositoryRelease + } + createReleaseReturns struct { + result1 github.RepositoryRelease + result2 error + } + UploadReleaseAssetStub func(release github.RepositoryRelease, name string, file *os.File) + uploadReleaseAssetMutex sync.RWMutex + uploadReleaseAssetArgsForCall []struct { + release github.RepositoryRelease + name string + file *os.File + } +} + +func (fake *FakeGitHub) CreateRelease(release github.RepositoryRelease) (github.RepositoryRelease, error) { + fake.createReleaseMutex.Lock() + fake.createReleaseArgsForCall = append(fake.createReleaseArgsForCall, struct { + release github.RepositoryRelease + }{release}) + fake.createReleaseMutex.Unlock() + if fake.CreateReleaseStub != nil { + return fake.CreateReleaseStub(release) + } else { + return fake.createReleaseReturns.result1, fake.createReleaseReturns.result2 + } +} + +func (fake *FakeGitHub) CreateReleaseCallCount() int { + fake.createReleaseMutex.RLock() + defer fake.createReleaseMutex.RUnlock() + return len(fake.createReleaseArgsForCall) +} + +func (fake *FakeGitHub) CreateReleaseArgsForCall(i int) github.RepositoryRelease { + fake.createReleaseMutex.RLock() + defer fake.createReleaseMutex.RUnlock() + return fake.createReleaseArgsForCall[i].release +} + +func (fake *FakeGitHub) CreateReleaseReturns(result1 github.RepositoryRelease, result2 error) { + fake.CreateReleaseStub = nil + fake.createReleaseReturns = struct { + result1 github.RepositoryRelease + result2 error + }{result1, result2} +} + +func (fake *FakeGitHub) UploadReleaseAsset(release github.RepositoryRelease, name string, file *os.File) { + fake.uploadReleaseAssetMutex.Lock() + fake.uploadReleaseAssetArgsForCall = append(fake.uploadReleaseAssetArgsForCall, struct { + release github.RepositoryRelease + name string + file *os.File + }{release, name, file}) + fake.uploadReleaseAssetMutex.Unlock() + if fake.UploadReleaseAssetStub != nil { + fake.UploadReleaseAssetStub(release, name, file) + } +} + +func (fake *FakeGitHub) UploadReleaseAssetCallCount() int { + fake.uploadReleaseAssetMutex.RLock() + defer fake.uploadReleaseAssetMutex.RUnlock() + return len(fake.uploadReleaseAssetArgsForCall) +} + +func (fake *FakeGitHub) UploadReleaseAssetArgsForCall(i int) (github.RepositoryRelease, string, *os.File) { + fake.uploadReleaseAssetMutex.RLock() + defer fake.uploadReleaseAssetMutex.RUnlock() + return fake.uploadReleaseAssetArgsForCall[i].release, fake.uploadReleaseAssetArgsForCall[i].name, fake.uploadReleaseAssetArgsForCall[i].file +} + +var _ resource.GitHub = new(FakeGitHub) diff --git a/fmt.go b/fmt.go new file mode 100644 index 0000000..f68cf20 --- /dev/null +++ b/fmt.go @@ -0,0 +1,17 @@ +package resource + +import ( + "fmt" + "os" + + "github.com/mitchellh/colorstring" +) + +func Fatal(doing string, err error) { + Sayf(colorstring.Color("[red]error %s: %s\n"), doing, err) + os.Exit(1) +} + +func Sayf(message string, args ...interface{}) { + fmt.Fprintf(os.Stderr, message, args...) +} diff --git a/github.go b/github.go new file mode 100644 index 0000000..a6aecfc --- /dev/null +++ b/github.go @@ -0,0 +1,62 @@ +package resource + +import ( + "os" + + "code.google.com/p/goauth2/oauth" + + "github.com/google/go-github/github" +) + +//go:generate counterfeiter . GitHub + +type GitHub interface { + CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) + UploadReleaseAsset(release *github.RepositoryRelease, name string, file *os.File) error +} + +type GitHubClient struct { + client *github.Client + + user string + repository string +} + +func NewGitHubClient(source OutSource) *GitHubClient { + transport := &oauth.Transport{ + Token: &oauth.Token{ + AccessToken: source.AccessToken, + }, + } + + client := github.NewClient(transport.Client()) + + return &GitHubClient{ + client: client, + user: source.User, + repository: source.Repository, + } +} + +func (g *GitHubClient) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) { + createdRelease, _, err := g.client.Repositories.CreateRelease(g.user, g.repository, release) + if err != nil { + return &github.RepositoryRelease{}, err + } + + return createdRelease, nil +} + +func (g *GitHubClient) UploadReleaseAsset(release *github.RepositoryRelease, name string, file *os.File) error { + _, _, err := g.client.Repositories.UploadReleaseAsset( + g.user, + g.repository, + *release.ID, + &github.UploadOptions{ + Name: name, + }, + file, + ) + + return err +} diff --git a/out_command.go b/out_command.go new file mode 100644 index 0000000..a53b4eb --- /dev/null +++ b/out_command.go @@ -0,0 +1,45 @@ +package resource + +import ( + "os" + "path/filepath" + + "github.com/google/go-github/github" +) + +type OutCommand struct { + github GitHub +} + +func NewOutCommand(github GitHub) *OutCommand { + return &OutCommand{ + github: github, + } +} + +func (c *OutCommand) Run(sourceDir string, request OutRequest) (OutResponse, error) { + params := request.Params + + release := &github.RepositoryRelease{} + createdRelease, err := c.github.CreateRelease(release) + if err != nil { + return OutResponse{}, err + } + + for _, filePath := range params.Globs { + file, err := os.Open(filePath) + if err != nil { + return OutResponse{}, err + } + + name := filepath.Base(filePath) + err = c.github.UploadReleaseAsset(createdRelease, name, file) + if err != nil { + return OutResponse{}, err + } + + file.Close() + } + + return OutResponse{}, nil +} diff --git a/resources.go b/resources.go new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/resources.go @@ -0,0 +1,35 @@ +package resource + +type OutRequest struct { + Source OutSource `json:"source"` + Params OutParams `json:"params"` +} + +type OutSource struct { + AccessToken string `json:"access_token"` + + User string `json:"user"` + Repository string `json:"repository"` +} + +type OutParams struct { + NamePath string `json:"name"` + BodyPath string `json:"body"` + TagPath string `json:"tag"` + + Globs []string `json:"globs"` +} + +type OutResponse struct { + Version Version `json:"version"` + Metadata []MetadataPair `json:"metadata"` +} + +type Version struct { + Tag string `json:"tag"` +} + +type MetadataPair struct { + Name string `json:"name"` + Value string `json:"value"` +}