Skip to content

Commit b7ef3de

Browse files
authored
Rate limit github clone calls (#142)
* feat: rate limit github clone calls Add rate limiting to github clone calls, avoiding issues with github "permission denied" and EOF errors when cloning too many repositories in parallel. Fixes #139 * chore(config): initialize limiter with default buffer
1 parent a58794b commit b7ef3de

File tree

6 files changed

+85
-61
lines changed

6 files changed

+85
-61
lines changed

README.md

+67-60
Large diffs are not rendered by default.

cmd/git-xargs.go

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ func parseGitXargsConfig(c *cli.Context) (*config.GitXargsConfig, error) {
4141
config.SecondsToSleepBetweenPRs = c.Int("seconds-between-prs")
4242
config.PullRequestRetries = c.Int("max-pr-retries")
4343
config.SecondsToSleepWhenRateLimited = c.Int("seconds-to-wait-when-rate-limited")
44+
maxConcurrentClones := c.Int("max-concurrent-clones")
45+
if maxConcurrentClones > 0 {
46+
config.CloneJobsLimiter = make(chan struct{}, maxConcurrentClones)
47+
}
48+
4449
config.NoSkipCI = c.Bool("no-skip-ci")
4550
config.RetainLocalRepos = c.Bool("keep-cloned-repositories")
4651
// By default, prepend "[skip ci]" to commit messages, unless the user passed --no-skip-ci

common/common.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ const (
2323
DefaultPullRequestDescription = "git-xargs programmatic pull request"
2424
MaxPullRequestRetriesFlagName = "max-pr-retries"
2525
SecondsToWaitWhenRateLimitedFlagName = "seconds-to-wait-when-rate-limited"
26+
MaxConcurrentClonesFlagName = "max-concurrent-clones"
2627
NoSkipCIFlagName = "no-skip-ci"
2728
KeepClonedRepositoriesFlagName = "keep-cloned-repositories"
28-
DefaultMaxConcurrentRepos = 0
29+
DefaultMaxConcurrentClones = 4
2930
DefaultSecondsBetweenPRs = 1
3031
DefaultMaxPullRequestRetries = 3
3132
DefaultSecondsToWaitWhenRateLimited = 60
@@ -106,6 +107,11 @@ var (
106107
Usage: "The number of additional seconds to sleep before attempting to open a PR again, when rate limited by GitHub. Defaults to 60.",
107108
Value: DefaultSecondsToWaitWhenRateLimited,
108109
}
110+
GenericMaxConcurrentClonesFlag = cli.IntFlag{
111+
Name: MaxConcurrentClonesFlagName,
112+
Usage: "The maximum number of concurrent clones to run at once. Defaults to 4. If set to 0 no limit will be applied.",
113+
Value: DefaultMaxConcurrentClones,
114+
}
109115
GenericNoSkipCIFlag = cli.BoolFlag{
110116
Name: NoSkipCIFlagName,
111117
Usage: "By default, git-xargs prepends \"[skip ci]\" to its commit messages. Pass this flag to prevent \"[skip ci]\" from being prepending to commit messages.",

config/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type GitXargsConfig struct {
3838
SecondsToSleepBetweenPRs int
3939
PullRequestRetries int
4040
SecondsToSleepWhenRateLimited int
41+
CloneJobsLimiter chan struct{}
4142
NoSkipCI bool
4243
RetainLocalRepos bool
4344
Ticker *time.Ticker
@@ -70,6 +71,7 @@ func NewGitXargsConfig() *GitXargsConfig {
7071
SecondsToSleepBetweenPRs: common.DefaultSecondsBetweenPRs,
7172
SecondsToSleepWhenRateLimited: common.DefaultSecondsToWaitWhenRateLimited,
7273
PullRequestRetries: common.DefaultMaxPullRequestRetries,
74+
CloneJobsLimiter: make(chan struct{}, common.DefaultMaxConcurrentClones),
7375
NoSkipCI: false,
7476
RetainLocalRepos: false,
7577
}

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func setupApp() *cli.App {
7676
common.GenericSecondsToWaitFlag,
7777
common.GenericMaxPullRequestRetriesFlag,
7878
common.GenericSecondsToWaitWhenRateLimitedFlag,
79+
common.GenericMaxConcurrentClonesFlag,
7980
common.GenericNoSkipCIFlag,
8081
common.GenericKeepClonedRepositoriesFlag,
8182
}

repository/repo-operations.go

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
// git-xargs-<repo-name> appended to it to make it easier to find when you are looking for it while debugging
3131
func cloneLocalRepository(config *config.GitXargsConfig, repo *github.Repository) (string, *git.Repository, error) {
3232
logger := logging.GetLogger("git-xargs")
33+
config.CloneJobsLimiter <- struct{}{}
3334

3435
logger.WithFields(logrus.Fields{
3536
"Repo": repo.GetName(),
@@ -58,6 +59,8 @@ func cloneLocalRepository(config *config.GitXargsConfig, repo *github.Repository
5859
"Repo": repo.GetName(),
5960
}).Debug(gitProgressBuffer)
6061

62+
<-config.CloneJobsLimiter
63+
6164
if err != nil {
6265
logger.WithFields(logrus.Fields{
6366
"Error": err,

0 commit comments

Comments
 (0)