Skip to content

Commit 3381038

Browse files
tdharrisTyler Harris
authored and
Tyler Harris
committed
feat: add support for assignees
1 parent 076d550 commit 3381038

File tree

9 files changed

+46
-0
lines changed

9 files changed

+46
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ echo "gruntwork-io/terragrunt gruntwork-io/terratest" | git-xargs \
448448
| `--no-skip-ci` | By default, git-xargs will prepend \"[skip ci]\" to its commit messages to prevent large git-xargs jobs from creating expensive CI jobs excessively. If you pass the `--no-skip-ci` flag, then git-xargs will not prepend \"[skip ci]\". Default: false, meaning that \"[skip ci]\" will be prepended to commit messages. | Bool | No |
449449
| `--reviewers` | An optional slice of GitHub usernames, separated by commas, to request reviews from after a pull request is successfully opened. Default: empty slice, meaning that no reviewers will be requested. | String | No |
450450
| `--team-reviewers` | An optional slice of GitHub team names, separated by commas, to request reviews from after a pull request is successfully opened. Default: empty slice, meaning that no team reviewers will be requested. IMPORTANT: Please read and understand [the GitHub restrictions](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) on this functionality before using it! Only certain GitHub organizations / payment plans support this functionality. | String | No |
451+
| `--assignees` | An optional slice of GitHub usernames, separated by commas, to assign to the pull request after it is successfully opened. Default: empty slice, meaning that no assignees will be assigned. | String | No |
451452
| `--keep-cloned-repositories` | By default, git-xargs will delete the repositories it clones to your temporary file directory once it has completed processing that repo, to save space on your machine. If you wish to retain the local repositories, pass this flag. | Bool | No |
452453

453454
## Best practices, tips and tricks

auth/auth.go

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ type githubPullRequestService interface {
1818
RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers github.ReviewersRequest) (*github.PullRequest, *github.Response, error)
1919
}
2020

