Skip to content

Commit ac208ec

Browse files
authored
Merge pull request #47 from opengovern/fix_duplicates
feat: updated team category tables fields
2 parents 76ae617 + c180e1b commit ac208ec

14 files changed

+1159
-714
lines changed

cloudql/github/plugin.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ func Plugin(ctx context.Context) *plugin.Plugin {
5151
"github_repository_sbom": tableGitHubRepositorySbom(),
5252
"github_repository_vulnerability_alert": tableGitHubRepositoryVulnerabilityAlert(),
5353
"github_tag": tableGitHubTag(),
54+
"github_team": tableGitHubTeam(),
5455
"github_team_member": tableGitHubTeamMember(),
56+
"github_team_repository": tableGitHubTeamRepository(),
5557
//"github_tree": tableGitHubTree(),
5658
"github_user": tableGitHubUser(),
5759
"github_workflow": tableGitHubWorkflow(),

cloudql/github/table_github_organization_team.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,8 @@ func gitHubTeamColumns() []*plugin.Column {
4949
Transform: transform.FromField("Description.RepositoriesTotalCount")},
5050
{Name: "url", Type: proto.ColumnType_STRING, Description: "URL for the team page in GitHub.",
5151
Transform: transform.FromField("Description.URL")},
52-
{Name: "avatar_url", Type: proto.ColumnType_STRING, Description: "URL for teams avatar.",
53-
Transform: transform.FromField("Description.AvatarURL")},
5452
{Name: "discussions_url", Type: proto.ColumnType_STRING, Description: "URL for team discussions.",
5553
Transform: transform.FromField("Description.DiscussionsURL")},
56-
{Name: "edit_team_url", Type: proto.ColumnType_STRING, Description: "URL for editing this team.",
57-
Transform: transform.FromField("Description.EditTeamURL")},
5854
{Name: "members_url", Type: proto.ColumnType_STRING, Description: "URL for team members.",
5955
Transform: transform.FromField("Description.MembersURL")},
6056
{Name: "new_team_url", Type: proto.ColumnType_STRING, Description: "The HTTP URL creating a new team.",
@@ -63,10 +59,6 @@ func gitHubTeamColumns() []*plugin.Column {
6359
Transform: transform.FromField("Description.RepositoriesURL")},
6460
{Name: "teams_url", Type: proto.ColumnType_STRING, Description: "URL for this team's teams.",
6561
Transform: transform.FromField("Description.TeamsURL")},
66-
{Name: "can_administer", Type: proto.ColumnType_BOOL, Description: "If true, current user can administer the team.",
67-
Transform: transform.FromField("Description.CanAdminister")},
68-
{Name: "can_subscribe", Type: proto.ColumnType_BOOL, Description: "If true, current user can subscribe to the team.",
69-
Transform: transform.FromField("Description.CanSubscribe")},
7062
{Name: "subscription", Type: proto.ColumnType_STRING, Description: "Subscription status of the current user to the team.",
7163
Transform: transform.FromField("Description.Subscription")},
7264
}
@@ -77,11 +69,11 @@ func tableGitHubOrganizationTeam() *plugin.Table {
7769
Name: "github_organization_team",
7870
Description: "GitHub Teams in a given organization. GitHub Teams are groups of organization members that reflect your company or group's structure with cascading access permissions and mentions.",
7971
List: &plugin.ListConfig{
80-
Hydrate: opengovernance.ListTeamMembers,
72+
Hydrate: opengovernance.ListTeamMember,
8173
},
8274
Get: &plugin.GetConfig{
8375
KeyColumns: plugin.AllColumns([]string{"organization", "slug"}),
84-
Hydrate: opengovernance.GetTeamMembers,
76+
Hydrate: opengovernance.GetTeamMember,
8577
},
8678
Columns: commonColumns(gitHubTeamColumns()),
8779
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package github
2+
3+
import (
4+
opengovernance "github.com/opengovern/og-describer-github/discovery/pkg/es"
5+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
6+
)
7+
8+
func tableGitHubTeam() *plugin.Table {
9+
return &plugin.Table{
10+
Name: "github_team",
11+
Description: "GitHub Teams in a given organization. GitHub Teams are groups of organization members that reflect your company or group's structure with cascading access permissions and mentions.",
12+
List: &plugin.ListConfig{
13+
Hydrate: opengovernance.ListTeam,
14+
},
15+
Get: &plugin.GetConfig{
16+
KeyColumns: plugin.AllColumns([]string{"organization", "slug"}),
17+
ShouldIgnoreError: isNotFoundError([]string{"404"}),
18+
Hydrate: opengovernance.GetTeam,
19+
},
20+
Columns: commonColumns(gitHubTeamColumns()),
21+
}
22+
}

cloudql/github/table_github_team_member.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ func tableGitHubTeamMember() *plugin.Table {
1212
Name: "github_team_member",
1313
Description: "GitHub members for a given team. GitHub Users are user accounts in GitHub.",
1414
List: &plugin.ListConfig{
15-
Hydrate: opengovernance.ListTeamMembers,
15+
Hydrate: opengovernance.ListTeamMember,
16+
},
17+
Get: &plugin.GetConfig{
18+
KeyColumns: plugin.AllColumns([]string{"id"}),
19+
Hydrate: opengovernance.GetTeamMember,
1620
},
1721
Columns: commonColumns(gitHubTeamMemberColumns()),
1822
}
@@ -26,6 +30,28 @@ func gitHubTeamMemberColumns() []*plugin.Column {
2630
Transform: transform.FromField("Description.Slug")},
2731
{Name: "role", Type: proto.ColumnType_STRING, Description: "The team member's role (MEMBER, MAINTAINER).",
2832
Transform: transform.FromField("Description.Role")},
33+
{Name: "company", Type: proto.ColumnType_STRING, Description: "The company on the user's profile.",
34+
Transform: transform.FromField("Description.Company")},
35+
{Name: "created_at", Type: proto.ColumnType_TIMESTAMP, Description: "Timestamp when user was created.",
36+
Transform: transform.FromField("Description.CreatedAt")},
37+
{Name: "email", Type: proto.ColumnType_STRING, Description: "The email of the user.",
38+
Transform: transform.FromField("Description.Email")},
39+
{Name: "id", Type: proto.ColumnType_INT, Description: "The ID of the user.",
40+
Transform: transform.FromField("Description.ID")},
41+
{Name: "interaction_ability", Type: proto.ColumnType_JSON, Description: "The interaction ability settings for this user.",
42+
Transform: transform.FromField("Description.InteractionAbility")},
43+
{Name: "is_site_admin", Type: proto.ColumnType_BOOL, Description: "If true, user is a site administrator.",
44+
Transform: transform.FromField("Description.IsSiteAdmin")},
45+
{Name: "location", Type: proto.ColumnType_STRING, Description: "The location of the user.",
46+
Transform: transform.FromField("Description.Location")},
47+
{Name: "login", Type: proto.ColumnType_STRING, Description: "The login name of the user.",
48+
Transform: transform.FromField("Description.Login")},
49+
{Name: "login_id", Type: proto.ColumnType_STRING, Description: "Unique identifier for the user login.",
50+
Transform: transform.FromField("Description.LoginID")},
51+
{Name: "name", Type: proto.ColumnType_STRING, Description: "The name of the user.",
52+
Transform: transform.FromField("Description.Name")},
53+
{Name: "node_id", Type: proto.ColumnType_STRING, Description: "The node ID of the user.",
54+
Transform: transform.FromField("Description.NodeID")},
2955
}
3056

3157
cols = append(cols, sharedUserColumns()...)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package github
2+
3+
import (
4+
opengovernance "github.com/opengovern/og-describer-github/discovery/pkg/es"
5+
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
6+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
7+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
8+
)
9+
10+
func gitHubTeamRepositoryColumns() []*plugin.Column {
11+
teamColumns := []*plugin.Column{
12+
{Name: "repository_full_name", Type: proto.ColumnType_STRING, Description: "",
13+
Transform: transform.FromQual("Description.RepositoryFullName")},
14+
{Name: "permission", Type: proto.ColumnType_STRING, Description: "The permission level the team has on the repository.",
15+
Transform: transform.FromQual("Description.Permission")},
16+
{Name: "team_id", Type: proto.ColumnType_INT, Description: "",
17+
Transform: transform.FromQual("Description.TeamID")},
18+
{Name: "created_at", Type: proto.ColumnType_TIMESTAMP, Description: "",
19+
Transform: transform.FromQual("Description.CreatedAt")},
20+
{Name: "updated_at", Type: proto.ColumnType_TIMESTAMP, Description: "",
21+
Transform: transform.FromQual("Description.UpdatedAt")},
22+
}
23+
24+
return append(teamColumns, sharedRepositoryColumns()...)
25+
}
26+
27+
func tableGitHubTeamRepository() *plugin.Table {
28+
return &plugin.Table{
29+
Name: "github_team_repository",
30+
Description: "GitHub Repositories that a given team is associated with. GitHub Repositories contain all of your project's files and each file's revision history.",
31+
List: &plugin.ListConfig{
32+
Hydrate: opengovernance.ListTeamRepository,
33+
},
34+
Get: &plugin.GetConfig{
35+
KeyColumns: []*plugin.KeyColumn{
36+
{Name: "repository_full_name", Require: plugin.Required},
37+
},
38+
Hydrate: opengovernance.GetTeamRepository,
39+
},
40+
Columns: commonColumns(gitHubTeamRepositoryColumns()),
41+
}
42+
}

discovery/describers/organization_team.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,11 @@ func GetOrganizationTeamList(ctx context.Context, githubClient model.GitHubClien
7474
ProjectsV2TotalCount: team.ProjectsV2.TotalCount,
7575
RepositoriesTotalCount: team.Repositories.TotalCount,
7676
URL: team.Url,
77-
AvatarURL: team.AvatarUrl,
7877
DiscussionsURL: team.DiscussionsUrl,
79-
EditTeamURL: team.EditTeamUrl,
8078
MembersURL: team.MembersUrl,
8179
NewTeamURL: team.NewTeamUrl,
8280
RepositoriesURL: team.RepositoriesUrl,
8381
TeamsURL: team.TeamsUrl,
84-
CanAdminister: team.CanAdminister,
85-
CanSubscribe: team.CanSubscribe,
8682
Subscription: team.Subscription,
8783
},
8884
}

