Skip to content

Commit

Permalink
Update github_license table to use GraphQL API closes #236 (#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
graza-io authored May 2, 2023
1 parent 1002b4a commit 78cff7e
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 56 deletions.
45 changes: 45 additions & 0 deletions docs/tables/github_license.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,48 @@ group by
order by
num_repos desc;
```

### View conditions for a specific license

```sql
select
name,
key,
c ->> 'Key' as condition,
c ->> 'Description' as condition_desc
from
github_license,
jsonb_array_elements(conditions) as c
where
key = 'gpl-3.0';
```

### View limitations for a specific license

```sql
select
name,
key,
l ->> 'Key' as limitation,
l ->> 'Description' as limitation_desc
from
github_license,
jsonb_array_elements(limitations) as l
where
key = 'gpl-3.0';
```

### View permissions for a specific license

```sql
select
name,
key,
p ->> 'Key' as permission,
p ->> 'Description' as permission_desc
from
github_license,
jsonb_array_elements(permissions) as p
where
key = 'gpl-3.0';
```
108 changes: 52 additions & 56 deletions github/table_github_license.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package github

import (
"context"

"github.com/google/go-github/v48/github"
"github.com/shurcooL/githubv4"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"

"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
)

//// TABLE DEFINITION
Expand All @@ -27,53 +26,67 @@ func tableGitHubLicense() *plugin.Table {
Columns: []*plugin.Column{

// Top columns
{Name: "spdx_id", Description: "The Software Package Data Exchange (SPDX) id of the license.", Type: proto.ColumnType_STRING, Transform: transform.FromField("SPDXID")},
{Name: "spdx_id", Description: "The Software Package Data Exchange (SPDX) id of the license.", Type: proto.ColumnType_STRING, Transform: transform.FromField("SpdxId")},
{Name: "name", Description: "The name of the license.", Type: proto.ColumnType_STRING},
{Name: "html_url", Description: "The HTML URL of the license.", Type: proto.ColumnType_STRING, Hydrate: tableGitHubLicenseGetData},
{Name: "html_url", Description: "The HTML URL of the license.", Type: proto.ColumnType_STRING, Transform: transform.FromField("Url")},

// The body is huge and of limited value, exclude it for now
// {Name: "body", Type: proto.ColumnType_STRING, Hydrate: tableGitHubLicenseGetData},
{Name: "conditions", Description: "An array of license conditions (include-copyright,disclose-source, etc).", Type: proto.ColumnType_JSON, Hydrate: tableGitHubLicenseGetData},
{Name: "description", Description: "The license description.", Type: proto.ColumnType_STRING, Hydrate: tableGitHubLicenseGetData},
{Name: "featured", Description: "If true, the license is 'featured' in the GitHub UI.", Type: proto.ColumnType_BOOL, Hydrate: tableGitHubLicenseGetData},
{Name: "implementation", Description: "Implementation instructions for the license.", Type: proto.ColumnType_STRING, Hydrate: tableGitHubLicenseGetData},
{Name: "conditions", Description: "An array of license conditions (include-copyright,disclose-source, etc).", Type: proto.ColumnType_JSON},
{Name: "description", Description: "The license description.", Type: proto.ColumnType_STRING},
{Name: "featured", Description: "If true, the license is 'featured' in the GitHub UI.", Type: proto.ColumnType_BOOL},
{Name: "implementation", Description: "Implementation instructions for the license.", Type: proto.ColumnType_STRING},
{Name: "key", Description: "The unique key of the license.", Type: proto.ColumnType_STRING},
{Name: "limitations", Description: "An array of limitations for the license (trademark-use, liability,warranty, etc).", Type: proto.ColumnType_JSON, Hydrate: tableGitHubLicenseGetData},
{Name: "permissions", Description: "An array of permissions for the license (private-use, commercial-use,modifications, etc).", Type: proto.ColumnType_JSON, Hydrate: tableGitHubLicenseGetData},
{Name: "url", Description: "The API url of the license.", Type: proto.ColumnType_STRING},
{Name: "limitations", Description: "An array of limitations for the license (trademark-use, liability,warranty, etc).", Type: proto.ColumnType_JSON},
{Name: "permissions", Description: "An array of permissions for the license (private-use, commercial-use,modifications, etc).", Type: proto.ColumnType_JSON},
{Name: "nickname", Description: "The customary short name of the license.", Type: proto.ColumnType_STRING},
{Name: "pseudo_license", Description: "Indicates if the license is a pseudo-license placeholder (e.g. other, no-license).", Type: proto.ColumnType_BOOL},
},
}
}

//// LIST FUNCTION
type licenseRule struct {
Key string
Label string
Description string
}

func tableGitHubLicenseList(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
client := connect(ctx, d)
type license struct {
SpdxId string
Name string
Key string
Conditions []licenseRule
Description string
Featured bool
Implementation string
Limitations []licenseRule
Permissions []licenseRule
Url string
Nickname string
PseudoLicense bool
}

type ListPageResponse struct {
licenses []*github.License
resp *github.Response
}
var listLicensesQuery struct {
Licenses []license `graphql:"licenses"`
}

listPage := func(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
licenses, resp, err := client.Licenses.List(ctx)
return ListPageResponse{
licenses: licenses,
resp: resp,
}, err
}
var getLicenseQuery struct {
License license `graphql:"license(key: $key)"`
}

listPageResponse, err := retryHydrate(ctx, d, h, listPage)
//// LIST FUNCTION

listResponse := listPageResponse.(ListPageResponse)
licenses := listResponse.licenses
func tableGitHubLicenseList(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
client := connectV4(ctx, d)

err := client.Query(ctx, &listLicensesQuery, nil)
if err != nil {
plugin.Logger(ctx).Error("github_license", "api_error", err)
return nil, err
}

for _, i := range licenses {
d.StreamListItem(ctx, i)
for _, license := range listLicensesQuery.Licenses {
d.StreamListItem(ctx, license)

// Context can be cancelled due to manual cancellation or the limit has been hit
if d.RowsRemaining(ctx) == 0 {
Expand All @@ -84,44 +97,27 @@ func tableGitHubLicenseList(ctx context.Context, d *plugin.QueryData, h *plugin.
return nil, nil
}

//// HYDRATE FUNCTIONS
//// GET FUNCTION

func tableGitHubLicenseGetData(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
var key string
if h.Item != nil {
item := h.Item.(*github.License)
key = *item.Key
} else {
key = d.EqualsQuals["key"].GetStringValue()
}
key := d.EqualsQuals["key"].GetStringValue()

// Return nil, if no input provided
if key == "" {
return nil, nil
}

client := connect(ctx, d)

type GetResponse struct {
license *github.License
resp *github.Response
}

getDetails := func(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
license, resp, err := client.Licenses.Get(ctx, key)
return GetResponse{
license: license,
resp: resp,
}, err
variables := map[string]interface{}{
"key": githubv4.String(key),
}

getResponse, err := retryHydrate(ctx, d, h, getDetails)
client := connectV4(ctx, d)

err := client.Query(ctx, &getLicenseQuery, variables)
if err != nil {
plugin.Logger(ctx).Error("github_license", "api_error", err)
return nil, err
}
getResp := getResponse.(GetResponse)
license := getResp.license

return license, nil
return getLicenseQuery.License, nil
}

0 comments on commit 78cff7e

Please sign in to comment.