diff --git a/docs/tables/github_my_repository.md b/docs/tables/github_my_repository.md index 80575a3..5af7a26 100644 --- a/docs/tables/github_my_repository.md +++ b/docs/tables/github_my_repository.md @@ -220,4 +220,27 @@ where json_extract(hook.value, '$.config.insecure_ssl') = '1' or json_extract(hook.value, '$.config.secret') is null or json_extract(hook.value, '$.config.url') not like '%https:%'; -``` \ No newline at end of file +``` + +### List repositories with custom property values +Explore custom property key/value pairs configured on repositories you can access. + +```sql+postgres +select + name_with_owner, + custom_properties +from + github_my_repository +where + custom_properties is not null; +``` + +```sql+sqlite +select + name_with_owner, + custom_properties +from + github_my_repository +where + custom_properties is not null; +``` diff --git a/docs/tables/github_repository.md b/docs/tables/github_repository.md index 480b24a..d481e04 100644 --- a/docs/tables/github_repository.md +++ b/docs/tables/github_repository.md @@ -101,4 +101,27 @@ from github_repository where full_name = 'turbot/steampipe'; -``` \ No newline at end of file +``` + +### Get custom property values for a repository +Explore the custom property key/value pairs assigned to a repository. + +```sql+postgres +select + full_name, + custom_properties +from + github_repository +where + full_name = 'my-org/my-repo'; +``` + +```sql+sqlite +select + full_name, + custom_properties +from + github_repository +where + full_name = 'my-org/my-repo'; +``` diff --git a/docs/tables/github_search_repository.md b/docs/tables/github_search_repository.md index 258c111..b51a539 100644 --- a/docs/tables/github_search_repository.md +++ b/docs/tables/github_search_repository.md @@ -136,6 +136,31 @@ where query = 'tinyspotifyr in:name created:2021-01-01..2021-01-05 fork:only'; ``` +### Get custom property values from search results +Explore custom property key/value pairs for repositories returned by a search query. + +```sql+postgres +select + name_with_owner, + custom_properties +from + github_search_repository +where + query = 'org:my-org archived:false' + and custom_properties is not null; +``` + +```sql+sqlite +select + name_with_owner, + custom_properties +from + github_search_repository +where + query = 'org:my-org archived:false' + and custom_properties is not null; +``` + ```sql+sqlite select name, diff --git a/docs/tables/github_team_repository.md b/docs/tables/github_team_repository.md index 0282d49..c653802 100644 --- a/docs/tables/github_team_repository.md +++ b/docs/tables/github_team_repository.md @@ -65,7 +65,6 @@ where organization = 'my_org' and slug = 'my-team'; ``` - ### List visible teams and repositories they have admin permissions to Explore the teams and associated repositories within your organization that have administrative permissions. This is useful to ensure appropriate access rights and maintain security within your GitHub organization. @@ -105,4 +104,32 @@ where organization = 'my_org' and slug = 'my-team' and permission = 'ADMIN'; +``` + +### List custom property values for a team's repositories +Explore custom property key/value pairs for repositories visible to a team. + +```sql+postgres +select + organization, + slug, + name, + custom_properties +from + github_team_repository +where + organization = 'my_org' + and slug = 'my-team'; +``` +```sql+sqlite +select + organization, + slug, + name, + custom_properties +from + github_team_repository +where + organization = 'my_org' + and slug = 'my-team'; ``` \ No newline at end of file diff --git a/github/table_github_repository.go b/github/table_github_repository.go index b660dab..eeedf50 100644 --- a/github/table_github_repository.go +++ b/github/table_github_repository.go @@ -19,6 +19,16 @@ func gitHubRepositoryColumns() []*plugin.Column { return append(repoColumns, sharedRepositoryColumns()...) } +func repositoryCustomPropertiesColumn() *plugin.Column { + return &plugin.Column{ + Name: "custom_properties", + Type: proto.ColumnType_JSON, + Description: "A map of custom property names and values assigned to the repository.", + Hydrate: hydrateRepositoryCustomPropertiesFromV3, + Transform: transform.FromValue(), + } +} + 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")}, @@ -94,6 +104,7 @@ func sharedRepositoryColumns() []*plugin.Column { {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."}, // Columns from v3 api - hydrates + repositoryCustomPropertiesColumn(), {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}, @@ -146,6 +157,47 @@ func tableGitHubRepositoryList(ctx context.Context, d *plugin.QueryData, h *plug return nil, nil } +type repositoryCustomPropertyValue struct { + PropertyName string `json:"property_name"` + Value interface{} `json:"value"` +} + +func hydrateRepositoryCustomPropertiesFromV3(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) + req, err := client.NewRequest("GET", "repos/"+owner+"/"+repoName+"/properties/values", nil) + if err != nil { + return nil, err + } + + var values []repositoryCustomPropertyValue + _, err = client.Do(ctx, req, &values) + if err != nil { + if strings.Contains(err.Error(), "404") { + return nil, nil + } + return nil, err + } + + if len(values) == 0 { + return nil, nil + } + + customProperties := map[string]interface{}{} + for _, v := range values { + customProperties[v.PropertyName] = v.Value + } + + return customProperties, nil +} + func hydrateRepositoryDataFromV3(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { repo, err := extractRepoFromHydrateItem(h) if err != nil {