-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathtable_github_repository.go
More file actions
218 lines (195 loc) · 19.5 KB
/
Copy pathtable_github_repository.go
File metadata and controls
218 lines (195 loc) · 19.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package github
import (
"context"
"strings"
"github.com/google/go-github/v55/github"
"github.com/shurcooL/githubv4"
"github.com/turbot/steampipe-plugin-github/github/models"
"github.com/turbot/steampipe-plugin-sdk/v6/grpc/proto"
"github.com/turbot/steampipe-plugin-sdk/v6/plugin"
"github.com/turbot/steampipe-plugin-sdk/v6/plugin/transform"
)
func gitHubRepositoryColumns() []*plugin.Column {
repoColumns := []*plugin.Column{
{Name: "full_name", Type: proto.ColumnType_STRING, Description: "The full name of the repository, including the owner and repo name.", Transform: transform.FromQual("full_name")},
}
return append(repoColumns, sharedRepositoryColumns()...)
}
func sharedRepositoryColumns() []*plugin.Column {
return []*plugin.Column{
{Name: "id", Type: proto.ColumnType_INT, Description: "The numeric ID of the repository.", Transform: transform.FromField("Id", "Node.Id")},
{Name: "node_id", Type: proto.ColumnType_STRING, Description: "The node ID of the repository.", Transform: transform.FromField("NodeId", "Node.NodeId")},
{Name: "name", Type: proto.ColumnType_STRING, Description: "The name of the repository.", Transform: transform.FromField("Name", "Node.Name")},
{Name: "allow_update_branch", Type: proto.ColumnType_BOOL, Description: "If true, a pull request head branch that is behind its base branch can always be updated even if it is not required to be up to date before merging.", Hydrate: repoHydrateAllowUpdateBranch, Transform: transform.FromValue()},
{Name: "archived_at", Type: proto.ColumnType_TIMESTAMP, Description: "Timestamp when repository was archived.", Hydrate: repoHydrateArchivedAt, Transform: transform.FromValue().NullIfZero().Transform(convertTimestamp)},
{Name: "auto_merge_allowed", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateAutoMergeAllowed, Transform: transform.FromValue(), Description: "If true, auto-merge can be enabled on pull requests in this repository."},
{Name: "code_of_conduct", Type: proto.ColumnType_JSON, Hydrate: repoHydrateCodeOfConduct, Transform: transform.FromValue().NullIfZero(), Description: "The code of conduct for this repository."},
{Name: "contact_links", Type: proto.ColumnType_JSON, Hydrate: repoHydrateContactLinks, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "List of contact links associated to the repository."},
{Name: "created_at", Type: proto.ColumnType_TIMESTAMP, Hydrate: repoHydrateCreatedAt, Transform: transform.FromValue().NullIfZero().Transform(convertTimestamp), Description: "Timestamp when the repository was created."},
{Name: "default_branch_ref", Type: proto.ColumnType_JSON, Hydrate: repoHydrateDefaultBranchRef, Transform: transform.FromValue().NullIfZero(), Description: "Default ref information."},
{Name: "delete_branch_on_merge", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateDeleteBranchOnMerge, Transform: transform.FromValue(), Description: "If true, branches are automatically deleted when merged in this repository."},
{Name: "description", Type: proto.ColumnType_STRING, Hydrate: repoHydrateDescription, Transform: transform.FromValue(), Description: "The description of the repository."},
{Name: "disk_usage", Type: proto.ColumnType_INT, Hydrate: repoHydrateDiskUsage, Transform: transform.FromValue(), Description: "Number of kilobytes this repository occupies on disk."},
{Name: "fork_count", Type: proto.ColumnType_INT, Hydrate: repoHydrateForkCount, Transform: transform.FromValue(), Description: "Number of forks there are of this repository in the whole network."},
{Name: "forking_allowed", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateForkingAllowed, Transform: transform.FromValue(), Description: "If true, repository allows forks."},
{Name: "funding_links", Type: proto.ColumnType_JSON, Hydrate: repoHydrateFundingLinks, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "The funding links for this repository."},
{Name: "has_discussions_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasDiscussionsEnabled, Transform: transform.FromValue(), Description: "If true, the repository has the Discussions feature enabled."},
{Name: "has_issues_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasIssuesEnabled, Transform: transform.FromValue(), Description: "If true, the repository has issues feature enabled."},
{Name: "has_projects_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasProjectsEnabled, Transform: transform.FromValue(), Description: "If true, the repository has the Projects feature enabled."},
{Name: "has_vulnerability_alerts_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasVulnerabilityAlertsEnabled, Transform: transform.FromValue(), Description: "If true, vulnerability alerts are enabled for the repository."},
{Name: "has_wiki_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasWikiEnabled, Transform: transform.FromValue(), Description: "If true, the repository has wiki feature enabled."},
{Name: "homepage_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateHomepageUrl, Transform: transform.FromValue(), Description: "The external URL of the repository if set."},
{Name: "interaction_ability", Type: proto.ColumnType_JSON, Hydrate: repoHydrateInteractionAbility, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "The interaction ability settings for this repository."},
{Name: "is_archived", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsArchived, Transform: transform.FromValue(), Description: "If true, the repository is unmaintained (archived)."},
{Name: "is_blank_issues_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsBlankIssuesEnabled, Transform: transform.FromValue(), Description: "If true, blank issue creation is allowed."},
{Name: "is_disabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsDisabled, Transform: transform.FromValue(), Description: "If true, this repository disabled."},
{Name: "is_empty", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsEmpty, Transform: transform.FromValue(), Description: "If true, this repository is empty."},
{Name: "is_fork", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsFork, Transform: transform.FromValue(), Description: "If true, the repository is a fork."},
{Name: "is_in_organization", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsInOrganization, Transform: transform.FromValue(), Description: "If true, repository is either owned by an organization, or is a private fork of an organization repository."},
{Name: "is_locked", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsLocked, Transform: transform.FromValue(), Description: "If true, repository is locked."},
{Name: "is_mirror", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsMirror, Transform: transform.FromValue(), Description: "If true, the repository is a mirror."},
{Name: "is_private", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsPrivate, Transform: transform.FromValue(), Description: "If true, the repository is private or internal."},
{Name: "is_security_policy_enabled", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsSecurityPolicyEnabled, Transform: transform.FromValue(), Description: "If true, repository has a security policy."},
{Name: "is_template", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsTemplate, Transform: transform.FromValue(), Description: "If true, the repository is a template that can be used to generate new repositories."},
{Name: "is_user_configuration_repository", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateIsUserConfigurationRepository, Transform: transform.FromValue(), Description: "If true, this is a user configuration repository."},
{Name: "issue_templates", Type: proto.ColumnType_JSON, Hydrate: repoHydrateIssueTemplates, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "A list of issue templates associated to the repository."},
{Name: "license_info", Type: proto.ColumnType_JSON, Hydrate: repoHydrateLicenseInfo, Transform: transform.FromValue().NullIfZero(), Description: "The license associated with the repository."},
{Name: "lock_reason", Type: proto.ColumnType_STRING, Hydrate: repoHydrateLockReason, Transform: transform.FromValue(), Description: "The reason the repository has been locked."},
{Name: "merge_commit_allowed", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateMergeCommitAllowed, Transform: transform.FromValue(), Description: "If true, PRs are merged with a merge commit on this repository."},
{Name: "merge_commit_message", Type: proto.ColumnType_STRING, Hydrate: repoHydrateMergeCommitMessage, Transform: transform.FromValue(), Description: "How the default commit message will be generated when merging a pull request."},
{Name: "merge_commit_title", Type: proto.ColumnType_STRING, Hydrate: repoHydrateMergeCommitTitle, Transform: transform.FromValue(), Description: "How the default commit title will be generated when merging a pull request."},
{Name: "mirror_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateMirrorUrl, Transform: transform.FromValue(), Description: "The repository's original mirror URL."},
{Name: "name_with_owner", Type: proto.ColumnType_STRING, Transform: transform.FromField("NameWithOwner", "Node.NameWithOwner"), Description: "The repository's name with owner."},
{Name: "open_graph_image_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateOpenGraphImageUrl, Transform: transform.FromValue(), Description: "The image used to represent this repository in Open Graph data."},
{Name: "owner_login", Type: proto.ColumnType_STRING, Transform: transform.FromField("Owner.Login", "Node.Owner.Login"), Description: "Login of the repository owner."},
{Name: "primary_language", Type: proto.ColumnType_JSON, Hydrate: repoHydratePrimaryLanguage, Transform: transform.FromValue().NullIfZero(), Description: "The primary language of the repository's code."},
{Name: "projects_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateProjectsUrl, Transform: transform.FromValue(), Description: "The URL listing the repository's projects."},
{Name: "pull_request_templates", Type: proto.ColumnType_JSON, Hydrate: repoHydratePullRequestTemplates, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "Returns a list of pull request templates associated to the repository."},
{Name: "pushed_at", Type: proto.ColumnType_TIMESTAMP, Hydrate: repoHydratePushedAt, Transform: transform.FromValue().NullIfZero().Transform(convertTimestamp), Description: "Timestamp when the repository was last pushed to."},
{Name: "rebase_merge_allowed", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateRebaseMergeAllowed, Transform: transform.FromValue(), Description: "If true, rebase-merging is enabled on this repository."},
{Name: "security_policy_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateSecurityPolicyUrl, Transform: transform.FromValue(), Description: "The security policy URL."},
{Name: "squash_merge_allowed", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateSquashMergeAllowed, Transform: transform.FromValue(), Description: "If true, squash-merging is enabled on this repository."},
{Name: "squash_merge_commit_message", Type: proto.ColumnType_STRING, Hydrate: repoHydrateSquashMergeCommitMessage, Transform: transform.FromValue(), Description: "How the default commit message will be generated when squash merging a pull request."},
{Name: "squash_merge_commit_title", Type: proto.ColumnType_STRING, Hydrate: repoHydrateSquashMergeCommitTitle, Transform: transform.FromValue(), Description: "How the default commit title will be generated when squash merging a pull request."},
{Name: "ssh_url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateSshUrl, Transform: transform.FromValue(), Description: "The SSH URL to clone this repository."},
{Name: "stargazer_count", Type: proto.ColumnType_INT, Hydrate: repoHydrateStargazerCount, Transform: transform.FromValue(), Description: "Returns a count of how many stargazers there are on this repository."},
{Name: "updated_at", Type: proto.ColumnType_TIMESTAMP, Hydrate: repoHydrateUpdatedAt, Transform: transform.FromValue().NullIfZero().Transform(convertTimestamp), Description: "Timestamp when repository was last updated."},
{Name: "url", Type: proto.ColumnType_STRING, Hydrate: repoHydrateUrl, Transform: transform.FromValue(), Description: "The URL of the repository."},
{Name: "uses_custom_open_graph_image", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateUsesCustomOpenGraphImage, Transform: transform.FromValue(), Description: "if true, this repository has a custom image to use with Open Graph as opposed to being represented by the owner's avatar."},
{Name: "can_administer", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateCanAdminister, Transform: transform.FromValue(), Description: "If true, you can administer this repository."},
{Name: "can_create_projects", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateCanCreateProjects, Transform: transform.FromValue(), Description: "If true, you can create projects in this repository."},
{Name: "can_subscribe", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateCanSubscribe, Transform: transform.FromValue(), Description: "If true, you can subscribe to this repository."},
{Name: "can_update_topics", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateCanUpdateTopics, Transform: transform.FromValue(), Description: "If true, you can update topics on this repository."},
{Name: "has_starred", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateHasStarred, Transform: transform.FromValue(), Description: "If true, you have starred this repository."},
{Name: "possible_commit_emails", Type: proto.ColumnType_JSON, Hydrate: repoHydratePossibleCommitEmails, Transform: transform.FromValue().NullIfZero().NullIfEmptySlice(), Description: "A list of emails you can commit to this repository with."},
{Name: "subscription", Type: proto.ColumnType_STRING, Hydrate: repoHydrateSubscription, Transform: transform.FromValue(), Description: "Identifies if the current user is watching, not watching, or ignoring the repository."},
{Name: "visibility", Type: proto.ColumnType_STRING, Hydrate: repoHydrateVisibility, Transform: transform.FromValue(), Description: "Indicates the repository's visibility level."},
{Name: "your_permission", Type: proto.ColumnType_STRING, Hydrate: repoHydrateYourPermission, Transform: transform.FromValue(), Description: "Your permission level on the repository. Will return null if authenticated as an GitHub App."},
{Name: "web_commit_signoff_required", Type: proto.ColumnType_BOOL, Hydrate: repoHydrateWebCommitSignoffRequired, Transform: transform.FromValue(), Description: "If true, contributors are required to sign off on web-based commits in this repository."},
{Name: "repository_topics_total_count", Type: proto.ColumnType_INT, Hydrate: repoHydrateRepositoryTopicsCount, Transform: transform.FromValue(), Description: "Count of topics associated with the repository."},
{Name: "open_issues_total_count", Type: proto.ColumnType_INT, Hydrate: repoHydrateOpenIssuesCount, Transform: transform.FromValue(), Description: "Count of issues open on the repository."},
{Name: "watchers_total_count", Type: proto.ColumnType_INT, Hydrate: repoHydrateWatchersCount, Transform: transform.FromValue(), Description: "Count of watchers on the repository."},
{Name: "custom_properties", Type: proto.ColumnType_JSON, Description: "A map of custom property names and values assigned to the repository.", Hydrate: repoHydrateRepositoryCustomPropertyValues, Transform: transform.FromValue().Transform(repositoryCustomPropertiesTransform)},
// Columns from v3 api - hydrates
{Name: "hooks", Type: proto.ColumnType_JSON, Description: "The API Hooks URL.", Hydrate: hydrateRepositoryHooksFromV3, Transform: transform.FromValue()},
{Name: "topics", Type: proto.ColumnType_JSON, Description: "The topics (similar to tags or labels) associated with the repository.", Hydrate: hydrateRepositoryDataFromV3},
{Name: "subscribers_count", Type: proto.ColumnType_INT, Description: "The number of users who have subscribed to the repository.", Hydrate: hydrateRepositoryDataFromV3},
{Name: "has_downloads", Type: proto.ColumnType_BOOL, Description: "If true, the GitHub Downloads feature is enabled on the repository.", Hydrate: hydrateRepositoryDataFromV3},
{Name: "has_pages", Type: proto.ColumnType_BOOL, Description: "If true, the GitHub Pages feature is enabled on the repository.", Hydrate: hydrateRepositoryDataFromV3},
{Name: "network_count", Type: proto.ColumnType_INT, Description: "The number of member repositories in the network.", Hydrate: hydrateRepositoryDataFromV3},
}
}
func tableGitHubRepository() *plugin.Table {
return &plugin.Table{
Name: "github_repository",
Description: "GitHub Repositories contain all of your project's files and each file's revision history.",
List: &plugin.ListConfig{
Hydrate: tableGitHubRepositoryList,
ShouldIgnoreError: isNotFoundError([]string{"404"}),
KeyColumns: plugin.SingleColumn("full_name"),
},
Columns: commonColumns(gitHubRepositoryColumns()),
}
}
func tableGitHubRepositoryList(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
client := connectV4(ctx, d)
repoFullName := d.EqualsQuals["full_name"].GetStringValue()
owner, repoName := parseRepoFullName(repoFullName)
var query struct {
RateLimit models.RateLimit
Repository models.Repository `graphql:"repository(owner: $owner, name: $name)"`
}
variables := map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(repoName),
}
appendRepoColumnIncludes(&variables, d.QueryContext.Columns)
appendUserInteractionAbilityForIssue(&variables, d.QueryContext.Columns, d)
err := client.Query(ctx, &query, variables)
plugin.Logger(ctx).Debug(rateLimitLogString("github_repository", &query.RateLimit))
if err != nil {
plugin.Logger(ctx).Error("github_repository", "api_error", err)
return nil, err
}
d.StreamListItem(ctx, query.Repository)
return nil, nil
}
func repositoryCustomPropertiesTransform(_ context.Context, input *transform.TransformData) (interface{}, error) {
values, ok := input.Value.([]models.RepositoryCustomPropertyValue)
if !ok || len(values) == 0 {
return nil, nil
}
customProperties := make(map[string]interface{}, len(values))
for _, value := range values {
customProperties[value.PropertyName] = value.Value
}
if len(customProperties) == 0 {
return nil, nil
}
return customProperties, nil
}
func hydrateRepositoryDataFromV3(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
repo, err := extractRepoFromHydrateItem(h)
if err != nil {
return nil, err
}
owner := repo.Owner.Login
repoName := repo.Name
client := connect(ctx, d)
r, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
if strings.Contains(err.Error(), "404") {
return nil, nil
}
return nil, err
}
if r == nil {
return nil, nil
}
return r, nil
}
func hydrateRepositoryHooksFromV3(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
repo, err := extractRepoFromHydrateItem(h)
if err != nil {
return nil, err
}
owner := repo.Owner.Login
repoName := repo.Name
client := connect(ctx, d)
var repositoryHooks []*github.Hook
opt := &github.ListOptions{PerPage: 100}
for {
hooks, resp, err := client.Repositories.ListHooks(ctx, owner, repoName, opt)
if err != nil && strings.Contains(err.Error(), "Not Found") {
return nil, nil
} else if err != nil {
return nil, err
}
repositoryHooks = append(repositoryHooks, hooks...)
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return repositoryHooks, nil
}