Skip to content

Commit

Permalink
Added GetNewContributorsHistory (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
emanuelef authored Jan 19, 2025
1 parent 0fd979f commit f2fac5d
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 12 deletions.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ require (
github.com/joho/godotenv v1.5.1
github.com/pelletier/go-toml v1.9.5
github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0
go.opentelemetry.io/otel v1.33.0
go.opentelemetry.io/otel/trace v1.33.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0
go.opentelemetry.io/otel v1.34.0
go.opentelemetry.io/otel/trace v1.34.0
golang.org/x/mod v0.22.0
golang.org/x/oauth2 v0.25.0
golang.org/x/sync v0.10.0
Expand All @@ -21,6 +21,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.33.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
golang.org/x/net v0.34.0 // indirect
)
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
Expand Down
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ func main() {
allForks, _ := clientGQL.GetAllForksHistory(ctx, "ceccopierangiolieugenio/pyTermTk", nil)
fmt.Println(time.Time(allForks[len(allForks)-1].Day))

allContributors, _ := clientGQL.GetNewContributorsHistory(ctx, "temporalio/temporal", nil)
fmt.Println(time.Time(allContributors[len(allContributors)-1].Day))

//
result, _ = clientGQL.GetAllStats(ctx, "kubewarden/kubewarden-controller")
fmt.Println(result)
Expand Down
113 changes: 113 additions & 0 deletions repostats/gqlstats.go
Original file line number Diff line number Diff line change
Expand Up @@ -1389,3 +1389,116 @@ func (c *ClientGQL) GetAllCommitsHistory(ctx context.Context, ghRepo string, upd
}
return result, string(defaultBranchName), nil
}

func (c *ClientGQL) GetNewContributorsHistory(ctx context.Context, ghRepo string, updateChannel chan<- int) ([]stats.NewContributorsPerDay, error) {
repoSplit := strings.Split(ghRepo, "/")

if len(repoSplit) != 2 || !strings.Contains(ghRepo, "/") {
return nil, fmt.Errorf("Repo should be provided as owner/name")
}

defer func() {
if updateChannel != nil {
close(updateChannel)
}
}()

owner := repoSplit[0]
name := repoSplit[1]

result := []stats.NewContributorsPerDay{}
counter := &Counter{}

_, repoCreationDate, err := c.GetTotalStars(ctx, ghRepo)
if err != nil {
log.Printf("%v\n", err)
return result, err
}

currentTime := time.Now().UTC().Truncate(24 * time.Hour)
repoCreationDate = repoCreationDate.Truncate(24 * time.Hour)
diff := currentTime.Sub(repoCreationDate)
days := int(diff.Hours()/24 + 1)

for i := 0; i < days; i++ {
result = append(result, stats.NewContributorsPerDay{Day: stats.JSONDay(repoCreationDate.AddDate(0, 0, i).Truncate(24 * time.Hour))})
}

variablesContributors := map[string]any{
"owner": githubv4.String(owner),
"name": githubv4.String(name),
"prsCursor": (*githubv4.String)(nil),
}

type prs struct {
State string
MergedAt time.Time
Author struct {
Login string
}
}

var queryContributors struct {
Repository struct {
PullRequests struct {
Nodes []prs
PageInfo struct {
EndCursor githubv4.String
HasNextPage bool
}
} `graphql:"pullRequests(first: 100, orderBy: {field: CREATED_AT, direction: ASC}, after: $prsCursor)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}

seenContributors := map[string]bool{}

for {
err := c.query(ctx, &queryContributors, variablesContributors)
if err != nil {
fmt.Printf("%v\n", err)
return nil, err
}

res := queryContributors.Repository.PullRequests.Nodes

if len(res) == 0 {
break
}

for _, pr := range res {
if pr.State == "MERGED" {
daysMerged := pr.MergedAt.Sub(repoCreationDate).Hours() / 24
if daysMerged < 0 {
continue
}

if _, exists := seenContributors[pr.Author.Login]; !exists {
seenContributors[pr.Author.Login] = true
result[int(daysMerged)].NewContributors++
}
}
}

if !queryContributors.Repository.PullRequests.PageInfo.HasNextPage {
break
}

variablesContributors["prsCursor"] = githubv4.NewString(queryContributors.Repository.PullRequests.PageInfo.EndCursor)

counter.Increment()

if updateChannel != nil {
updateChannel <- counter.Value()
}
}

for i, day := range result {
if i > 0 {
result[i].TotalNewContributors = result[i-1].TotalNewContributors + day.NewContributors
} else {
result[i].TotalNewContributors = day.NewContributors
}
}

return result, nil
}
11 changes: 11 additions & 0 deletions stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ type PRsPerDay struct {
TotalCurrentlyOpen int
}

// NewContributorsPerDay holds statistics about new contributors for a specific day.
type NewContributorsPerDay struct {
Day JSONDay
NewContributors int
TotalNewContributors int
}

func (t StarsPerDay) MarshalJSON() ([]byte, error) {
return json.Marshal([]any{t.Day, t.Stars, t.TotalStars})
}
Expand All @@ -78,6 +85,10 @@ func (t PRsPerDay) MarshalJSON() ([]byte, error) {
return json.Marshal([]any{t.Day, t.Opened, t.Merged, t.Closed, t.TotalOpened, t.TotalMerged, t.TotalClosed, t.CurrentlyOpen, t.TotalCurrentlyOpen})
}

func (t NewContributorsPerDay) MarshalJSON() ([]byte, error) {
return json.Marshal([]any{t.Day, t.NewContributors, t.TotalNewContributors})
}

type StarsHistory struct {
AddedLast24H int
AddedLast7d int
Expand Down

0 comments on commit f2fac5d

Please sign in to comment.