Skip to content

Commit

Permalink
feat: use github api v4
Browse files Browse the repository at this point in the history
  • Loading branch information
maolonglong committed Sep 30, 2021
1 parent 4b60c1a commit 88ba2bf
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 85 deletions.
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ go 1.17

require (
github.com/google/go-github/v39 v39.1.0
github.com/shurcooL/githubv4 v0.0.0-20210922025249-6831e00d857f
github.com/wcharczuk/go-chart v2.0.1+incompatible
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
)

require (
github.com/blend/go-sdk v1.20210918.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/githubv4 v0.0.0-20210922025249-6831e00d857f h1:q4b8/GCL8Ksl+okhFKSd8DVBQNc0XExjxTO68nK0c3Y=
github.com/shurcooL/githubv4 v0.0.0-20210922025249-6831e00d857f/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a h1:KikTa6HtAK8cS1qjvUvvq4QO21QnwC+EfvB+OAuZ/ZU=
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
Expand Down Expand Up @@ -425,8 +429,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk=
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -443,7 +447,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
6 changes: 3 additions & 3 deletions internal/chart/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import (
"io"
"time"

"github.com/google/go-github/v39/github"
"github.com/maolonglong/actions-starcharts/internal/client"
"github.com/wcharczuk/go-chart"
"github.com/wcharczuk/go-chart/drawing"
)

func WriteStarsChart(stars []*github.Stargazer, w io.Writer) error {
func WriteStarsChart(stars []client.Stargazer, w io.Writer) error {
var series = chart.TimeSeries{
Style: chart.Style{
Show: true,
Expand All @@ -24,7 +24,7 @@ func WriteStarsChart(stars []*github.Stargazer, w io.Writer) error {
},
}
for i, star := range stars {
series.XValues = append(series.XValues, star.StarredAt.Time)
series.XValues = append(series.XValues, star.StarredAt)
series.YValues = append(series.YValues, float64(i))
}
if len(series.XValues) < 2 {
Expand Down
45 changes: 18 additions & 27 deletions internal/client/blob.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package client

import (
"bytes"
"encoding/base64"
"fmt"

"github.com/google/go-github/v39/github"
"github.com/shurcooL/githubv4"
)

func (c *Client) CreateOrUpdate(owner, repo, sha, path, message string, content []byte) error {
Expand All @@ -13,41 +13,32 @@ func (c *Client) CreateOrUpdate(owner, repo, sha, path, message string, content
return err
}

if b != nil {
preContent, err := base64.StdEncoding.DecodeString(*b.Content)
if err != nil {
return err
}

if bytes.Equal(preContent, content) {
return nil
}
if b.Text == string(content) {
return nil
}

// TODO: replace with graphql API
opt := &github.RepositoryContentFileOptions{
Message: &message,
Content: content,
}
if b != nil {
opt.SHA = b.SHA
if b.Oid != "" {
opt.SHA = &b.Oid
}
_, _, err = c.g.Repositories.CreateFile(c.ctx, owner, repo, path, opt)
v3 := github.NewClient(c.httpClient)
_, _, err = v3.Repositories.CreateFile(c.ctx, owner, repo, path, opt)
return err
}

func (c *Client) getBlob(owner, repo, sha, path string) (*github.Blob, error) {
tree, _, err := c.g.Git.GetTree(c.ctx, owner, repo, sha, true)
func (c *Client) getBlob(owner, repo, sha, path string) (Blob, error) {
var q getFileSHAQuery
err := c.g.Query(c.ctx, &q, map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(repo),
"expression": githubv4.String(fmt.Sprintf("%s:%s", sha, path)),
})
if err != nil {
return nil, err
}
for _, ent := range tree.Entries {
if *ent.Path == path {
blob, _, err := c.g.Git.GetBlob(c.ctx, owner, repo, ent.GetSHA())
if err != nil {
return nil, err
}
return blob, nil
}
return Blob{}, nil
}
return nil, nil
return q.Repository.Object.Blob, nil
}
20 changes: 13 additions & 7 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@ package client

import (
"context"
"net/http"

"github.com/google/go-github/v39/github"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
)

const defaultPerPage = 100

type Client struct {
g *github.Client
ctx context.Context
g *githubv4.Client

// TODO: remove httpClient and github api v3
httpClient *http.Client
}

func New(ctx context.Context, token string) *Client {
ts := oauth2.StaticTokenSource(
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(ctx, ts)
return &Client{g: github.NewClient(tc), ctx: ctx}
httpClient := oauth2.NewClient(ctx, src)
return &Client{
ctx: ctx,
httpClient: httpClient,
g: githubv4.NewClient(httpClient),
}
}
64 changes: 64 additions & 0 deletions internal/client/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package client

import (
"time"

"github.com/shurcooL/githubv4"
)

type Stargazer struct {
StarredAt time.Time
}

/*
repository(name: $name, owner: $owner) {
stargazers(first: 100, after: $after) {
edges {
starredAt
}
pageInfo {
endCursor
hasNextPage
}
}
}
*/
type getStarsQuery struct {
Repository struct {
Stargazers struct {
Edges []Stargazer
PageInfo struct {
EndCursor githubv4.String
HasNextPage bool
}
} `graphql:"stargazers(first: 100, after: $after)"`
} `graphql:"repository(owner: $owner, name: $name)"`
RateLimit struct {
Remaining int
}
}

type Blob struct {
Oid string
Text string
}

/*
{
repository(owner: $owner, name: $name) {
object(expression: $expression) {
... on Blob {
oid
text
}
}
}
}
*/
type getFileSHAQuery struct {
Repository struct {
Object struct {
Blob `graphql:"... on Blob"`
} `graphql:"object(expression: $expression)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
61 changes: 21 additions & 40 deletions internal/client/star.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,37 @@
package client

import (
"log"
"sort"
"sync"

"github.com/google/go-github/v39/github"
"golang.org/x/sync/errgroup"
"github.com/shurcooL/githubv4"
)

func (c *Client) GetStargazers(owner, repo string) ([]*github.Stargazer, error) {
r, _, err := c.g.Repositories.Get(c.ctx, owner, repo)
if err != nil {
return nil, err
}

stars := make([]*github.Stargazer, 0, r.GetStargazersCount())
var mu sync.Mutex
var g errgroup.Group
sem := make(chan struct{}, 4)
func (c *Client) GetStargazers(owner, name string) ([]Stargazer, error) {
var q getStarsQuery

lastPage := getLastPage(r.GetStargazersCount(), defaultPerPage)
for page := 1; page <= lastPage; page++ {
sem <- struct{}{}
page := page
g.Go(func() error {
defer func() { <-sem }()
opt := &github.ListOptions{
Page: page,
PerPage: defaultPerPage,
}
result, _, err := c.g.Activity.ListStargazers(c.ctx, owner, repo, opt)
if err != nil {
return err
}
mu.Lock()
stars = append(stars, result...)
mu.Unlock()
return nil
})
variables := map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(name),
"after": (*githubv4.String)(nil),
}

err = g.Wait()
if err != nil {
return nil, err
var stars []Stargazer
for {
err := c.g.Query(c.ctx, &q, variables)
if err != nil {
return nil, err
}
stars = append(stars, q.Repository.Stargazers.Edges...)
log.Printf("get stargazers: completed=%v, ratelimit_remaining=%v", len(stars), q.RateLimit.Remaining)
if !q.Repository.Stargazers.PageInfo.HasNextPage {
break
}
variables["after"] = githubv4.NewString(q.Repository.Stargazers.PageInfo.EndCursor)
}

sort.Slice(stars, func(i, j int) bool {
return stars[i].StarredAt.Before(stars[j].StarredAt.Time)
return stars[i].StarredAt.Before(stars[j].StarredAt)
})
return stars, nil
}

func getLastPage(total, perPage int) int {
return (total + perPage - 1) / perPage
}
6 changes: 3 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (
)

func main() {
owner, repo := action.GetRepo()
owner, name := action.GetRepo()
sha := action.GetSHA()
token := action.GetInput("github_token")
svgPath := action.GetInput("svg_path")
commitMessage := action.GetInput("commit_message")

client := client.New(context.Background(), token)
stars, err := client.GetStargazers(owner, repo)
stars, err := client.GetStargazers(owner, name)
if err != nil {
log.Fatal("get stargazers failed: ", err.Error())
}
Expand All @@ -29,7 +29,7 @@ func main() {
log.Fatal("write stargazers chart failed: ", err.Error())
}

err = client.CreateOrUpdate(owner, repo, sha, svgPath, commitMessage, buf.Bytes())
err = client.CreateOrUpdate(owner, name, sha, svgPath, commitMessage, buf.Bytes())
if err != nil {
log.Fatal("update content failed: ", err.Error())
}
Expand Down

0 comments on commit 88ba2bf

Please sign in to comment.