Skip to content

Commit

Permalink
Allow default branch to be set to master/main on update, using a new …
Browse files Browse the repository at this point in the history
…github_branch_default resource (integrations#194)

* Added github_branch_default resource

* Fix branch_default example in docs
  • Loading branch information
liamg authored Nov 24, 2020
1 parent 24f3541 commit 421abfc
Show file tree
Hide file tree
Showing 6 changed files with 303 additions and 1 deletion.
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,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
53 changes: 53 additions & 0 deletions website/docs/r/branch_default.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
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

```hcl
resource "github_repository" "example" {
name = "example"
description = "My awesome codebase"
private = true
template {
owner = "github"
repository = "terraform-module-template"
}
}
resource "github_branch" "development" {
repository = github_repository.example.name
branch = "development"
}
resource "github_branch_default" "default"{
repository = github_repository.example.name
branch = github_branch.development.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

0 comments on commit 421abfc

Please sign in to comment.