Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for assignees #154

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ echo "gruntwork-io/terragrunt gruntwork-io/terratest" | git-xargs \
| `--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 |
| `--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 |
| `--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 |
| `--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 |
| `--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 |
## Best practices, tips and tricks

Expand Down
7 changes: 7 additions & 0 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ type githubPullRequestService interface {
RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers github.ReviewersRequest) (*github.PullRequest, *github.Response, error)
}

// The go-github package satisfies this Issues service's interface in production
type githubIssuesService interface {
AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*github.Issue, *github.Response, error)
}

// The go-github package satisfies this Repositories service's interface in production
type githubRepositoriesService interface {
Get(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error)
Expand All @@ -31,12 +36,14 @@ type githubRepositoriesService interface {
// without actually making API calls to GitHub when running tests
type GithubClient struct {
PullRequests githubPullRequestService
Issues githubIssuesService
Repositories githubRepositoriesService
}

func NewClient(client *github.Client) GithubClient {
return GithubClient{
PullRequests: client.PullRequests,
Issues: client.Issues,
Repositories: client.Repositories,
}
}
Expand Down
1 change: 1 addition & 0 deletions cmd/git-xargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func parseGitXargsConfig(c *cli.Context) (*config.GitXargsConfig, error) {
config.PullRequestDescription = c.String("pull-request-description")
config.Reviewers = c.StringSlice("reviewers")
config.TeamReviewers = c.StringSlice("team-reviewers")
config.Assignees = c.StringSlice("assignees")
config.ReposFile = c.String("repos")
config.GithubOrg = c.String("github-org")
config.RepoSlice = c.StringSlice("repo")
Expand Down
5 changes: 5 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
PullRequestDescriptionFlagName = "pull-request-description"
PullRequestReviewersFlagName = "reviewers"
PullRequestTeamReviewersFlagName = "team-reviewers"
PullRequestAssigneesFlagName = "assignees"
SecondsToWaitBetweenPrsFlagName = "seconds-between-prs"
DefaultCommitMessage = "git-xargs programmatic commit"
DefaultPullRequestTitle = "git-xargs programmatic pull request"
Expand Down Expand Up @@ -91,6 +92,10 @@ var (
Name: PullRequestTeamReviewersFlagName,
Usage: "A list of GitHub team names to request reviews from",
}
GenericPullRequestAssigneesFlag = cli.StringSliceFlag{
Name: PullRequestAssigneesFlagName,
Usage: "A list of GitHub usernames to request as the assignees",
}
GenericSecondsToWaitFlag = cli.IntFlag{
Name: SecondsToWaitBetweenPrsFlagName,
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.",
Expand Down
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type GitXargsConfig struct {
PullRequestDescription string
Reviewers []string
TeamReviewers []string
Assignees []string
ReposFile string
GithubOrg string
RepoSlice []string
Expand Down Expand Up @@ -58,6 +59,7 @@ func NewGitXargsConfig() *GitXargsConfig {
PullRequestDescription: common.DefaultPullRequestDescription,
Reviewers: []string{},
TeamReviewers: []string{},
Assignees: []string{},
ReposFile: "",
GithubOrg: "",
RepoSlice: []string{},
Expand Down Expand Up @@ -91,3 +93,7 @@ func NewGitXargsTestConfig() *GitXargsConfig {
func (c *GitXargsConfig) HasReviewers() bool {
return len(c.Reviewers) > 0 || len(c.TeamReviewers) > 0
}

func (c *GitXargsConfig) HasAssignees() bool {
return len(c.Assignees) > 0
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func setupApp() *cli.App {
common.GenericPullRequestDescriptionFlag,
common.GenericPullRequestReviewersFlag,
common.GenericPullRequestTeamReviewersFlag,
common.GenericPullRequestAssigneesFlag,
common.GenericSecondsToWaitFlag,
common.GenericMaxPullRequestRetriesFlag,
common.GenericSecondsToWaitWhenRateLimitedFlag,
Expand Down
14 changes: 14 additions & 0 deletions mocks/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ func (m mockGithubPullRequestService) RequestReviewers(ctx context.Context, owne
return m.PullRequest, m.Response, nil
}

// This mocks the Issue service in go-github that is used in production to call the associated GitHub endpoint
type mockgithubIssuesService struct {
Issue *github.Issue
Response *github.Response
}

func (m mockgithubIssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*github.Issue, *github.Response, error) {
return m.Issue, m.Response, nil
}

// This mocks the Repositories service in go-github that is used in production to call the associated GitHub endpoint
type mockGithubRepositoriesService struct {
Repository *github.Repository
Expand Down Expand Up @@ -126,6 +136,10 @@ func ConfigureMockGithubClient() auth.GithubClient {
},
Response: &github.Response{},
}
client.Issues = mockgithubIssuesService{
Issue: &github.Issue{},
Response: &github.Response{},
}

return client
}
Expand Down
8 changes: 8 additions & 0 deletions repository/repo-operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,14 @@ func openPullRequest(config *config.GitXargsConfig, pr types.OpenPrRequest) erro

}

if config.HasAssignees() {
assignees := config.Assignees
_, _, assigneeErr := config.GithubClient.Issues.AddAssignees(context.Background(), *pr.Repo.GetOwner().Login, pr.Repo.GetName(), githubPR.GetNumber(), assignees)
if assigneeErr != nil {
config.Stats.TrackSingle(stats.AddAssigneesErr, pr.Repo)
}
}

if config.Draft {
config.Stats.TrackDraftPullRequest(pr.Repo.GetName(), githubPR.GetHTMLURL())
} else {
Expand Down
3 changes: 3 additions & 0 deletions stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ const (
PRFailedAfterMaximumRetriesErr types.Event = "pr-failed-after-maximum-retries"
// RequestReviewersErr denotes a repo whose follow up request to add reviewers to the opened pull request failed
RequestReviewersErr types.Event = "request-reviewers-error"
// AddAssigneesErr denotes a repo whose follow up request to add assignees to the opened pull request failed
AddAssigneesErr types.Event = "add-assignees-error"
)

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

// 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
Expand Down