Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add table github_actions_repository_runner closes #140 #141

Merged
merged 7 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/tables/github_actions_repository_runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Table: github_actions_repository_runner

A runner is a server that runs your workflows when they're triggered. Each runner can run a single job at a time. Self-hosted runners offer more control of hardware, operating system, and software tools than GitHub-hosted runners provide.

The `github_actions_repository_runner` table can be used to query information about any self-hosted runner, and **you must specify which repository** in the where or join clause using the `repository_full_name` column.

## Examples

### List runners

```sql
select
*
from
github_actions_repository_runner
where
repository_full_name = 'turbot/steampipe';
```

### List runners with mac operating system

```sql
select
repository_full_name,
id,
name,
os
from
github_actions_repository_runner
where
repository_full_name = 'turbot/steampipe' and os = 'macos';
```

### List runners which are in use currently

```sql
select
repository_full_name,
id,
name,
os,
busy
from
github_actions_repository_runner
where
repository_full_name = 'turbot/steampipe' and busy;
```
67 changes: 34 additions & 33 deletions github/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,41 @@ func Plugin(ctx context.Context) *plugin.Plugin {
},
DefaultTransform: transform.FromGo(),
TableMap: map[string]*plugin.Table{
"github_actions_repository_runner": tableGitHubActionsRepositoryRunner(ctx),
"github_actions_repository_secret": tableGitHubActionsRepositorySecret(ctx),
"github_branch": tableGitHubBranch(ctx),
"github_branch_protection": tableGitHubBranchProtection(ctx),
"github_commit": tableGitHubCommit(ctx),
"github_community_profile": tableGitHubCommunityProfile(ctx),
"github_gist": tableGitHubGist(),
"github_gitignore": tableGitHubGitignore(),
"github_issue": tableGitHubIssue(),
"github_license": tableGitHubLicense(),
"github_my_gist": tableGitHubMyGist(),
"github_my_issue": tableGitHubMyIssue(),
"github_my_organization": tableGitHubMyOrganization(),
"github_my_repository": tableGitHubMyRepository(),
"github_my_star": tableGitHubMyStar(),
"github_my_team": tableGitHubMyTeam(),
"github_organization": tableGitHubOrganization(),
"github_pull_request": tableGitHubPullRequest(),
"github_rate_limit": tableGitHubRateLimit(ctx),
"github_release": tableGitHubRelease(ctx),
"github_repository": tableGitHubRepository(),
"github_search_code": tableGitHubSearchCode(ctx),
"github_search_commit": tableGitHubSearchCommit(ctx),
"github_search_issue": tableGitHubSearchIssue(ctx),
"github_search_label": tableGitHubSearchLable(ctx),
"github_search_pull_request": tableGitHubSearchPullRequest(ctx),
"github_search_repository": tableGitHubSearchRepository(ctx),
"github_search_topic": tableGitHubSearchTopic(ctx),
"github_search_user": tableGitHubSearchUser(ctx),
"github_stargazer": tableGitHubStargazer(ctx),
"github_tag": tableGitHubTag(ctx),
"github_traffic_view_daily": tableGitHubTrafficViewDaily(ctx),
"github_traffic_view_weekly": tableGitHubTrafficViewWeekly(ctx),
"github_user": tableGitHubUser(),
"github_workflow": tableGitHubWorkflow(ctx),
"github_branch": tableGitHubBranch(ctx),
"github_branch_protection": tableGitHubBranchProtection(ctx),
"github_commit": tableGitHubCommit(ctx),
"github_community_profile": tableGitHubCommunityProfile(ctx),
"github_gist": tableGitHubGist(),
"github_gitignore": tableGitHubGitignore(),
"github_issue": tableGitHubIssue(),
"github_license": tableGitHubLicense(),
"github_my_gist": tableGitHubMyGist(),
"github_my_issue": tableGitHubMyIssue(),
"github_my_organization": tableGitHubMyOrganization(),
"github_my_repository": tableGitHubMyRepository(),
"github_my_star": tableGitHubMyStar(),
"github_my_team": tableGitHubMyTeam(),
"github_organization": tableGitHubOrganization(),
"github_pull_request": tableGitHubPullRequest(),
"github_rate_limit": tableGitHubRateLimit(ctx),
"github_release": tableGitHubRelease(ctx),
"github_repository": tableGitHubRepository(),
"github_search_code": tableGitHubSearchCode(ctx),
"github_search_commit": tableGitHubSearchCommit(ctx),
"github_search_issue": tableGitHubSearchIssue(ctx),
"github_search_label": tableGitHubSearchLable(ctx),
"github_search_pull_request": tableGitHubSearchPullRequest(ctx),
"github_search_repository": tableGitHubSearchRepository(ctx),
"github_search_topic": tableGitHubSearchTopic(ctx),
"github_search_user": tableGitHubSearchUser(ctx),
"github_stargazer": tableGitHubStargazer(ctx),
"github_tag": tableGitHubTag(ctx),
"github_traffic_view_daily": tableGitHubTrafficViewDaily(ctx),
"github_traffic_view_weekly": tableGitHubTrafficViewWeekly(ctx),
"github_user": tableGitHubUser(),
"github_workflow": tableGitHubWorkflow(ctx),
},
}
return p
Expand Down
140 changes: 140 additions & 0 deletions github/table_github_actions_repository_runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package github

