Skip to content

Commit

Permalink
Allow to get only protected on non protected branch with github_repos…
Browse files Browse the repository at this point in the history
…itory_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 <me@kfcampbell.com>
  • Loading branch information
bpaquet and kfcampbell committed Sep 23, 2022
1 parent 759426b commit 6773d80
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 28 deletions.
17 changes: 0 additions & 17 deletions github/data_source_github_repository.go
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
55 changes: 46 additions & 9 deletions github/data_source_github_repository_branches.go
Expand Up @@ -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,
Expand All @@ -36,35 +48,60 @@ 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 {
client := meta.(*Owner).v3client
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
}
79 changes: 79 additions & 0 deletions github/data_source_github_repository_branches_test.go
Expand Up @@ -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)
})
})
}
2 changes: 0 additions & 2 deletions website/docs/d/repository.html.markdown
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions website/docs/d/repository_branches.html.markdown
Expand Up @@ -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:
Expand Down

0 comments on commit 6773d80

Please sign in to comment.