Skip to content

Commit

Permalink
Merge pull request #29 from philips-labs/feature/gh-repo-contents
Browse files Browse the repository at this point in the history
Feature/gh repo contents
  • Loading branch information
marcofranssen authored Jul 23, 2020
2 parents d812cd6 + fa11b24 commit 4e685af
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jobs:
- name: Test and Cover
run: go test -v -race -count=1 -covermode=atomic -coverprofile=coverage.out ./...
env:
TABIA_GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Upload Code Coverage
uses: codecov/codecov-action@v1.0.10
Expand Down
65 changes: 65 additions & 0 deletions cmd/cmd_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"text/tabwriter"

"github.com/urfave/cli/v2"
Expand Down Expand Up @@ -64,6 +66,32 @@ func createGithub() *cli.Command {
},
},
},
{
Name: "contents",
Usage: "Gets contents from a repository",
Action: githubContents,
ArgsUsage: " ",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Aliases: []string{"R"},
Usage: "fetches content of given `REPO`",
Required: true,
},
&cli.StringFlag{
Name: "file",
Aliases: []string{"f"},
Usage: "fetches content of given `FILE`",
Required: true,
},
&cli.StringFlag{
Name: "output",
Aliases: []string{"o"},
Usage: "writes contents to `FILEPATH`",
Required: false,
},
},
},
},
}
}
Expand Down Expand Up @@ -143,3 +171,40 @@ func githubRepositories(c *cli.Context) error {

return nil
}

func githubContents(c *cli.Context) error {
repo := c.String("repo")
filePath := c.String("file")
output := c.Path("output")

client := github.NewClientWithTokenAuth(os.Getenv("TABIA_GITHUB_TOKEN"))
ctx, cancel := context.WithCancel(c.Context)
defer cancel()

repoParts := strings.Split(repo, "/")
owner := repoParts[0]
repo = repoParts[1]

contents, err := client.DownloadContents(ctx, owner, repo, filePath)
if err != nil {
return err
}

if output != "" {
if strings.Contains(output, "/") {
dir := filepath.Dir(output)
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}
}
err := ioutil.WriteFile(output, contents, 0644)
if err != nil {
return err
}
} else {
fmt.Fprintf(c.App.Writer, "%s", contents)
}

return nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/antonmedv/expr v1.8.8
github.com/google/go-github/v32 v32.1.0
github.com/goreleaser/goreleaser v0.140.1
github.com/shurcooL/githubv4 v0.0.0-20200414012201-bbc966b061dd
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
Expand Down
34 changes: 8 additions & 26 deletions go.sum

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions lib/github/contents.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package github

import (
"context"
"io/ioutil"
)

// DownloadContents downloads file contents from the given filepath
func (c *Client) DownloadContents(ctx context.Context, owner, repo, filepath string) ([]byte, error) {
contents, err := c.restClient.Repositories.DownloadContents(ctx, owner, repo, filepath, nil)
if err != nil {
return nil, err
}

defer contents.Close()
return ioutil.ReadAll(contents)
}
28 changes: 28 additions & 0 deletions lib/github/contents_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package github_test

import (
"context"
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/assert"

"github.com/philips-labs/tabia/lib/github"
)

func TestDownloadContents(t *testing.T) {
assert := assert.New(t)
gh := github.NewClientWithTokenAuth(os.Getenv("TABIA_GITHUB_TOKEN"))
contents, err := gh.DownloadContents(context.Background(), "philips-labs", "tabia", "README.md")
if assert.NoError(err) {
readme, _ := ioutil.ReadFile("../../README.md")
assert.NotEmpty(contents)
assert.Equal(string(readme), string(contents))
}

contents, err = gh.DownloadContents(context.Background(), "philips-labs", "tabia", "IamNotThere.txt")
if assert.Error(err) {
assert.EqualError(err, "No file named IamNotThere.txt found in .")
}
}
25 changes: 10 additions & 15 deletions lib/github/github.go → lib/github/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ package github

