-
Notifications
You must be signed in to change notification settings - Fork 0
fix: Error on PR creation #414
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
base: main
Are you sure you want to change the base?
Changes from all commits
0b5863f
7b75829
3c1914c
1fa5ac5
0de040c
3ef569e
c8b0e91
3a2a99d
4d983b8
56c2832
bdf4fca
3ca4e9e
bbbad60
50154f4
7b846b4
e3b5e87
3712723
8d9a486
d1407a8
81a94b4
42c9136
b13f451
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,7 @@ import ( | |||||||||||
| "errors" | ||||||||||||
| "fmt" | ||||||||||||
| "regexp" | ||||||||||||
| "strconv" | ||||||||||||
| "strings" | ||||||||||||
| "time" | ||||||||||||
|
|
||||||||||||
|
|
@@ -25,6 +26,8 @@ type Gh struct { | |||||||||||
| } | ||||||||||||
|
|
||||||||||||
| var ErrorNoNewCommits error = errors.New("no new commits created") | ||||||||||||
| var MaxRetries int = 5 | ||||||||||||
| var WaitTimeBetweenRetries time.Duration = 2 * time.Second | ||||||||||||
|
|
||||||||||||
| // Exit code 10 is used to indicate the 'no new commits' scenario. | ||||||||||||
| // This value is chosen to distinguish it from standard exit codes (e.g., 0 for success, 1 for general errors). | ||||||||||||
|
|
@@ -349,26 +352,65 @@ func (m *Gh) CreatePR( | |||||||||||
| ctr = ctr. | ||||||||||||
| WithExec(cmd) | ||||||||||||
|
|
||||||||||||
| _, err = ctr.Sync(ctx) | ||||||||||||
| if err != nil { | ||||||||||||
| return "", errors.New( | ||||||||||||
| extractErrorMessage(err), | ||||||||||||
| ) | ||||||||||||
| fmt.Println("\nCreating PR...") | ||||||||||||
| for i := range MaxRetries { | ||||||||||||
| _, err = ctr.Sync(ctx) | ||||||||||||
|
|
||||||||||||
| if err == nil { | ||||||||||||
| break | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if i == MaxRetries-1 { | ||||||||||||
| return "", errors.New( | ||||||||||||
| extractErrorMessage(err), | ||||||||||||
| ) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| fmt.Printf("Error creating PR, retrying... (%d/%d)\n", i+1, MaxRetries-1) | ||||||||||||
|
|
||||||||||||
| timer := time.NewTimer(WaitTimeBetweenRetries) | ||||||||||||
| select { | ||||||||||||
| case <-timer.C: | ||||||||||||
| case <-ctx.Done(): | ||||||||||||
| timer.Stop() | ||||||||||||
| return "", ctx.Err() | ||||||||||||
| } | ||||||||||||
|
Comment on lines
+371
to
+377
|
||||||||||||
| } | ||||||||||||
juanjosevazquezgil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
|
||||||||||||
| prId, err := ctr. | ||||||||||||
| WithExec([]string{ | ||||||||||||
| "gh", "pr", "list", | ||||||||||||
| "--head", branch, | ||||||||||||
| "--json", "number", | ||||||||||||
| "--jq", ".[0].number", | ||||||||||||
| }). | ||||||||||||
| Stdout(ctx) | ||||||||||||
| var prId string | ||||||||||||
| fmt.Println("Getting PR ID...") | ||||||||||||
| for i := range MaxRetries { | ||||||||||||
| prId, err = ctr. | ||||||||||||
| WithExec([]string{ | ||||||||||||
| "gh", "pr", "list", | ||||||||||||
| "--head", branch, | ||||||||||||
| "--json", "number", | ||||||||||||
| "--jq", ".[0].number", | ||||||||||||
| }). | ||||||||||||
| Stdout(ctx) | ||||||||||||
|
|
||||||||||||
| if err != nil { | ||||||||||||
| return "", errors.New( | ||||||||||||
| extractErrorMessage(err), | ||||||||||||
| ) | ||||||||||||
| // Check if the prId is a valid integer (which means we got the PR ID successfully). If not, we retry. | ||||||||||||
| _, convErr := strconv.Atoi(strings.TrimSpace(prId)) | ||||||||||||
|
|
||||||||||||
| if err == nil && convErr == nil { | ||||||||||||
| break | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if i == MaxRetries-1 { | ||||||||||||
|
||||||||||||
| if i == MaxRetries-1 { | |
| if i == MaxRetries-1 { | |
| if err == nil && convErr != nil { | |
| return "", convErr | |
| } |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using fmt.Println and fmt.Printf for logging in a library module is not ideal as it bypasses the caller's control over logging output and format. These print statements will always output to stdout, which may not be desired in all contexts. Consider either removing these debug statements for production code, or if logging is necessary, use a structured logging approach that can be configured by the caller (e.g., passing a logger interface).
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timer should be stopped after the select statement completes to free resources, regardless of which case is triggered. Currently, the timer is only stopped when the context is cancelled. If the timer fires normally (case <-timer.C), the timer resources are not explicitly cleaned up. While Go's garbage collector will eventually handle this, it's best practice to explicitly stop timers that are no longer needed. Add timer.Stop() after the select statement or use defer timer.Stop() right after creating the timer.
juanjosevazquezgil marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The retry logic is duplicated between the PR creation and PR ID retrieval sections. This code duplication makes maintenance harder and increases the risk of inconsistencies. Consider extracting the retry logic into a reusable helper function that accepts a function to execute and returns its result, similar to: retryWithBackoff(ctx context.Context, operation func() error, maxRetries int, waitTime time.Duration) error. This would also make it easier to improve the retry strategy (e.g., adding exponential backoff) in one place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The retry logic blindly retries all errors without distinguishing between transient failures (which should be retried) and permanent failures (which should fail immediately). For example, authentication errors, invalid repository errors, or permission errors should not be retried. Consider checking the error type or message to determine if the error is retryable before waiting and retrying.