From 0fd055c7118c44336f49d98a850c79e7c7529acb Mon Sep 17 00:00:00 2001 From: Jeremy Udit Date: Mon, 9 Nov 2020 08:19:42 -0500 Subject: [PATCH] Resolve repository name to node ID if provided (#593) --- github/resource_github_branch_protection.go | 2 +- .../resource_github_branch_protection_test.go | 4 +- github/util_v4_branch_protection.go | 7 +++- github/util_v4_repository.go | 39 ++++++++++++++++++- .../docs/r/branch_protection.html.markdown | 13 +++++-- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/github/resource_github_branch_protection.go b/github/resource_github_branch_protection.go index 8dd0c79ef3..feaa23b002 100644 --- a/github/resource_github_branch_protection.go +++ b/github/resource_github_branch_protection.go @@ -21,7 +21,7 @@ func resourceGithubBranchProtection() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - Description: "", + Description: "Node ID or name of repository", }, PROTECTION_PATTERN: { Type: schema.TypeString, diff --git a/github/resource_github_branch_protection_test.go b/github/resource_github_branch_protection_test.go index a1dc029891..0adb43467a 100644 --- a/github/resource_github_branch_protection_test.go +++ b/github/resource_github_branch_protection_test.go @@ -210,8 +210,8 @@ func TestAccGithubBranchProtection(t *testing.T) { resource "github_branch_protection" "test" { - repository_id = github_repository.test.node_id - pattern = "main" + repository_id = github_repository.test.name + pattern = "main" push_restrictions = [ data.github_user.test.node_id, diff --git a/github/util_v4_branch_protection.go b/github/util_v4_branch_protection.go index f7b601740d..55e7fed398 100644 --- a/github/util_v4_branch_protection.go +++ b/github/util_v4_branch_protection.go @@ -3,6 +3,7 @@ package github import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/shurcooL/githubv4" ) @@ -68,7 +69,11 @@ func branchProtectionResourceData(d *schema.ResourceData, meta interface{}) (Bra data := BranchProtectionResourceData{} if v, ok := d.GetOk(REPOSITORY_ID); ok { - data.RepositoryID = v.(string) + repoID, err := getRepositoryID(v.(string), meta) + if err != nil { + return data, err + } + data.RepositoryID = repoID.(string) } if v, ok := d.GetOk(PROTECTION_PATTERN); ok { diff --git a/github/util_v4_repository.go b/github/util_v4_repository.go index 3866e04676..494e5fadea 100644 --- a/github/util_v4_repository.go +++ b/github/util_v4_repository.go @@ -2,10 +2,22 @@ package github import ( "context" + "github.com/shurcooL/githubv4" ) func getRepositoryID(name string, meta interface{}) (githubv4.ID, error) { + + // Interperet `name` as a node ID and return + exists, err := repositoryNodeIDExists(name, meta) + if exists { + return githubv4.ID(name), nil + } + if err != nil { + return nil, err + } + + // Resolve `name` to a node ID and return var query struct { Repository struct { ID githubv4.ID @@ -17,10 +29,35 @@ func getRepositoryID(name string, meta interface{}) (githubv4.ID, error) { } ctx := context.Background() client := meta.(*Owner).v4client - err := client.Query(ctx, &query, variables) + err = client.Query(ctx, &query, variables) if err != nil { return nil, err } return query.Repository.ID, nil } + +func repositoryNodeIDExists(name string, meta interface{}) (bool, error) { + // Quick check for node ID length + if len(name) != 32 { + return false, nil + } + + // API check if node ID exists + var query struct { + Node struct { + ID githubv4.ID + } `graphql:"node(id:$id)"` + } + variables := map[string]interface{}{ + "id": githubv4.ID(name), + } + ctx := context.Background() + client := meta.(*Owner).v4client + err := client.Query(ctx, &query, variables) + if err != nil { + return false, err + } + + return query.Node.ID.(string) == name, nil +} diff --git a/website/docs/r/branch_protection.html.markdown b/website/docs/r/branch_protection.html.markdown index 9033028c38..2269cba049 100644 --- a/website/docs/r/branch_protection.html.markdown +++ b/website/docs/r/branch_protection.html.markdown @@ -17,8 +17,13 @@ This resource allows you to configure branch protection for repositories in your # Protect the master branch of the foo repository. Additionally, require that # the "ci/travis" context to be passing and only allow the engineers team merge # to the branch. + resource "github_branch_protection" "example" { - repository_id = github_repository.example.node_id + + repository_id = github_repository.example.node_id + # also accepts repository name + # repository_id = github_repository.example.name + pattern = "main" enforce_admins = true @@ -37,8 +42,10 @@ resource "github_branch_protection" "example" { push_restrictions = [ data.github_user.example.node_id, - github_team.example.node_id, + # limited to a list of one type of restriction (user, team, app) + # github_team.example.node_id ] + } resource "github_user" "example" { @@ -60,7 +67,7 @@ resource "github_team_repository" "example" { The following arguments are supported: -* `repository_id` - (Required) The repository associated with this branch protection rule. +* `repository_id` - (Required) The name or node ID of the repository associated with this branch protection rule. * `pattern` - (Required) Identifies the protection rule pattern. * `enforce_admins` - (Optional) Boolean, setting this to `true` enforces status checks for repository administrators. * `require_signed_commits` - (Optional) Boolean, setting this to `true` requires all commits to be signed with GPG.