This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 14108386c fix(github): show private repos for authenticated user's own
account (#8680) (#8681)
14108386c is described below
commit 14108386cf38d7afb96335dab887f82d3e59edc4
Author: Kristian Lind <[email protected]>
AuthorDate: Mon Jan 12 16:02:33 2026 +0100
fix(github): show private repos for authenticated user's own account
(#8680) (#8681)
Previously, when listing repos for the PAT owner's own account, the code
used /users/{username}/repos which only returns public repos.
Changes:
- Add getOwnerInfo() to fetch owner type (User/Organization) from API
- Add getAuthenticatedUserID() to get current user's ID
- Use switch on owner type to select the correct endpoint:
- Organization: /orgs/{owner}/repos
- Authenticated user: /user/repos (includes private repos)
- Other users: /users/{owner}/repos (public only)
- Rename function to listGithubOwnerRepos and parameter to 'owner'
- Add type=all query parameter to include all repo types
Closes #8680
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <[email protected]>
Co-authored-by: Klesh Wong <[email protected]>
---
backend/plugins/github/api/remote_api.go | 67 ++++++++++++++++++++++++++++----
1 file changed, 59 insertions(+), 8 deletions(-)
diff --git a/backend/plugins/github/api/remote_api.go
b/backend/plugins/github/api/remote_api.go
index 98ad96167..6fff1a202 100644
--- a/backend/plugins/github/api/remote_api.go
+++ b/backend/plugins/github/api/remote_api.go
@@ -52,7 +52,7 @@ func listGithubRemoteScopes(
if groupId == "" {
return listGithubUserOrgs(apiClient, page)
}
- return listGithubOrgRepos(apiClient, groupId, page)
+ return listGithubOwnerRepos(apiClient, groupId, page)
}
func listGithubUserOrgs(
@@ -112,9 +112,41 @@ func listGithubUserOrgs(
return children, nextPage, nil
}
-func listGithubOrgRepos(
+// getOwnerInfo fetches the owner's type and ID from the GitHub API.
+func getOwnerInfo(apiClient plugin.ApiClient, owner string) (ownerType string,
ownerID int, err errors.Error) {
+ resp, err := apiClient.Get(fmt.Sprintf("users/%s", owner), nil, nil)
+ if err != nil {
+ return "", 0, err
+ }
+ var info struct {
+ ID int `json:"id"`
+ Type string `json:"type"`
+ }
+ errors.Must(api.UnmarshalResponse(resp, &info))
+ return info.Type, info.ID, nil
+}
+
+// getAuthenticatedUserID returns the ID of the currently authenticated user.
+func getAuthenticatedUserID(apiClient plugin.ApiClient) (int, errors.Error) {
+ resp, err := apiClient.Get("user", nil, nil)
+ if err != nil {
+ return 0, err
+ }
+ var user struct {
+ ID int `json:"id"`
+ }
+ errors.Must(api.UnmarshalResponse(resp, &user))
+ return user.ID, nil
+}
+
+// listGithubOwnerRepos lists repositories for a given owner (user or
organization).
+// It determines the owner type via the GitHub API and uses the appropriate
endpoint:
+// - For organizations: /orgs/{owner}/repos
+// - For the authenticated user: /user/repos (includes private repos)
+// - For other users: /users/{owner}/repos (public repos only)
+func listGithubOwnerRepos(
apiClient plugin.ApiClient,
- org string,
+ owner string,
page GithubRemotePagination,
) (
children []dsmodels.DsRemoteApiScopeListEntry[models.GithubRepo],
@@ -124,19 +156,38 @@ func listGithubOrgRepos(
query := url.Values{
"page": []string{fmt.Sprintf("%v", page.Page)},
"per_page": []string{fmt.Sprintf("%v", page.PerPage)},
+ "type": []string{"all"},
}
- // user's orgs
- reposBody, err := apiClient.Get(fmt.Sprintf("orgs/%s/repos", org),
query, nil)
+
+ ownerType, ownerID, err := getOwnerInfo(apiClient, owner)
if err != nil {
return nil, nil, err
}
- // if not found, try to get user repos
- if reposBody.StatusCode == http.StatusNotFound {
- reposBody, err = apiClient.Get(fmt.Sprintf("users/%s/repos",
org), query, nil)
+
+ var reposBody *http.Response
+ switch ownerType {
+ case "Organization":
+ reposBody, err = apiClient.Get(fmt.Sprintf("orgs/%s/repos",
owner), query, nil)
+ case "User":
+ authUserID, err := getAuthenticatedUserID(apiClient)
if err != nil {
return nil, nil, err
}
+ if authUserID == ownerID {
+ // Authenticated user's own account - includes private
repos
+ reposBody, err = apiClient.Get("user/repos", query, nil)
+ } else {
+ // Another user's account - public repos only
+ reposBody, err =
apiClient.Get(fmt.Sprintf("users/%s/repos", owner), query, nil)
+ }
+ default:
+ // Fallback for unknown types
+ reposBody, err = apiClient.Get(fmt.Sprintf("users/%s/repos",
owner), query, nil)
}
+ if err != nil {
+ return nil, nil, err
+ }
+
var repos []repo
errors.Must(api.UnmarshalResponse(reposBody, &repos))
for _, repo := range repos {