From 00a35ac6e45429cd12bd769a6feb313bf1f45b6a Mon Sep 17 00:00:00 2001 From: Wally Guzman <3623426+WallyGuzman@users.noreply.github.com> Date: Mon, 20 Jul 2026 22:51:10 -0500 Subject: [PATCH] Add table github_actions_cache - Follow documentation and logic from github_actions_cache - Add optional filters for key and ref --- docs/tables/github_actions_cache.md | 110 +++++++++++++++++++++++++++ github/plugin.go | 1 + github/table_github_actions_cache.go | 89 ++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 docs/tables/github_actions_cache.md create mode 100644 github/table_github_actions_cache.go diff --git a/docs/tables/github_actions_cache.md b/docs/tables/github_actions_cache.md new file mode 100644 index 0000000..296db18 --- /dev/null +++ b/docs/tables/github_actions_cache.md @@ -0,0 +1,110 @@ +--- +title: "Steampipe Table: github_actions_cache - Query GitHub Actions Caches using SQL" +description: "Allows users to query GitHub Actions Caches, providing insights into the caches generated by GitHub Actions workflows." +folder: "Actions" +--- + +# Table: github_actions_cache - Query GitHub Actions Caches using SQL + +GitHub Actions Caches are the files created to persist data to re-use in your workflows. These caches allow you to persist data after a job has completed and share that data with another job in the same workflow. + +## Table Usage Guide + +The `github_actions_cache` table provides insights into caches generated by GitHub Actions workflows. As a software developer or DevOps engineer, explore cache-specific details through this table, including metadata, size, versions, and timestamps. + +To query this table using a [fine-grained access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token), the following permissions are required: + - Repository permissions: + - Actions (Read-only): Required to access all columns. + - Metadata (Read-only): Required to access general repository metadata. + +**Important Notes** +- You must specify the `repository_full_name` column in `where` or `join` clause to query the table. + +## Examples + +### List caches +Explore which caches are associated with the 'turbot/steampipe' repository on GitHub. This can be useful for developers needing to understand or manage the resources related to this specific project. + +```sql+postgres +select + * +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe'; +``` + +```sql+sqlite +select + * +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe'; +``` + +### List caches on branch +Discover the caches within a specific repository on a branch, which is useful in scenarios where you need to track and manage these caches for ongoing workflows. + +```sql+postgres +select + id, + key, + version, + created_at, + last_accessed_at, + size_in_bytes +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe' + and ref = 'refs/heads/develop'; +``` + +```sql+sqlite +select + id, + key, + version, + created_at, + last_accessed_at, + size_in_bytes +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe' + and ref = 'refs/heads/develop'; +``` + +### List caches matching key regex +Discover the caches that match a pattern based on developer-defined key. + +```sql+postgres +select + id, + key, + version, + created_at, + last_accessed_at, + size_in_bytes +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe' + and key like 'codeql-%'; +``` + +```sql+sqlite +select + id, + key, + version, + created_at, + last_accessed_at, + size_in_bytes +from + github_actions_cache +where + repository_full_name = 'turbot/steampipe' + and key like 'codeql-%'; +``` \ No newline at end of file diff --git a/github/plugin.go b/github/plugin.go index 9a7e3cc..ad5c0c0 100644 --- a/github/plugin.go +++ b/github/plugin.go @@ -24,6 +24,7 @@ func Plugin(ctx context.Context) *plugin.Plugin { DefaultRetryConfig: retryConfig(), TableMap: map[string]*plugin.Table{ "github_actions_artifact": tableGitHubActionsArtifact(), + "github_actions_cache": tableGitHubActionsCache(), "github_actions_environment_variable": tableGitHubActionsEnvironmentVariable(), "github_actions_organization_variable": tableGitHubActionsOrganizationVariable(), "github_actions_repository_runner": tableGitHubActionsRepositoryRunner(), diff --git a/github/table_github_actions_cache.go b/github/table_github_actions_cache.go new file mode 100644 index 0000000..de4e8d0 --- /dev/null +++ b/github/table_github_actions_cache.go @@ -0,0 +1,89 @@ +package github + +import ( + "context" + + "github.com/google/go-github/v55/github" + + "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 tableGitHubActionsCache() *plugin.Table { + return &plugin.Table{ + Name: "github_actions_cache", + Description: "Caches are a built-in storage mechanism to speed up jobs in a workflow by persisting data for re-use.", + List: &plugin.ListConfig{ + KeyColumns: []*plugin.KeyColumn{ + {Name: "repository_full_name", Require: plugin.Required}, + {Name: "key", Require: plugin.Optional}, + {Name: "ref", Require: plugin.Optional}, + }, + ShouldIgnoreError: isNotFoundError([]string{"404"}), + Hydrate: tableGitHubCacheList, + }, + Columns: commonColumns([]*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 cache."}, + {Name: "id", Type: proto.ColumnType_INT, Description: "Unique ID of the cache."}, + {Name: "key", Type: proto.ColumnType_STRING, Description: "Developer-defined string identifier of the cache."}, + + // Other columns + {Name: "ref", Type: proto.ColumnType_STRING, Description: "The git reference of the cache."}, + {Name: "version", Type: proto.ColumnType_STRING, Description: "Hash generated from combination of compression tool, runner OS, and path."}, + {Name: "last_accessed_at", Type: proto.ColumnType_TIMESTAMP, Transform: transform.FromField("LastAccessedAt").Transform(convertTimestamp), Description: "Time of the most recent cache access."}, + {Name: "created_at", Type: proto.ColumnType_TIMESTAMP, Transform: transform.FromField("CreatedAt").Transform(convertTimestamp), Description: "Time when the cache was created."}, + {Name: "size_in_bytes", Type: proto.ColumnType_INT, Description: "Size of the cache in bytes."}, + }), + } +} + +func tableGitHubCacheList(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + client := connect(ctx, d) + + fullName := d.EqualsQuals["repository_full_name"].GetStringValue() + owner, repo := parseRepoFullName(fullName) + opts := &github.ActionsCacheListOptions{ + ListOptions: github.ListOptions{PerPage: 100}, + } + if key := d.EqualsQualString("key"); key != "" { + opts.Key = github.String(key) + } + if ref := d.EqualsQualString("ref"); ref != "" { + opts.Ref = github.String(ref) + } + + limit := d.QueryContext.Limit + if limit != nil { + if *limit < int64(opts.PerPage) { + opts.PerPage = int(*limit) + } + } + + for { + caches, resp, err := client.Actions.ListCaches(ctx, owner, repo, opts) + if err != nil { + return nil, err + } + + for _, i := range caches.ActionsCaches { + if i != nil { + d.StreamListItem(ctx, i) + } + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + + if resp.NextPage == 0 { + break + } + + opts.Page = resp.NextPage + } + + return nil, nil +}