-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Daniel Hiller <[email protected]>
- Loading branch information
Showing
4 changed files
with
391 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* This file is part of the KubeVirt project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* Copyright the KubeVirt Authors. | ||
* | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"github.com/shurcooL/githubv4" | ||
log "github.com/sirupsen/logrus" | ||
"golang.org/x/oauth2" | ||
"gopkg.in/yaml.v3" | ||
"os" | ||
"strings" | ||
) | ||
|
||
type options struct { | ||
org string | ||
repo string | ||
username string | ||
githubTokenPath string | ||
} | ||
|
||
func gatherOptions() (options, error) { | ||
o := options{} | ||
fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError) | ||
fs.StringVar(&o.org, "org", "kubevirt", "org name") | ||
fs.StringVar(&o.repo, "repo", "", "repo name") | ||
fs.StringVar(&o.username, "username", "", "github handle") | ||
fs.StringVar(&o.githubTokenPath, "github-token", "/etc/github/oauth", "path to github token to use") | ||
err := fs.Parse(os.Args[1:]) | ||
return o, err | ||
} | ||
|
||
func init() { | ||
log.SetFormatter(&log.JSONFormatter{}) | ||
log.SetLevel(log.DebugLevel) | ||
} | ||
|
||
func main() { | ||
opts, err := gatherOptions() | ||
if err != nil { | ||
log.Fatalf("error parsing arguments %v: %v", os.Args[1:], err) | ||
} | ||
|
||
token, err := os.ReadFile(opts.githubTokenPath) | ||
if err != nil { | ||
log.Fatalf("failed to use github token path %s: %v", opts.githubTokenPath, err) | ||
} | ||
src := oauth2.StaticTokenSource( | ||
&oauth2.Token{AccessToken: strings.TrimSpace(string(token))}, | ||
) | ||
httpClient := oauth2.NewClient(context.Background(), src) | ||
graphqlClient := githubv4.NewClient(httpClient) | ||
|
||
activity, err := generateUserActivity(graphqlClient, opts.org, opts.repo, opts.username) | ||
|
||
if err != nil { | ||
log.Fatalf("failed to query: %v", err) | ||
} | ||
|
||
out, err := yaml.Marshal(activity) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println(string(out)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,298 @@ | ||
/* | ||
* This file is part of the KubeVirt project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* Copyright the KubeVirt Authors. | ||
* | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/shurcooL/githubv4" | ||
"time" | ||
) | ||
|
||
type UserActivityResult struct { | ||
IssuesCreated IssuesCreated | ||
IssuesCommented IssuesCommented | ||
PullRequestsCreated PullRequestsCreated | ||
PullRequestsReviewed PullRequestsReviewed | ||
PullRequestsCommented PullRequestsCommented | ||
CommitsByUser CommitsByUser | ||
} | ||
|
||
type Repository struct { | ||
Name string | ||
} | ||
type Author struct { | ||
Login string | ||
} | ||
type IssueFragment struct { | ||
Number int | ||
Title string | ||
Repository Repository | ||
Author Author | ||
CreatedAt time.Time | ||
} | ||
|
||
type IssuesCreatedNodeItem struct { | ||
Issue IssueFragment `graphql:"... on Issue"` | ||
} | ||
|
||
type IssuesCreated struct { | ||
IssueCount int | ||
Nodes []IssuesCreatedNodeItem | ||
} | ||
|
||
type CommentAuthor struct { | ||
Login string | ||
} | ||
type CommentItem struct { | ||
Author CommentAuthor | ||
CreatedAt time.Time | ||
} | ||
|
||
type Comments struct { | ||
Nodes []CommentItem | ||
} | ||
|
||
type IssueWithCommentFragment struct { | ||
Number int | ||
Title string | ||
Repository Repository | ||
Author Author | ||
Comments Comments `graphql:"comments(first:100, orderBy: {field: UPDATED_AT, direction: ASC} )"` | ||
} | ||
|
||
type IssuesCommentedNodeItem struct { | ||
Issue IssueWithCommentFragment `graphql:"... on Issue"` | ||
} | ||
|
||
type IssuesCommented struct { | ||
IssueCount int | ||
Nodes []IssuesCommentedNodeItem | ||
} | ||
|
||
type PullRequestAuthor struct { | ||
Login string | ||
} | ||
|
||
type PullRequestFragment struct { | ||
Number int | ||
Title string | ||
CreatedAt time.Time | ||
Author PullRequestAuthor | ||
} | ||
|
||
type PullRequestNodeItem struct { | ||
PullRequest PullRequestFragment `graphql:"... on PullRequest"` | ||
} | ||
|
||
type PullRequestsCreated struct { | ||
IssueCount int | ||
Nodes []PullRequestNodeItem | ||
} | ||
|
||
type PullRequestReviewItem struct { | ||
State string | ||
} | ||
|
||
type PullRequestReviews struct { | ||
TotalCount int | ||
Nodes []PullRequestReviewItem | ||
} | ||
|
||
type PullRequestReviewFragment struct { | ||
Title string | ||
Number int | ||
CreatedAt time.Time | ||
Reviews PullRequestReviews `graphql:"reviews(first:5, author: $username)"` | ||
} | ||
|
||
type PullRequestReviewNodeItem struct { | ||
PullRequestReview PullRequestReviewFragment `graphql:"... on PullRequest"` | ||
} | ||
|
||
type PullRequestsReviewed struct { | ||
IssueCount int | ||
Nodes []PullRequestReviewNodeItem | ||
} | ||
|
||
type PullRequestCommentAuthor struct { | ||
Login string | ||
} | ||
|
||
type PullRequestComment struct { | ||
Author PullRequestCommentAuthor | ||
CreatedAt time.Time | ||
} | ||
type PullRequestCommentsItem struct { | ||
Nodes []PullRequestComment | ||
} | ||
|
||
type PullRequestCommentedRepository struct { | ||
Name string | ||
} | ||
|
||
type PullRequestCommentedAuthor struct { | ||
Login string | ||
} | ||
|
||
type PullRequestCommentedFragment struct { | ||
Number int | ||
Title string | ||
Repository PullRequestCommentedRepository | ||
Author PullRequestCommentedAuthor | ||
Comments PullRequestCommentsItem `graphql:"comments(first:100, orderBy: {field: UPDATED_AT, direction: ASC} )"` | ||
} | ||
|
||
type PullRequestCommentedItem struct { | ||
PullRequest PullRequestCommentedFragment `graphql:"... on PullRequest"` | ||
} | ||
|
||
type PullRequestsCommented struct { | ||
IssueCount int | ||
Nodes []PullRequestCommentedItem | ||
} | ||
|
||
/* | ||
defaultBranchRef { | ||
target { | ||
... on Commit { | ||
history(author: {emails: "[email protected]"}, since: "2023-11-27T00:00:00Z") { | ||
totalCount | ||
nodes { | ||
commitUrl | ||
associatedPullRequests(first: 5) { | ||
nodes { | ||
number | ||
title | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
*/ | ||
|
||
type AssociatedPullRequest struct { | ||
Number int | ||
Title string | ||
URL string | ||
} | ||
|
||
type AssociatedPullRequests struct { | ||
Nodes []AssociatedPullRequest | ||
} | ||
|
||
type CommitsByUserTargetHistoryNode struct { | ||
CommitUrl string | ||
AssociatedPullRequests `graphql:"associatedPullRequests(first: 5)"` | ||
} | ||
|
||
type CommitsByUserTargetHistory struct { | ||
TotalCount int | ||
Nodes []CommitsByUserTargetHistoryNode | ||
} | ||
|
||
type CommitsByUserTargetFragment struct { | ||
History CommitsByUserTargetHistory `graphql:"history(author: {emails: [$userEMail]}, since: $startFrom)"` | ||
} | ||
|
||
type CommitsByUserTargetItem struct { | ||
Fragment CommitsByUserTargetFragment `graphql:"... on Commit"` | ||
} | ||
|
||
type CommitsByUserRef struct { | ||
Target CommitsByUserTargetItem | ||
} | ||
|
||
type CommitsByUser struct { | ||
DefaultBranchRef CommitsByUserRef | ||
} | ||
|
||
func generateUserActivity(client *githubv4.Client, org, repo, username string) (*UserActivityResult, error) { | ||
|
||
var query struct { | ||
IssuesCreated IssuesCreated `graphql:"issuesCreated: search(first: 5, type: ISSUE, query: $authorSearchQuery)"` | ||
IssuesCommented IssuesCommented `graphql:"issuesCommented: search(first: 5, type: ISSUE, query: $commenterSearchQuery)"` | ||
PullRequestsCreated PullRequestsCreated `graphql:"prsCreated: search(type: ISSUE, first: 5, query: $pullRequestsCreatedQuery)"` | ||
PullRequestsReviewed PullRequestsReviewed `graphql:"prsReviewed: search(type: ISSUE, first: 5, query: $pullRequestsReviewedQuery)"` | ||
PullRequestsCommented PullRequestsCommented `graphql:"prsCommented: search(last: 100, type: ISSUE, query: $pullRequestsCommentedQuery)"` | ||
CommitsByUser CommitsByUser `graphql:"commitsByUser: repository(owner: $org, name: $repo)"` | ||
} | ||
|
||
oneYearAgo := time.Now().AddDate(-1, 0, 0) | ||
fromDate := oneYearAgo.Format("2006-01-02") | ||
|
||
variables := map[string]interface{}{ | ||
"org": githubv4.String(org), | ||
"repo": githubv4.String(repo), | ||
"username": githubv4.String(username), | ||
"userEMail": githubv4.String("[email protected]"), | ||
"startFrom": githubv4.GitTimestamp{Time: oneYearAgo}, | ||
"authorSearchQuery": githubv4.String(fmt.Sprintf( | ||
"repo:%s/%s author:%s is:issue created:>=%s", | ||
org, | ||
repo, | ||
username, | ||
fromDate, | ||
)), | ||
"commenterSearchQuery": githubv4.String(fmt.Sprintf( | ||
"repo:%s/%s commenter:%s is:issue created:>=%s", | ||
org, | ||
repo, | ||
username, | ||
fromDate, | ||
)), | ||
"pullRequestsCreatedQuery": githubv4.String(fmt.Sprintf( | ||
"repo:%s/%s author:%s is:pr created:>=%s", | ||
org, | ||
repo, | ||
username, | ||
fromDate, | ||
)), | ||
"pullRequestsReviewedQuery": githubv4.String(fmt.Sprintf( | ||
"repo:%s/%s reviewed-by:%s is:pr updated:>=%s", | ||
org, | ||
repo, | ||
username, | ||
fromDate, | ||
)), | ||
"pullRequestsCommentedQuery": githubv4.String(fmt.Sprintf( | ||
"repo:%s/%s commenter:%s is:pr updated:>=%s", | ||
org, | ||
repo, | ||
username, | ||
fromDate, | ||
)), | ||
} | ||
|
||
err := client.Query(context.Background(), &query, variables) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to use github query %+v with variables %v: %w", query, variables, err) | ||
} | ||
return &UserActivityResult{ | ||
IssuesCreated: query.IssuesCreated, | ||
IssuesCommented: query.IssuesCommented, | ||
PullRequestsCreated: query.PullRequestsCreated, | ||
PullRequestsReviewed: query.PullRequestsReviewed, | ||
PullRequestsCommented: query.PullRequestsCommented, | ||
CommitsByUser: query.CommitsByUser, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.