Skip to content

Commit d74c637

Browse files
authored
paginate repo list, bug fix for issue #1941 (#2093)
* paginate repo list
1 parent 4666df9 commit d74c637

File tree

3 files changed

+105
-10
lines changed

3 files changed

+105
-10
lines changed

backend/controllers/github.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9-
"github.com/diggerhq/digger/libs/digger_config/terragrunt/tac"
10-
"github.com/diggerhq/digger/libs/git_utils"
119
"log/slog"
1210
"math/rand"
1311
"net/http"
@@ -21,6 +19,9 @@ import (
2119
"strings"
2220
"time"
2321

22+
"github.com/diggerhq/digger/libs/digger_config/terragrunt/tac"
23+
"github.com/diggerhq/digger/libs/git_utils"
24+
2425
"github.com/diggerhq/digger/backend/ci_backends"
2526
config2 "github.com/diggerhq/digger/backend/config"
2627
"github.com/diggerhq/digger/backend/locking"
@@ -2599,8 +2600,7 @@ func (d DiggerController) GithubAppCallbackPage(c *gin.Context) {
25992600
// we get repos accessible to this installation
26002601
slog.Debug("Listing repositories for installation", "installationId", installationId64)
26012602

2602-
opt := &github.ListOptions{Page: 1, PerPage: 100}
2603-
listRepos, _, err := client.Apps.ListRepos(context.Background(), opt)
2603+
repos, err := dg_github.ListGithubRepos(client)
26042604
if err != nil {
26052605
slog.Error("Failed to list existing repositories",
26062606
"installationId", installationId64,
@@ -2609,12 +2609,6 @@ func (d DiggerController) GithubAppCallbackPage(c *gin.Context) {
26092609
c.String(http.StatusInternalServerError, "Failed to list existing repos: %v", err)
26102610
return
26112611
}
2612-
repos := listRepos.Repositories
2613-
2614-
slog.Info("Retrieved repositories for installation",
2615-
"installationId", installationId64,
2616-
"repoCount", len(repos),
2617-
)
26182612

26192613
// resets all existing installations (soft delete)
26202614
slog.Debug("Resetting existing GitHub installations",

libs/ci/github/github_utils.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log/slog"
7+
8+
"github.com/google/go-github/v61/github"
9+
)
10+
11+
func ListGithubRepos(client *github.Client) ([]*github.Repository, error) {
12+
allRepos := make([]*github.Repository, 0)
13+
//err := c.BindJSON(&request)
14+
opts := &github.ListOptions{PerPage: 100}
15+
16+
pageLimit := 0
17+
for {
18+
listRepos, resp, err := client.Apps.ListRepos(context.Background(), opts)
19+
if err != nil {
20+
// Check specifically for rate limit errors
21+
if _, ok := err.(*github.RateLimitError); ok {
22+
slog.Error("GitHub API rate limit exceeded",
23+
"error", err,
24+
)
25+
// Wait and retry after a delay or return a specific error
26+
// For now, we'll just return with the rate limit error
27+
return nil, err
28+
}
29+
slog.Error("Failed to list existing repositories",
30+
"error", err,
31+
)
32+
return nil, err
33+
}
34+
allRepos = append(allRepos, listRepos.Repositories...)
35+
pageLimit++
36+
if pageLimit == 20 {
37+
slog.Error("Exceeded maximum number of pages (20) when listing repositories, results may be incomplete")
38+
return nil, fmt.Errorf("exceeded maximum number of pages (20) when listing repositories, results may be incomplete")
39+
}
40+
if resp.NextPage == 0 {
41+
break
42+
}
43+
opts.Page = resp.NextPage
44+
}
45+
return allRepos, nil
46+
}

libs/ci/github/github_utils_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package github
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
net "net/http"
7+
"os"
8+
"strconv"
9+
"testing"
10+
11+
"github.com/bradleyfalzon/ghinstallation/v2"
12+
"github.com/google/go-github/v61/github"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestListRepositoriesReturnsAllReposities(t *testing.T) {
17+
if os.Getenv("CI") != "" {
18+
t.Skip("skipping in CI")
19+
}
20+
githubAppPrivateKeyB64 := os.Getenv("GITHUB_APP_PRIVATE_KEY_BASE64")
21+
decodedBytes, err := base64.StdEncoding.DecodeString(githubAppPrivateKeyB64)
22+
if err != nil {
23+
fmt.Printf("Failed to decode GITHUB_APP_PRIVATE_KEY_BASE64, error: %v\n", err)
24+
t.Error(err)
25+
}
26+
githubAppPrivateKey := string(decodedBytes)
27+
tr := net.DefaultTransport
28+
var githubAppId = os.Getenv("GITHUB_APP_ID")
29+
var installationId = os.Getenv("INSTALLATION_ID")
30+
31+
githubAppIdintValue, err := strconv.ParseInt(githubAppId, 10, 64)
32+
if err != nil {
33+
fmt.Printf("Error converting environment variable to int64: %v\n", err)
34+
t.Fatalf("Failed to parse GITHUB_APP_ID: %v", err)
35+
}
36+
installationIdintValue, err := strconv.ParseInt(installationId, 10, 64)
37+
if err != nil {
38+
fmt.Printf("Error converting environment variable to int64: %v\n", err)
39+
t.Fatalf("Failed to parse INSTALLATION_ID: %v", err)
40+
}
41+
42+
itr, err := ghinstallation.New(tr, githubAppIdintValue, installationIdintValue, []byte(githubAppPrivateKey))
43+
if err != nil {
44+
fmt.Printf("Failed to initialize GitHub app installation: githubAppId=%s, installationId=%s, error=%v\n", githubAppId, installationId, err)
45+
t.Error(err)
46+
}
47+
48+
client := github.NewClient(&net.Client{Transport: itr})
49+
50+
allRepos, err := ListGithubRepos(client)
51+
fmt.Println("err is", err)
52+
assert.Nil(t, err)
53+
// Currently Digger has 388 repositories, Update the hardcoded value to the expected number of repositories if the number changes in the future.
54+
assert.Equal(t, 388, len(allRepos))
55+
}

0 commit comments

Comments
 (0)