From 6773d80600f761bf50b695f475c2d457d1151ee5 Mon Sep 17 00:00:00 2001 From: Bertrand Paquet Date: Fri, 23 Sep 2022 22:26:02 +0200 Subject: [PATCH] Allow to get only protected on non protected branch with github_repository_branches (#1296) * Allow to get only protected on non protected branch with github_repository_branches Remove leftover code and doc after #1117 Reintroduce the feature from #1162 with integration tests * Add ConflicsWith * Implement pagination Co-authored-by: Keegan Campbell --- github/data_source_github_repository.go | 17 ---- .../data_source_github_repository_branches.go | 55 ++++++++++--- ..._source_github_repository_branches_test.go | 79 +++++++++++++++++++ website/docs/d/repository.html.markdown | 2 - .../docs/d/repository_branches.html.markdown | 4 + 5 files changed, 129 insertions(+), 28 deletions(-) diff --git a/github/data_source_github_repository.go b/github/data_source_github_repository.go index 2af5cc44ea..c8f2354a7b 100644 --- a/github/data_source_github_repository.go +++ b/github/data_source_github_repository.go @@ -28,12 +28,6 @@ func dataSourceGithubRepository() *schema.Resource { Computed: true, ConflictsWith: []string{"full_name"}, }, - "only_protected_branches": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "description": { Type: schema.TypeString, Default: nil, @@ -251,17 +245,6 @@ func dataSourceGithubRepositoryRead(d *schema.ResourceData, meta interface{}) er d.Set("repo_id", repo.GetID()) d.Set("has_projects", repo.GetHasProjects()) - onlyProtectedBranches := d.Get("only_protected_branches").(bool) - listBranchOptions := &github.BranchListOptions{ - Protected: &onlyProtectedBranches, - } - - branches, _, err := client.Repositories.ListBranches(context.TODO(), owner, repoName, listBranchOptions) - if err != nil { - return err - } - d.Set("branches", flattenBranches(branches)) - if repo.GetHasPages() { pages, _, err := client.Repositories.GetPagesInfo(context.TODO(), owner, repoName) if err != nil { diff --git a/github/data_source_github_repository_branches.go b/github/data_source_github_repository_branches.go index c5e2e80dd8..39dd96741e 100644 --- a/github/data_source_github_repository_branches.go +++ b/github/data_source_github_repository_branches.go @@ -16,6 +16,18 @@ func dataSourceGithubRepositoryBranches() *schema.Resource { Type: schema.TypeString, Required: true, }, + "only_protected_branches": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ConflictsWith: []string{"only_non_protected_branches"}, + }, + "only_non_protected_branches": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ConflictsWith: []string{"only_protected_branches"}, + }, "branches": { Type: schema.TypeList, Computed: true, @@ -36,20 +48,20 @@ func dataSourceGithubRepositoryBranches() *schema.Resource { } } -func flattenBranches(branches []*github.Branch) []interface{} { +func flattenBranches(branches []*github.Branch) []map[string]interface{} { + results := make([]map[string]interface{}, 0) if branches == nil { - return []interface{}{} + return results } - branchList := make([]interface{}, 0, len(branches)) for _, branch := range branches { branchMap := make(map[string]interface{}) branchMap["name"] = branch.GetName() branchMap["protected"] = branch.GetProtected() - branchList = append(branchList, branchMap) + results = append(results, branchMap) } - return branchList + return results } func dataSourceGithubRepositoryBranchesRead(d *schema.ResourceData, meta interface{}) error { @@ -57,14 +69,39 @@ func dataSourceGithubRepositoryBranchesRead(d *schema.ResourceData, meta interfa orgName := meta.(*Owner).name repoName := d.Get("repository").(string) - branches, _, err := client.Repositories.ListBranches(context.TODO(), orgName, repoName, nil) - if err != nil { - return err + onlyProtectedBranches := d.Get("only_protected_branches").(bool) + onlyNonProtectedBranches := d.Get("only_non_protected_branches").(bool) + var listBranchOptions *github.BranchListOptions + if onlyProtectedBranches { + listBranchOptions = &github.BranchListOptions{ + Protected: &onlyProtectedBranches, + } + } else if onlyNonProtectedBranches { + listBranchOptions = &github.BranchListOptions{ + Protected: &onlyProtectedBranches, + } + } else { + listBranchOptions = &github.BranchListOptions{} + } + + results := make([]map[string]interface{}, 0) + for { + branches, resp, err := client.Repositories.ListBranches(context.TODO(), orgName, repoName, listBranchOptions) + if err != nil { + return err + } + results = append(results, flattenBranches(branches)...) + + if resp.NextPage == 0 { + break + } + + listBranchOptions.Page = resp.NextPage } d.SetId(fmt.Sprintf("%s/%s", orgName, repoName)) d.Set("repository", repoName) - d.Set("branches", flattenBranches(branches)) + d.Set("branches", results) return nil } diff --git a/github/data_source_github_repository_branches_test.go b/github/data_source_github_repository_branches_test.go index bb6491bda4..84b7cedc21 100644 --- a/github/data_source_github_repository_branches_test.go +++ b/github/data_source_github_repository_branches_test.go @@ -54,4 +54,83 @@ func TestAccGithubRepositoryBranchesDataSource(t *testing.T) { testCase(t, organization) }) }) + + t.Run("manages branches of a new repository with filtering", func(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-branches-%s", acctest.RandString(5)) + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + auto_init = true + } + + resource "github_branch" "test" { + repository = github_repository.test.id + branch = "test" + } + + resource "github_branch_protection_v3" "test" { + repository = github_repository.test.name + branch = "test" + depends_on = [github_branch.test] + } + `, repoName) + + config2 := config + ` + data "github_repository_branches" "test" { + repository = github_repository.test.name + } + + data "github_repository_branches" "protected" { + repository = github_repository.test.name + only_protected_branches = true + } + + data "github_repository_branches" "non_protected" { + repository = github_repository.test.name + only_non_protected_branches = true + } + ` + + const resourceName = "data.github_repository_branches.test" + const protectedResourceName = "data.github_repository_branches.protected" + const nonProtectedResourceName = "data.github_repository_branches.non_protected" + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "branches.#", "2"), + resource.TestCheckResourceAttr(protectedResourceName, "branches.#", "1"), + resource.TestCheckResourceAttr(protectedResourceName, "branches.0.name", "test"), + resource.TestCheckResourceAttr(protectedResourceName, "branches.0.protected", "true"), + resource.TestCheckResourceAttr(nonProtectedResourceName, "branches.#", "1"), + resource.TestCheckResourceAttr(nonProtectedResourceName, "branches.0.name", "main"), + resource.TestCheckResourceAttr(nonProtectedResourceName, "branches.0.protected", "false"), + ) + + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc(), + }, + { + Config: config2, + Check: check, + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) } diff --git a/website/docs/d/repository.html.markdown b/website/docs/d/repository.html.markdown index e6f66ca205..40ac1fffd4 100644 --- a/website/docs/d/repository.html.markdown +++ b/website/docs/d/repository.html.markdown @@ -25,8 +25,6 @@ The following arguments are supported: * `full_name` - (Optional) Full name of the repository (in `org/name` format). -* `only_protected_branches` - (Optional). If true, the `branches` attributes will be populated only with protected branches. Default: `false`. - ## Attributes Reference * `node_id` - the Node ID of the repository. diff --git a/website/docs/d/repository_branches.html.markdown b/website/docs/d/repository_branches.html.markdown index c2209b9c79..9639af1d66 100644 --- a/website/docs/d/repository_branches.html.markdown +++ b/website/docs/d/repository_branches.html.markdown @@ -21,6 +21,10 @@ data "github_repository_branches" "example" { * `repository` - (Required) Name of the repository to retrieve the branches from. +* `only_protected_branches` - (Optional). If true, the `branches` attributes will be populated only with protected branches. Default: `false`. + +* `only_non_protected_branches` - (Optional). If true, the `branches` attributes will be populated only with non protected branches. Default: `false`. + ## Attributes Reference * `branches` - The list of this repository's branches. Each element of `branches` has the following attributes: