Skip to content

Instantly share code, notes, and snippets.

@mszostok
Last active June 13, 2022 19:18
Show Gist options
  • Save mszostok/b68ff95f85d4b4ff8a27aeed56f9d3ca to your computer and use it in GitHub Desktop.
Save mszostok/b68ff95f85d4b4ff8a27aeed56f9d3ca to your computer and use it in GitHub Desktop.
Example on how to collects start using `cli/go-gh`
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/cli/go-gh"
"github.com/cli/go-gh/pkg/api"
"github.com/cli/go-gh/pkg/repository"
)
type (
OverTime []time.Time
stargazersResponse struct {
Repository struct {
Stargazers struct {
Edges []struct {
StarredAt string
}
PageInfo struct {
HasNextPage bool
EndCursor string
}
TotalCount int
}
}
}
)
func FetchStars(ctx context.Context, client api.GQLClient, repo repository.Repository) (OverTime, error) {
query := `
query Stars(
$owner: String!,
$repo: String!,
$endCursor: String
) {
repository(owner: $owner, name: $repo) {
stargazers(first: 100, after: $endCursor) {
totalCount
pageInfo {
hasNextPage
endCursor
}
edges {
starredAt
}
}
}
}`
variables := map[string]interface{}{
"owner": repo.Owner(),
"repo": repo.Name(),
}
res := OverTime{}
for {
if ctx.Err() != nil { // if cancelled, return. Small workaround to cancel long operation.
return nil, ctx.Err()
}
var data stargazersResponse
fmt.Println("Fetching stars...")
// TODO: support context on client.Do
err := client.Do(query, variables, &data)
if err != nil {
return nil, err
}
stargazers := data.Repository.Stargazers
for _, star := range stargazers.Edges {
t, err := time.Parse(time.RFC3339, star.StarredAt)
if err != nil {
return nil, err
}
res = append(res, t)
}
if !stargazers.PageInfo.HasNextPage {
break
}
variables["endCursor"] = stargazers.PageInfo.EndCursor
}
return res, nil
}
func main() {
repo, err := repository.Parse("kubernetes/kubernetes")
if err != nil {
log.Fatal(err)
}
client, err := gh.GQLClient(nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Fetching stars")
out, err := FetchStars(cancelableContext(), client, repo)
if err != nil {
log.Fatal(err)
}
fmt.Println(len(out))
}
func cancelableContext() context.Context {
ctx, cancel := context.WithCancel(context.Background())
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
select {
case <-ctx.Done():
case <-sigCh:
cancel()
}
}()
return ctx
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment