Skip to content

Commit cac0fb2

Browse files
authored
Repo selection mode enhancements (#54)
- Make the selection mode used by git-xargs explicit in the report - Add more explicit error handling when all --repo or STDIN repos are malformed - These changes should make it easier to grok what git-xargs is doing and why when it comes to --github-org being preferred, or user-supplied inputs being malformed
1 parent 98fd7d2 commit cac0fb2

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

printer/printer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ func PrintRepoReport(allEvents []types.AnnotatedEvent, runReport *types.RunRepor
3939
fmt.Println()
4040
fmt.Println(runReport.Command)
4141
fmt.Println()
42+
fmt.Println("REPO SELECTION METHOD USED FOR THIS RUN - (see README.md for more information)")
43+
fmt.Println()
44+
fmt.Println(runReport.SelectionMode)
4245

4346
// If the user selected repos via a flat file, print a table showing which repos they were
4447
if len(runReport.FileProvidedRepos) > 0 {

repository/select-repos.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,38 +71,54 @@ func selectReposViaInput(config *config.GitXargsConfig) (*RepoSelection, error)
7171
AllowedRepos: []*types.AllowedRepo{},
7272
GithubOrganizationName: config.GithubOrg,
7373
}
74-
7574
switch getPreferredOrderOfRepoSelections(config) {
7675
case ExplicitReposOnCommandLine:
77-
allowedRepos, err := selectReposViaRepoFlag(config.RepoSlice)
76+
config.Stats.SetSelectionMode(string(ExplicitReposOnCommandLine))
77+
78+
allowedRepos, malformedRepos, err := selectReposViaRepoFlag(config.RepoSlice)
7879
if err != nil {
7980
return def, err
8081
}
82+
83+
trackMalformedUserSuppliedRepoNames(config, malformedRepos)
84+
8185
return &RepoSelection{
8286
SelectionType: ExplicitReposOnCommandLine,
8387
AllowedRepos: allowedRepos,
8488
GithubOrganizationName: "",
8589
}, nil
8690

8791
case ReposFilePath:
92+
93+
config.Stats.SetSelectionMode(string(ReposFilePath))
94+
8895
allowedRepos, err := io.ProcessAllowedRepos(config.ReposFile)
8996
if err != nil {
9097
return def, err
9198
}
99+
92100
return &RepoSelection{
93101
SelectionType: ReposFilePath,
94102
AllowedRepos: allowedRepos,
95103
GithubOrganizationName: "",
96104
}, nil
97105

98106
case GithubOrganization:
107+
108+
config.Stats.SetSelectionMode(string(GithubOrganization))
109+
99110
return def, nil
100111

101112
case ReposViaStdIn:
102-
allowedRepos, err := selectReposViaRepoFlag(config.RepoFromStdIn)
113+
config.Stats.SetSelectionMode(string(ReposViaStdIn))
114+
115+
allowedRepos, malformedRepos, err := selectReposViaRepoFlag(config.RepoFromStdIn)
103116
if err != nil {
104117
return def, err
105118
}
119+
120+
trackMalformedUserSuppliedRepoNames(config, malformedRepos)
121+
106122
return &RepoSelection{
107123
SelectionType: ReposViaStdIn,
108124
AllowedRepos: allowedRepos,
@@ -114,23 +130,40 @@ func selectReposViaInput(config *config.GitXargsConfig) (*RepoSelection, error)
114130
}
115131
}
116132

133+
// trackMalformedUserSuppliedRepoNames will add any malformed repositories supplied by the user via --repo or STDIN
134+
// to the final report, explaining that the repos could not be used as supplied (usually due to missing org prefix)
135+
func trackMalformedUserSuppliedRepoNames(config *config.GitXargsConfig, malformedRepos []string) {
136+
// If any repos supplied via --repo flags were not parsed successfully, probably because they were malformed,
137+
// then add them to the final run report so the operator understands why they were not processed
138+
for _, m := range malformedRepos {
139+
mr := &github.Repository{
140+
Name: github.String(m),
141+
}
142+
config.Stats.TrackSingle(stats.RepoFlagSuppliedRepoMalformed, mr)
143+
}
144+
}
145+
117146
// selectReposViaRepoFlag converts the string slice of repo flags provided via stdin or by invocations of the --repo
118147
// flag into the internal representation of AllowedRepo that we use prior to fetching the corresponding repo from
119148
// GitHub
120-
func selectReposViaRepoFlag(inputRepos []string) ([]*types.AllowedRepo, error) {
149+
func selectReposViaRepoFlag(inputRepos []string) ([]*types.AllowedRepo, []string, error) {
121150
var allowedRepos []*types.AllowedRepo
151+
var malformedRepos []string
122152

123153
for _, repoInput := range inputRepos {
124154
allowedRepo := util.ConvertStringToAllowedRepo(repoInput)
125155
if allowedRepo != nil {
126156
allowedRepos = append(allowedRepos, allowedRepo)
157+
} else {
158+
malformedRepos = append(malformedRepos, repoInput)
127159
}
128160
}
161+
129162
if len(allowedRepos) < 1 {
130-
return allowedRepos, errors.WithStackTrace(types.NoRepoSelectionsMadeErr{})
163+
return allowedRepos, malformedRepos, errors.WithStackTrace(types.NoRepoFlagTargetsValid{})
131164
}
132165

133-
return allowedRepos, nil
166+
return allowedRepos, malformedRepos, nil
134167
}
135168

136169
// fetchUserProvidedReposViaGithub converts repos provided as strings, already validated as being well-formed, into GitHub API repo objects that can be further processed

stats/stats.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ const (
6666
BranchRemotePullFailed types.Event = "branch-remote-pull-failed"
6767
// BranchRemoteDidntExistYet denotes a repo whose specified branch didn't exist remotely yet and so was just created locally to begin with
6868
BranchRemoteDidntExistYet types.Event = "branch-remote-didnt-exist-yet"
69+
// RepoFlagSuppliedRepoMalformed denotes a repo passed via the --repo flag that was malformed (perhaps missing it's Github org prefix) and therefore unprocessable
70+
RepoFlagSuppliedRepoMalformed types.Event = "repo-flag-supplied-repo-malformed"
6971
)
7072

7173
var allEvents = []types.AnnotatedEvent{
@@ -94,10 +96,12 @@ var allEvents = []types.AnnotatedEvent{
9496
{Event: DirectCommitsPushedToRemoteBranch, Description: "Repos whose changes were pushed directly to the remote branch because --skip-pull-requests was passed"},
9597
{Event: BranchRemotePullFailed, Description: "Repos whose remote branches could not be successfully pulled"},
9698
{Event: BranchRemoteDidntExistYet, Description: "Repos whose specified branches did not exist on the remote, and so were first created locally"},
99+
{Event: RepoFlagSuppliedRepoMalformed, Description: "Repos passed via the --repo flag that were malformed (missing their Github org prefix?) and therefore unprocessable"},
97100
}
98101

99102
// 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
100103
type RunStats struct {
104+
selectionMode string
101105
repos map[types.Event][]*github.Repository
102106
skippedArchivedRepos map[types.Event][]*github.Repository
103107
pulls map[string]string
@@ -128,6 +132,16 @@ func NewStatsTracker() *RunStats {
128132
return t
129133
}
130134

135+
// SetSelectionMode accepts a string representing the method by which repos were selected for this run - in order to print a human-legible description in the final report
136+
func (r *RunStats) SetSelectionMode(mode string) {
137+
r.selectionMode = mode
138+
}
139+
140+
// GetSelectionMode returns the currently set repo selection method
141+
func (r *RunStats) GetSelectionMode() string {
142+
return r.selectionMode
143+
}
144+
131145
// GetTotalRunSeconds returns the total time it took, in seconds, to run all the selected commands against all the targeted repos
132146
func (r *RunStats) GetTotalRunSeconds() int {
133147
s := time.Since(r.startTime).Seconds()
@@ -223,6 +237,7 @@ func (r *RunStats) GenerateRunReport() *types.RunReport {
223237
Repos: r.GetRepos(),
224238
SkippedRepos: r.GetSkippedArchivedRepos(),
225239
Command: r.command,
240+
SelectionMode: r.selectionMode,
226241
RuntimeSeconds: r.GetTotalRunSeconds(), FileProvidedRepos: r.GetFileProvidedRepos(),
227242
PullRequests: r.GetPullRequests(),
228243
}

types/types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type RunReport struct {
1919
Repos map[Event][]*github.Repository
2020
SkippedRepos map[Event][]*github.Repository
2121
Command []string
22+
SelectionMode string
2223
RuntimeSeconds int
2324
FileProvidedRepos []*AllowedRepo
2425
PullRequests map[string]string
@@ -60,6 +61,12 @@ func (NoRepoSelectionsMadeErr) Error() string {
6061
return fmt.Sprint("You must target some repos for processing either via stdin or by providing one of the --github-org, --repos, or --repo flags")
6162
}
6263

64+
type NoRepoFlagTargetsValid struct{}
65+
66+
func (NoRepoFlagTargetsValid) Error() string {
67+
return fmt.Sprint("None of the repos specified via the --repo flag are valid. Please double-check you have included the Github org prefix for each - e.g. --repo gruntwork-io/git-xargs")
68+
}
69+
6370
type NoBranchNameErr struct{}
6471

6572
func (NoBranchNameErr) Error() string {

0 commit comments

Comments
 (0)