discovery/describers/team.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package describers
2+
3+
import (
4+
"context"
5+
"github.com/opengovern/og-describer-github/discovery/pkg/models"
6+
model "github.com/opengovern/og-describer-github/discovery/provider"
7+
"github.com/shurcooL/githubv4"
8+
steampipemodels "github.com/turbot/steampipe-plugin-github/github/models"
9+
"strconv"
10+
)
11+
12+
func GetTeamList(ctx context.Context, githubClient model.GitHubClient, organizationName string, stream *models.StreamSender) ([]models.Resource, error) {
13+
client := githubClient.GraphQLClient
14+
var query struct {
15+
RateLimit steampipemodels.RateLimit
16+
Viewer struct {
17+
Organization struct {
18+
Login string
19+
Teams struct {
20+
PageInfo steampipemodels.PageInfo
21+
Nodes []steampipemodels.TeamWithCounts
22+
} `graphql:"teams(first: $pageSize, after: $cursor)"`
23+
} `graphql:"organization(login: $orgName)"`
24+
}
25+
}
26+
variables := map[string]interface{}{
27+
"orgName": githubv4.String(organizationName),
28+
"pageSize": githubv4.Int(pageSize),
29+
"cursor": (*githubv4.String)(nil),
30+
}
31+
appendTeamColumnIncludes(&variables, teamCols())
32+
var values []models.Resource
33+
var teams []steampipemodels.TeamWithCounts
34+
err := client.Query(ctx, &query, variables)
35+
if err != nil {
36+
return nil, err
37+
}
38+
teams = append(teams, query.Viewer.Organization.Teams.Nodes...)
39+
if query.Viewer.Organization.Teams.PageInfo.HasNextPage {
40+
ts, err := getAdditionalTeams(ctx, client, query.Viewer.Organization.Login, query.Viewer.Organization.Teams.PageInfo.EndCursor)
41+
if err != nil {
42+
return nil, err
43+
}
44+
teams = append(teams, ts...)
45+
}
46+
47+
for _, team := range teams {
48+
value := models.Resource{
49+
ID: strconv.Itoa(team.Id),
50+
Name: team.Name,
51+
Description: model.TeamDescription{
52+
Organization: team.Organization.Name,
53+
Slug: team.Slug,
54+
Name: team.Name,
55+
ID: team.Id,
56+
NodeID: team.NodeId,
57+
Description: team.Description,
58+
CreatedAt: team.CreatedAt,
59+
UpdatedAt: team.UpdatedAt,
60+
CombinedSlug: team.CombinedSlug,
61+
ParentTeam: struct {
62+
Id int
63+
NodeId string
64+
Name string
65+
Slug string
66+
}{Id: team.ParentTeam.Id, NodeId: team.ParentTeam.NodeId, Name: team.ParentTeam.Name, Slug: team.ParentTeam.Slug},
67+
Privacy: team.Privacy,
68+
AncestorsTotalCount: team.Ancestors.TotalCount,
69+
ChildTeamsTotalCount: team.ChildTeams.TotalCount,
70+
DiscussionsTotalCount: team.Discussions.TotalCount,
71+
InvitationsTotalCount: team.Invitations.TotalCount,
72+
MembersTotalCount: team.Members.TotalCount,
73+
ProjectsV2TotalCount: team.ProjectsV2.TotalCount,
74+
RepositoriesTotalCount: team.Repositories.TotalCount,
75+
URL: team.Url,
76+
DiscussionsURL: team.DiscussionsUrl,
77+
MembersURL: team.MembersUrl,
78+
NewTeamURL: team.NewTeamUrl,
79+
RepositoriesURL: team.RepositoriesUrl,
80+
TeamsURL: team.TeamsUrl,
81+
Subscription: team.Subscription,
82+
OrganizationID: team.Organization.Id,
83+
},
84+
}
85+
if stream != nil {
86+
if err := (*stream)(value); err != nil {
87+
return nil, err
88+
}
89+
} else {
90+
values = append(values, value)
91+
}
92+
}
93+
94+
return values, nil
95+
}