21+
// The go-github package satisfies this Issues service's interface in production
22+
type githubIssuesService interface {
23+
AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*github.Issue, *github.Response, error)
24+
}
25+
2126
// The go-github package satisfies this Repositories service's interface in production
2227
type githubRepositoriesService interface {
2328
Get(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error)
@@ -31,12 +36,14 @@ type githubRepositoriesService interface {
3136
// without actually making API calls to GitHub when running tests
3237
type GithubClient struct {
3338
PullRequests githubPullRequestService
39+
Issues githubIssuesService
3440
Repositories githubRepositoriesService
3541
}
3642

3743
func NewClient(client *github.Client) GithubClient {
3844
return GithubClient{
3945
PullRequests: client.PullRequests,
46+
Issues: client.Issues,
4047
Repositories: client.Repositories,
4148
}
4249
}

cmd/git-xargs.go

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func parseGitXargsConfig(c *cli.Context) (*config.GitXargsConfig, error) {
3434
config.PullRequestDescription = c.String("pull-request-description")
3535
config.Reviewers = c.StringSlice("reviewers")
3636
config.TeamReviewers = c.StringSlice("team-reviewers")
37+
config.Assignees = c.StringSlice("assignees")
3738
config.ReposFile = c.String("repos")
3839
config.GithubOrg = c.String("github-org")
3940
config.RepoSlice = c.StringSlice("repo")

common/common.go

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const (
1717
PullRequestDescriptionFlagName = "pull-request-description"
1818
PullRequestReviewersFlagName = "reviewers"
1919
PullRequestTeamReviewersFlagName = "team-reviewers"
20+
PullRequestAssigneesFlagName = "assignees"
2021
SecondsToWaitBetweenPrsFlagName = "seconds-between-prs"
2122
DefaultCommitMessage = "git-xargs programmatic commit"
2223
DefaultPullRequestTitle = "git-xargs programmatic pull request"
@@ -92,6 +93,10 @@ var (
9293
Name: PullRequestTeamReviewersFlagName,
9394
Usage: "A list of GitHub team names to request reviews from",
9495
}
96+
GenericPullRequestAssigneesFlag = cli.StringSliceFlag{
97+
Name: PullRequestAssigneesFlagName,
98+
Usage: "A list of GitHub usernames to request as the assignees",
99+
}
95100
GenericSecondsToWaitFlag = cli.IntFlag{
96101
Name: SecondsToWaitBetweenPrsFlagName,
97102
Usage: "The number of seconds to sleep between pull requests in order to respect GitHub API rate limits. Increase this number if you are being rate limited regularly. Defaults to 12 seconds.",

config/config.go

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type GitXargsConfig struct {
2626
PullRequestDescription string
2727
Reviewers []string
2828
TeamReviewers []string
29+
Assignees []string
2930
ReposFile string
3031
GithubOrg string
3132
RepoSlice []string
@@ -59,6 +60,7 @@ func NewGitXargsConfig() *GitXargsConfig {
5960
PullRequestDescription: common.DefaultPullRequestDescription,
6061
Reviewers: []string{},
6162
TeamReviewers: []string{},
63+
Assignees: []string{},
6264
ReposFile: "",
6365
GithubOrg: "",
6466
RepoSlice: []string{},
@@ -93,3 +95,7 @@ func NewGitXargsTestConfig() *GitXargsConfig {
9395
func (c *GitXargsConfig) HasReviewers() bool {
9496
return len(c.Reviewers) > 0 || len(c.TeamReviewers) > 0
9597
}
98+
99+
func (c *GitXargsConfig) HasAssignees() bool {
100+
return len(c.Assignees) > 0
101+
}

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func setupApp() *cli.App {
7373
common.GenericPullRequestDescriptionFlag,
7474
common.GenericPullRequestReviewersFlag,
7575
common.GenericPullRequestTeamReviewersFlag,
76+
common.GenericPullRequestAssigneesFlag,
7677
common.GenericSecondsToWaitFlag,
7778
common.GenericMaxPullRequestRetriesFlag,
7879
common.GenericSecondsToWaitWhenRateLimitedFlag,

mocks/mocks.go

+14
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ func (m mockGithubPullRequestService) RequestReviewers(ctx context.Context, owne
8787
return m.PullRequest, m.Response, nil
8888
}
8989

90+
// This mocks the Issue service in go-github that is used in production to call the associated GitHub endpoint
91+
type mockgithubIssuesService struct {
92+
Issue *github.Issue
93+
Response *github.Response
94+
}
95+
96+
func (m mockgithubIssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*github.Issue, *github.Response, error) {
97+
return m.Issue, m.Response, nil
98+
}
99+
90100
// This mocks the Repositories service in go-github that is used in production to call the associated GitHub endpoint
91101
type mockGithubRepositoriesService struct {
92102
Repository *github.Repository
@@ -136,6 +146,10 @@ func ConfigureMockGithubClient() auth.GithubClient {
136146
},
137147
Response: &github.Response{},
138148
}
149+
client.Issues = mockgithubIssuesService{
150+
Issue: &github.Issue{},
151+
Response: &github.Response{},
152+
}
139153

140154
return client
141155
}

repository/repo-operations.go

+8
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,14 @@ func openPullRequest(config *config.GitXargsConfig, pr types.OpenPrRequest) erro
597597

598598
}
599599

600+
if config.HasAssignees() {
601+
assignees := config.Assignees
602+
_, _, assigneeErr := config.GithubClient.Issues.AddAssignees(context.Background(), *pr.Repo.GetOwner().Login, pr.Repo.GetName(), githubPR.GetNumber(), assignees)
603+
if assigneeErr != nil {
604+
config.Stats.TrackSingle(stats.AddAssigneesErr, pr.Repo)
605+
}
606+
}
607+
600608
if config.Draft {
601609
config.Stats.TrackDraftPullRequest(pr.Repo.GetName(), githubPR.GetHTMLURL())
602610
} else {

stats/stats.go

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ const (
7878
PRFailedAfterMaximumRetriesErr types.Event = "pr-failed-after-maximum-retries"
7979
// RequestReviewersErr denotes a repo whose follow up request to add reviewers to the opened pull request failed
8080
RequestReviewersErr types.Event = "request-reviewers-error"
81+
// AddAssigneesErr denotes a repo whose follow up request to add assignees to the opened pull request failed
82+
AddAssigneesErr types.Event = "add-assignees-error"
8183
)
8284

8385
var allEvents = []types.AnnotatedEvent{
@@ -112,6 +114,7 @@ var allEvents = []types.AnnotatedEvent{
112114
{Event: PRFailedDueToRateLimitsErr, Description: "Repos whose initial Pull Request failed to be created due to GitHub rate limits"},
113115
{Event: PRFailedAfterMaximumRetriesErr, Description: "Repos whose Pull Request failed to be created after the maximum number of retries"},
114116
{Event: RequestReviewersErr, Description: "Repos whose request to add reviewers to the opened pull request failed"},
117+
{Event: AddAssigneesErr, Description: "Repos whose request to add assignees to the opened pull request failed"},
115118
}
116119

117120
// RunStats will be a stats-tracker class that keeps score of which repos were touched, which were considered for update, which had branches made, PRs made, which were missing workflows or contexts, or had out of date workflows syntax values, etc

0 commit comments

Comments
 (0)