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

Allow default branch to be set to master/main on update, using a new github_branch_default resource #194

Merged
merged 3 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func Provider() terraform.ResourceProvider {
"github_user_gpg_key": resourceGithubUserGpgKey(),
"github_user_invitation_accepter": resourceGithubUserInvitationAccepter(),
"github_user_ssh_key": resourceGithubUserSshKey(),
"github_branch_default": resourceGithubBranchDefault(),
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down
126 changes: 126 additions & 0 deletions github/resource_github_branch_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package github

import (
"context"
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func resourceGithubBranchDefault() *schema.Resource {
return &schema.Resource{
Create: resourceGithubBranchDefaultCreate,
Read: resourceGithubBranchDefaultRead,
Delete: resourceGithubBranchDefaultDelete,
Update: resourceGithubBranchDefaultUpdate,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"branch": {
Type: schema.TypeString,
Required: true,
},
"repository": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

func resourceGithubBranchDefaultCreate(d *schema.ResourceData, meta interface{}) error {

client := meta.(*Owner).v3client
owner := meta.(*Owner).name
repoName := d.Get("repository").(string)
defaultBranch := d.Get("branch").(string)

ctx := context.Background()

repository, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return err
}

repository.DefaultBranch = &defaultBranch

log.Printf("[DEBUG] Creating branch default: %s (%s/%s)", defaultBranch, owner, repoName)
if _, _, err := client.Repositories.Edit(ctx, owner, repoName, repository); err != nil {
return err
}

d.SetId(repoName)

return resourceGithubBranchDefaultRead(d, meta)
}

func resourceGithubBranchDefaultRead(d *schema.ResourceData, meta interface{}) error {

client := meta.(*Owner).v3client
owner := meta.(*Owner).name
repoName := d.Id()

ctx := context.WithValue(context.Background(), ctxId, d.Id())

repository, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return err
}

if repository.DefaultBranch == nil {
d.SetId("")
return nil
}

d.Set("branch", *repository.DefaultBranch)
d.Set("repository", *repository.Name)
return nil
}

func resourceGithubBranchDefaultDelete(d *schema.ResourceData, meta interface{}) error {

client := meta.(*Owner).v3client
owner := meta.(*Owner).name
repoName := d.Id()
defaultBranch := d.Get("branch").(string)

ctx := context.Background()

repository, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return err
}

repository.DefaultBranch = nil

log.Printf("[DEBUG] Removing branch default: %s (%s/%s)", defaultBranch, owner, repoName)
_, _, err = client.Repositories.Edit(ctx, owner, repoName, repository)
return err
}

func resourceGithubBranchDefaultUpdate(d *schema.ResourceData, meta interface{}) error {

client := meta.(*Owner).v3client
owner := meta.(*Owner).name
repoName := d.Id()
defaultBranch := d.Get("branch").(string)

ctx := context.Background()

repository, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return err
}

repository.DefaultBranch = &defaultBranch

log.Printf("[DEBUG] Updating branch default: %s (%s/%s)", defaultBranch, owner, repoName)
if _, _, err := client.Repositories.Edit(ctx, owner, repoName, repository); err != nil {
return err
}

return resourceGithubBranchDefaultRead(d, meta)
}
121 changes: 121 additions & 0 deletions github/resource_github_branch_default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package github

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestAccGithubBranchDefault(t *testing.T) {

randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)

t.Run("creates and manages branch defaults", func(t *testing.T) {

config := fmt.Sprintf(`

resource "github_repository" "test" {
name = "tf-acc-test-%s"
auto_init = true
}

resource "github_branch_default" "test" {
repository = github_repository.test.name
branch = "main"
}
`, randomID)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"github_branch_default.test", "branch",
"main",
),
resource.TestCheckResourceAttr(
"github_branch_default.test", "repository",
fmt.Sprintf("tf-acc-test-%s", randomID),
),
)

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: 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)
})

})

t.Run("can be configured to override the default_branch of the repository", func(t *testing.T) {

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "tf-acc-test-%s"
default_branch = "main"
auto_init = true
}

resource "github_branch_default" "test" {
repository = github_repository.test.name
branch = "override"
}

`, randomID)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"github_branch_default.test", "branch",
"override",
),
resource.TestCheckResourceAttr(
"github_branch_default.test", "repository",
fmt.Sprintf("tf-acc-test-%s", randomID),
),
)

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: 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)
})

})
}
1 change: 1 addition & 0 deletions github/resource_github_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func resourceGithubRepository() *schema.Resource {
Optional: true,
Computed: true,
Description: "Can only be set after initial repository creation, and only if the target branch exists",
Deprecated: "Use the github_branch_default resource instead",
},
"license_template": {
Type: schema.TypeString,
Expand Down
37 changes: 37 additions & 0 deletions website/docs/r/branch_default.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
layout: "github"
page_title: "GitHub: github_branch_default"
description: |-
Provides a GitHub branch default for a given repository.
---

# github_branch_default

Provides a GitHub branch default resource.

This resource allows you to set the default branch for a given repository.

## Example Usage
liamg marked this conversation as resolved.
Show resolved Hide resolved

```hcl
# Add a collaborator to a repository
liamg marked this conversation as resolved.
Show resolved Hide resolved
resource "github_repository_collaborator" "a_repo_collaborator" {
liamg marked this conversation as resolved.
Show resolved Hide resolved
repository = "our-cool-repo"
branch = "my-default-branch"
}
```

## Argument Reference

The following arguments are supported:

* `repository` - (Required) The GitHub repository
* `branch` - (Required) The branch (e.g. `main`)

## Import

GitHub Branch Defaults can be imported using an ID made up of `repository`, e.g.

```
$ terraform import github_branch_default.branch_default my-repo
```
2 changes: 1 addition & 1 deletion website/docs/r/repository.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ The following arguments are supported:

* `license_template` - (Optional) Use the [name of the template](https://github.com/github/choosealicense.com/tree/gh-pages/_licenses) without the extension. For example, "mit" or "mpl-2.0".

* `default_branch` - (Optional) The name of the default branch of the repository. **NOTE:** This can only be set after a repository has already been created,
* `default_branch` - (Optional) (Deprecated: Use `github_branch_default` resource instead) The name of the default branch of the repository. **NOTE:** This can only be set after a repository has already been created,
and after a correct reference has been created for the target branch inside the repository. This means a user will have to omit this parameter from the
initial repository creation and create the target branch inside of the repository prior to setting this attribute.

Expand Down