import (
"context"

"github.com/google/go-github/v33/github"

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

//// TABLE DEFINITION

func tableGitHubActionsRepositoryRunner(ctx context.Context) *plugin.Table {
return &plugin.Table{
Name: "github_actions_repository_runner",
Description: "The runner is the application that runs a job from a GitHub Actions workflow",
List: &plugin.ListConfig{
KeyColumns: plugin.SingleColumn("repository_full_name"),
ShouldIgnoreError: isNotFoundError([]string{"404"}),
Hydrate: tableGitHubRunnerList,
},
Get: &plugin.GetConfig{
KeyColumns: plugin.AllColumns([]string{"repository_full_name", "id"}),
ShouldIgnoreError: isNotFoundError([]string{"404"}),
Hydrate: tableGitHubRunnerGet,
},
Columns: []*plugin.Column{
// Top columns
{Name: "repository_full_name", Type: proto.ColumnType_STRING, Transform: transform.FromQual("repository_full_name"), Description: "Full name of the repository that contains the runners."},
{Name: "id", Type: proto.ColumnType_INT, Transform: transform.FromGo(), Description: "The unique identifier of the runner."},
{Name: "name", Type: proto.ColumnType_STRING, Description: "The name of the runner."},
{Name: "os", Type: proto.ColumnType_STRING, Transform: transform.FromField("OS"), Description: "The operating system of the runner."},
{Name: "status", Type: proto.ColumnType_STRING, Description: "The status of the runner."},
{Name: "busy", Type: proto.ColumnType_BOOL, Description: "Indicates wheather the runner is currently in use or not."},
{Name: "labels", Type: proto.ColumnType_JSON, Description: "Labels represents a collection of labels attached to each runner."},
},
}
}

//// LIST FUNCTION

func tableGitHubRunnerList(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
client := connect(ctx, d)

orgName := d.KeyColumnQuals["repository_full_name"].GetStringValue()
owner, repo := parseRepoFullName(orgName)

type ListPageResponse struct {
runners *github.Runners
resp *github.Response
}

opts := &github.ListOptions{PerPage: 100}

limit := d.QueryContext.Limit
if limit != nil {
if *limit < int64(opts.PerPage) {
opts.PerPage = int(*limit)
}
}

listPage := func(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
runners, resp, err := client.Actions.ListRunners(ctx, owner, repo, opts)
return ListPageResponse{
runners: runners,
resp: resp,
}, err
}

for {
listPageResponse, err := plugin.RetryHydrate(ctx, d, h, listPage, &plugin.RetryConfig{ShouldRetryError: shouldRetryError})
if err != nil {
return nil, err
}

listResponse := listPageResponse.(ListPageResponse)
runners := listResponse.runners
resp := listResponse.resp

for _, i := range runners.Runners {
if i != nil {
d.StreamListItem(ctx, i)
}

// Context can be cancelled due to manual cancellation or the limit has been hit
if d.QueryStatus.RowsRemaining(ctx) == 0 {
return nil, nil
}
}

if resp.NextPage == 0 {
break
}

opts.Page = resp.NextPage
}

return nil, nil
}

//// HYDRATE FUNCTIONS

func tableGitHubRunnerGet(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
runnerId := d.KeyColumnQuals["id"].GetInt64Value()
orgName := d.KeyColumnQuals["repository_full_name"].GetStringValue()

// Empty check for the parameter
if runnerId == 0 || orgName == "" {
return nil, nil
}

owner, repo := parseRepoFullName(orgName)
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
plugin.Logger(ctx).Trace("tableGitHubRunnerGet", "owner", owner, "repo", repo, "runnerId", runnerId)

client := connect(ctx, d)

type GetResponse struct {
runner *github.Runner
resp *github.Response
}

getDetails := func(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
detail, resp, err := client.Actions.GetRunner(ctx, owner, repo, runnerId)
return GetResponse{
runner: detail,
resp: resp,
}, err
}

getResponse, err := plugin.RetryHydrate(ctx, d, h, getDetails, &plugin.RetryConfig{ShouldRetryError: shouldRetryError})
if err != nil {
return nil, err
}

getResp := getResponse.(GetResponse)

return getResp.runner, nil
}