diff --git a/action.yaml b/action.yaml index d90c4a4..455a94c 100644 --- a/action.yaml +++ b/action.yaml @@ -25,7 +25,7 @@ inputs: default: 1 runs: using: 'docker' - image: 'docker://ghcr.io/prodyna/github-users:v1.3' + image: 'docker://ghcr.io/prodyna/github-users:v1.4' env: ACTION: ${{ inputs.action }} ENTERPRISE: ${{ inputs.enterprise }} diff --git a/template/collaborators.tpl b/template/collaborators.tpl index fd20cff..dd94d1a 100644 --- a/template/collaborators.tpl +++ b/template/collaborators.tpl @@ -6,5 +6,10 @@ Last updated: {{ .Updated }} | ------ | ---- | ------------- | ------------ | ---------- | {{ range $user := .Users }}{{ range $org := $user.Organizations }}{{ range $repo := $org.Repositories }}| {{ $user.Number }} | [{{ $user.Login }}](https://github.com/{{ $user.Login }}) | {{if $user.Contributions}}:green_square:{{else}}:red_square:{{end}} {{ $user.Contributions }} | [{{ $org.Name }}](https://github.com/{{ $org.Login }}) | [{{ $repo.Name }}](https://github.com/{{ $org.Login }}/{{ $repo.Name }}) | {{ end }}{{ end }}{{ end }} + +{{ if .Warnings }} +## Warnings +{{ range .Warnings }}* {{ . }} +{{ end }}{{ end }} --- Generated with :heart: by [github-users](https://github.com/prodyna/github-users) diff --git a/template/members.tpl b/template/members.tpl index 8f7e7ee..0b013b7 100644 --- a/template/members.tpl +++ b/template/members.tpl @@ -9,5 +9,9 @@ Last updated: {{ .Updated }} {{ if .Users }}_{{ len .Users }} users_{{ else }}No users found.{{ end }} +{{ if .Warnings }} +## Warnings +{{ range .Warnings }}* {{ . }} +{{ end }}{{ end }} --- Generated with :heart: by [github-users](https://github.com/prodyna/github-users) diff --git a/userlist/collaborators.go b/userlist/collaborators.go index 767d2bb..0081dec 100644 --- a/userlist/collaborators.go +++ b/userlist/collaborators.go @@ -2,7 +2,6 @@ package userlist import ( "context" - "encoding/json" "fmt" "github.com/shurcooL/githubv4" "golang.org/x/oauth2" @@ -46,6 +45,10 @@ func (c *UserListConfig) loadCollaborators() error { Login string Name string } + PageInfo struct { + HasNextPage bool + EndCursor githubv4.String + } } `graphql:"organizations(first:100)"` } `graphql:"enterprise(slug: $slug)"` } @@ -62,6 +65,11 @@ func (c *UserListConfig) loadCollaborators() error { } slog.Info("Loaded organizations", "organization.count", len(organizations.Enterprise.Organizations.Nodes)) + if organizations.Enterprise.Organizations.PageInfo.HasNextPage { + slog.Warn("More organizations available - not yet implemented") + c.userList.addWarning("More organizations available - not yet implemented") + } + /* { organization(login:"prodyna") { @@ -92,6 +100,7 @@ func (c *UserListConfig) loadCollaborators() error { userNumber := 0 slog.Info("Iterating organizatons", "organization.count", len(organizations.Enterprise.Organizations.Nodes)) + for _, org := range organizations.Enterprise.Organizations.Nodes { slog.Info("Loading repositories and external collaborators", "organization", org.Login) var query struct { @@ -110,82 +119,95 @@ func (c *UserListConfig) loadCollaborators() error { } } } + PageInfo struct { + HasNextPage bool + EndCursor githubv4.String + } } `graphql:"collaborators(first:100,affiliation:OUTSIDE)"` } - } `graphql:"repositories(first:100)"` + PageInfo struct { + HasNextPage bool + EndCursor githubv4.String + } + } `graphql:"repositories(first:$first,after:$after)"` } `graphql:"organization(login: $organization)"` } variables := map[string]interface{}{ "organization": githubv4.String(org.Login), + "first": githubv4.Int(100), + "after": (*githubv4.String)(nil), } - err := client.Query(ctx, &query, variables) - if err != nil { - slog.WarnContext(ctx, "Unable to query - will skip this organization", "error", err, "organization", org.Login) - continue - } + for { + err := client.Query(ctx, &query, variables) + if err != nil { + slog.WarnContext(ctx, "Unable to query - will skip this organization", "error", err, "organization", org.Login) + c.userList.addWarning(fmt.Sprintf("Unable to query organization %s", org.Login)) + break + } - // count the collaborators - collaboratorCount := 0 - for _, repo := range query.Organization.Repositories.Nodes { - collaboratorCount += len(repo.Collaborators.Nodes) - } - if collaboratorCount == 0 { - slog.DebugContext(ctx, "No collaborators found", "organization", org.Login) - continue - } + // count the collaborators + collaboratorCount := 0 + for _, repo := range query.Organization.Repositories.Nodes { + collaboratorCount += len(repo.Collaborators.Nodes) + } + if collaboratorCount == 0 { + slog.DebugContext(ctx, "No collaborators found", "organization", org.Login) + break + } - for _, repo := range query.Organization.Repositories.Nodes { - slog.DebugContext(ctx, "Processing repository", "repository", repo.Name, "collaborator.count", len(repo.Collaborators.Nodes)) - for _, collaborator := range repo.Collaborators.Nodes { - slog.DebugContext(ctx, "Processing collaborator", "login", collaborator.Login, "name", collaborator.Name, "contributions", collaborator.ContributionsCollection.ContributionCalendar.TotalContributions) - - // User - user := c.userList.findUser(collaborator.Login) - if user == nil { - user = c.userList.createUser(userNumber+1, collaborator.Login, collaborator.Name, "", collaborator.ContributionsCollection.ContributionCalendar.TotalContributions) - userNumber++ - } else { - slog.Info("Found existing user", "login", user.Login) - } + for _, repo := range query.Organization.Repositories.Nodes { + slog.DebugContext(ctx, "Processing repository", "repository", repo.Name, "collaborator.count", len(repo.Collaborators.Nodes)) + for _, collaborator := range repo.Collaborators.Nodes { + slog.DebugContext(ctx, "Processing collaborator", "login", collaborator.Login, "name", collaborator.Name, "contributions", collaborator.ContributionsCollection.ContributionCalendar.TotalContributions) + + // User + user := c.userList.findUser(collaborator.Login) + if user == nil { + user = c.userList.createUser(userNumber+1, collaborator.Login, collaborator.Name, "", collaborator.ContributionsCollection.ContributionCalendar.TotalContributions) + userNumber++ + } else { + slog.Info("Found existing user", "login", user.Login) + } - // Organization - organization := user.findOrganization(org.Login) - if organization == nil { - organization = user.createOrganization(org.Login, org.Name) - } else { - slog.Info("Found existing organization", "organization", organization.Name) - } + // Organization + organization := user.findOrganization(org.Login) + if organization == nil { + organization = user.createOrganization(org.Login, org.Name) + } else { + slog.Info("Found existing organization", "organization", organization.Name) + } - // Repository - repository := organization.findRepository(repo.Name) - if repository == nil { - repository = organization.createRepository(repo.Name) - } else { - slog.Info("Found existing repository", "repository", repository.Name) + // Repository + repository := organization.findRepository(repo.Name) + if repository == nil { + repository = organization.createRepository(repo.Name) + } else { + slog.Info("Found existing repository", "repository", repository.Name) + } + organization.upsertRepository(*repository) } - organization.upsertRepository(*repository) } - } - slog.InfoContext(ctx, "Loaded repositories", - "repository.count", len(query.Organization.Repositories.Nodes), - "organization", org.Login, - "collaborator.count", collaboratorCount) + slog.InfoContext(ctx, "Loaded repositories", + "repository.count", len(query.Organization.Repositories.Nodes), + "organization", org.Login, + "collaborator.count", collaboratorCount) - if collaboratorCount == 0 { - continue - } + if collaboratorCount == 0 { + continue + } - output, err := json.MarshalIndent(c.userList, "", " ") - if err != nil { - slog.ErrorContext(ctx, "Unable to marshal json", "error", err) - return err - } - fmt.Printf("%s\n", output) + slog.InfoContext(ctx, "Adding collaborators", "organization", org.Login) - slog.InfoContext(ctx, "Adding collaborators", "organization", org.Login) + if !query.Organization.Repositories.PageInfo.HasNextPage { + break + } + + slog.Info("More repositories available", "organization", org.Login, "after", query.Organization.Repositories.PageInfo.EndCursor) + variables["after"] = githubv4.NewString(query.Organization.Repositories.PageInfo.EndCursor) + } } c.loaded = true diff --git a/userlist/userlist.go b/userlist/userlist.go index 19984e4..cd709c0 100644 --- a/userlist/userlist.go +++ b/userlist/userlist.go @@ -31,6 +31,7 @@ type UserList struct { Updated string Enterprise Enterprise Users []*User + Warnings []string } type Enterprise struct { @@ -244,3 +245,10 @@ func (o *Organization) createRepository(name string) *Repository { o.upsertRepository(*repo) return repo } + +func (c *UserList) addWarning(warning string) { + if c.Warnings == nil { + c.Warnings = make([]string, 0) + } + c.Warnings = append(c.Warnings, warning) +}