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 columns required_conversation_resolution and signatures_protected_branch to table github_branch_protection Closes #174, #175 #178

Merged
merged 7 commits into from
Aug 10, 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
30 changes: 30 additions & 0 deletions docs/tables/github_branch_protection.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,33 @@ where
repository_full_name = 'turbot/steampipe'
and name = 'main';
```

## Get repositories where coversation resolution is required for merging

```sql
select
repository_full_name,
b.name as branch_name,
signatures_protected_branch
from
github_branch_protection b
join
github_my_repository r
on r.full_name = b.repository_full_name
where required_conversation_resolution = true;
```

## Get repositories that require signed commits for merging

```sql
select
repository_full_name,
b.name as branch_name,
required_conversation_resolution
from
github_branch_protection b
join
github_my_repository r
on r.full_name = b.repository_full_name
where signatures_protected_branch = true;
```
53 changes: 53 additions & 0 deletions github/table_github_branch_protection.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ func tableGitHubBranchProtection(ctx context.Context) *plugin.Table {
{Name: "enforce_admins_enabled", Type: proto.ColumnType_BOOL, Transform: transform.FromField("EnforceAdmins.Enabled"), Description: "If true, enforce all configured restrictions for administrators."},
{Name: "allow_deletions_enabled", Type: proto.ColumnType_BOOL, Transform: transform.FromField("AllowDeletions.Enabled"), Description: "If true, allow users with push access to delete matching branches."},
{Name: "allow_force_pushes_enabled", Type: proto.ColumnType_BOOL, Transform: transform.FromField("AllowForcePushes.Enabled"), Description: "If true, permit force pushes for all users with push access."},
{Name: "required_conversation_resolution_enabled", Type: proto.ColumnType_BOOL, Transform: transform.FromField("RequiredConversationResolution.Enabled"), Description: "If enabled, requires all comments on the pull request to be resolved before it can be merged to a protected branch."},
{Name: "required_linear_history_enabled", Type: proto.ColumnType_BOOL, Transform: transform.FromField("RequireLinearHistory.Enabled"), Description: "If true, prevent merge commits from being pushed to matching branches."},
{Name: "required_status_checks", Type: proto.ColumnType_JSON, Description: "Status checks that must pass before a branch can be merged into branches matching this rule."},
{Name: "required_pull_request_reviews", Type: proto.ColumnType_JSON, Description: "Pull request reviews required before merging."},
{Name: "signatures_protected_branch_enabled", Type: proto.ColumnType_BOOL, Description: "Commits pushed to matching branches must have verified signatures.", Hydrate: repositorySignaturesProtectedBranchGet, Transform: transform.FromValue()},
},
}
}
Expand Down Expand Up @@ -102,6 +104,57 @@ func tableGitHubRepositoryBranchProtectionGet(ctx context.Context, d *plugin.Que
return nil, nil
}

func repositorySignaturesProtectedBranchGet(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
logger := plugin.Logger(ctx)
quals := d.KeyColumnQuals
fullName := quals["repository_full_name"].GetStringValue()
owner, repo := parseRepoFullName(fullName)
branchName := ""

if h.ParentItem != nil {
b := h.ParentItem.(*github.Branch)
branchName = *b.Name
} else {
branchName = quals["name"].GetStringValue()
}

logger.Trace("tableGitHubRepositoryBranchProtectionGet", "owner", owner, "repo", repo, "branchName", branchName)
client := connect(ctx, d)

type GetResponse struct {
protectedBranch *github.SignaturesProtectedBranch
}

getDetails := func(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
protectedBranch, _, err := client.Repositories.GetSignaturesProtectedBranch(ctx, owner, repo, branchName)
if err != nil {
// For private and archived repositories, users who do not have owner/admin access will get the below error
// 403 Upgrade to GitHub Pro or make this repository public to enable this feature.
// For repository owners the API will return nil if the repository is private and archived
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "Upgrade to GitHub Pro") || strings.Contains(err.Error(), "branch is not protected") {
return nil, nil
}
return nil, err
}

return GetResponse{
protectedBranch: protectedBranch,
}, err
}

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

if protectedBranch != nil {
return protectedBranch.Enabled, nil
}
return nil, nil
}

func branchNameQual(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
quals := d.KeyColumnQuals
if quals["name"] != nil {
Expand Down