discovery/describers/team_member.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package describers
22

33
import (
44
"context"
5-
"strconv"
6-
"strings"
7-
85
"github.com/opengovern/og-describer-github/discovery/pkg/models"
96
model "github.com/opengovern/og-describer-github/discovery/provider"
107
"github.com/shurcooL/githubv4"
118
steampipemodels "github.com/turbot/steampipe-plugin-github/github/models"
9+
"strconv"
10+
"strings"
1211
)
1312

1413
func GetAllTeamsMembers(ctx context.Context, githubClient model.GitHubClient, organizationName string, stream *models.StreamSender) ([]models.Resource, error) {
@@ -65,11 +64,20 @@ func tableGitHubTeamMemberList(ctx context.Context, githubClient model.GitHubCli
6564
value := models.Resource{
6665
ID: strconv.Itoa(member.Node.Id),
6766
Name: member.Node.Name,
68-
Description: model.TeamMembersDescription{
69-
User: member.Node,
70-
Organization: org,
71-
Slug: slug,
72-
Role: member.Role,
67+
Description: model.TeamMemberDescription{
68+
Company: member.Node.Company,
69+
CreatedAt: member.Node.CreatedAt.Time,
70+
Email: member.Node.Email,
71+
ID: member.Node.Id,
72+
InteractionAbility: member.Node.InteractionAbility,
73+
IsSiteAdmin: member.Node.IsSiteAdmin,
74+
Location: member.Node.Location,
75+
Login: member.Node.Login,
76+
LoginID: member.Node.Login,
77+
Name: member.Node.Name,
78+
NodeID: member.Node.NodeId,
79+
Organization: org,
80+
Role: string(member.Role),
7381
},
7482
}
7583
if stream != nil {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package describers
2+
3+
import (
4+
"context"
5+
"github.com/opengovern/og-describer-github/discovery/pkg/models"
6+
model "github.com/opengovern/og-describer-github/discovery/provider"
7+
"github.com/shurcooL/githubv4"
8+
steampipemodels "github.com/turbot/steampipe-plugin-github/github/models"
9+
"strconv"
10+
"strings"
11+
)
12+
13+
func GetAllTeamsRepositories(ctx context.Context, githubClient model.GitHubClient, organizationName string, stream *models.StreamSender) ([]models.Resource, error) {
14+
client := githubClient.RestClient
15+
teams, err := getTeams(ctx, client)
16+
if err != nil {
17+
return nil, nil
18+
}
19+
var values []models.Resource
20+
for _, team := range teams {
21+
teamValues, err := GetTeamRepositories(ctx, githubClient, organizationName, stream, team.GetOrganization().GetLogin(), team.GetSlug(), team.GetID())
22+
if err != nil {
23+
return nil, err
24+
}
25+
values = append(values, teamValues...)
26+
}
27+
return values, nil
28+
}
29+
30+
func GetTeamRepositories(ctx context.Context, githubClient model.GitHubClient, organizationName string, stream *models.StreamSender, org, slug string, teamID int64) ([]models.Resource, error) {
31+
client := githubClient.GraphQLClient
32+
var query struct {
33+
RateLimit steampipemodels.RateLimit
34+
Organization struct {
35+
Team struct {
36+
Repositories struct {
37+
TotalCount int
38+
PageInfo steampipemodels.PageInfo
39+
Edges []steampipemodels.TeamRepositoryWithPermission
40+
} `graphql:"repositories(first: $pageSize, after: $cursor)"`
41+
} `graphql:"team(slug: $slug)"`
42+
} `graphql:"organization(login: $login)"`
43+
}
44+
variables := map[string]interface{}{
45+
"login": githubv4.String(org),
46+
"slug": githubv4.String(slug),
47+
"pageSize": githubv4.Int(teamMembersPageSize),
48+
"cursor": (*githubv4.String)(nil),
49+
}
50+
appendRepoColumnIncludes(&variables, teamRepositoriesCols())
51+
var values []models.Resource
52+
for {
53+
err := client.Query(ctx, &query, variables)
54+
if err != nil {
55+
if strings.Contains(err.Error(), "Could not resolve to an Organization with the login of") {
56+
return nil, nil
57+
}
58+
return nil, err
59+
}
60+
for _, repo := range query.Organization.Team.Repositories.Edges {
61+
value := models.Resource{
62+
ID: strconv.Itoa(repo.Node.Id),
63+
Name: repo.Node.Name,
64+
Description: model.TeamRepositoryDescription{
65+
TeamID: int(teamID),
66+
RepositoryFullName: repo.Node.NameWithOwner,
67+
Permission: string(repo.Permission),
68+
CreatedAt: repo.Node.CreatedAt.Time,
69+
UpdatedAt: repo.Node.UpdatedAt.Time,
70+
},
71+
}
72+
if stream != nil {
73+
if err := (*stream)(value); err != nil {
74+
return nil, err
75+
}
76+
} else {
77+
values = append(values, value)
78+
}
79+
}
80+
if !query.Organization.Team.Repositories.PageInfo.HasNextPage {
81+
break
82+
}
83+
variables["cursor"] = githubv4.NewString(query.Organization.Team.Repositories.PageInfo.EndCursor)
84+
}
85+
return values, nil
86+
}

0 commit comments

Comments
 (0)