import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"

"golang.org/x/oauth2"

"github.com/google/go-github/v32/github"
"github.com/shurcooL/githubv4"

"github.com/philips-labs/tabia/lib/github/graphql"
)

type Client struct {
httpClient *http.Client
restClient *github.Client
*githubv4.Client
}

Expand All @@ -25,8 +26,9 @@ func NewClientWithTokenAuth(token string) *Client {
httpClient := oauth2.NewClient(context.Background(), src)

client := githubv4.NewClient(httpClient)
restClient := github.NewClient(httpClient)

return &Client{httpClient, client}
return &Client{httpClient, restClient, client}
}

//go:generate stringer -type=Visibility
Expand Down Expand Up @@ -109,30 +111,23 @@ func (c *Client) FetchOrganziationRepositories(ctx context.Context, owner string

// currently the graphql api does not seem to support private vs internal.
// therefore we use the rest api to fetch the private repos so we can determine private vs internal in the Map function.
privateRepos, err := c.FetchRestRepositories(owner, "private")
privateRepos, err := c.FetchRestRepositories(ctx, owner, "private")
if err != nil {
return nil, err
}
return Map(repositories, privateRepos)
}

func (c *Client) FetchRestRepositories(owner, repoType string) ([]RestRepo, error) {
resp, err := c.httpClient.Get(fmt.Sprintf("https://api.github.com/orgs/%s/repos?type=%s", owner, repoType))
func (c *Client) FetchRestRepositories(ctx context.Context, owner, repoType string) ([]*github.Repository, error) {
repos, resp, err := c.restClient.Repositories.ListByOrg(ctx, owner, &github.RepositoryListByOrgOptions{Type: repoType})
if err != nil {
return nil, err
}
defer resp.Body.Close()

var privateRepos []RestRepo
err = json.NewDecoder(resp.Body).Decode(&privateRepos)
if err != nil {
return nil, err
}

return privateRepos, nil
return repos, nil
}

func Map(repositories []graphql.Repository, privateRepositories []RestRepo) ([]Repository, error) {
func Map(repositories []graphql.Repository, privateRepositories []*github.Repository) ([]Repository, error) {
repos := make([]Repository, len(repositories))
for i, repo := range repositories {
repos[i] = Repository{
Expand All @@ -151,7 +146,7 @@ func Map(repositories []graphql.Repository, privateRepositories []RestRepo) ([]R
if repo.IsPrivate {
isPrivate := false
for _, privRepo := range privateRepositories {
if privRepo.Name == repo.Name {
if *privRepo.Name == repo.Name {
isPrivate = true
break
}
Expand Down
11 changes: 8 additions & 3 deletions lib/github/github_test.go → lib/github/repositories_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"
"testing"

gh "github.com/google/go-github/v32/github"
"github.com/stretchr/testify/assert"

"github.com/philips-labs/tabia/lib/github"
Expand Down Expand Up @@ -71,9 +72,9 @@ func TestMap(t *testing.T) {
graphql.Repository{Owner: owner, Name: "secret-repo", Description: " ** secrets ** ", IsPrivate: true},
}

privateRepos := []github.RestRepo{
github.RestRepo{Name: "private-repo"},
github.RestRepo{Name: "secret-repo"},
privateRepos := []*gh.Repository{
&gh.Repository{Name: stringPointer("private-repo")},
&gh.Repository{Name: stringPointer("secret-repo")},
}
ghRepos, err := github.Map(graphqlRepositories, privateRepos)
if !assert.NoError(err) {
Expand Down Expand Up @@ -103,3 +104,7 @@ func TestMap(t *testing.T) {
assert.Equal("graphql", ghRepos[2].Topics[2].Name)
assert.Equal("https://github.com/topics/graphql", ghRepos[2].Topics[2].URL)
}

func stringPointer(s string) *string {
return &s
}

0 comments on commit 4e685af

Please sign in to comment.