From 0e1998af370bce20ea1c369afca364434008799b Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Fri, 9 Oct 2020 13:50:51 +0100 Subject: [PATCH 1/2] Added github_branch_default resource --- github/provider.go | 1 + github/resource_github_branch_default.go | 126 ++++++++++++++++++ github/resource_github_branch_default_test.go | 121 +++++++++++++++++ github/resource_github_repository.go | 1 + website/docs/r/branch_default.html.markdown | 37 +++++ website/docs/r/repository.html.markdown | 2 +- 6 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 github/resource_github_branch_default.go create mode 100644 github/resource_github_branch_default_test.go create mode 100644 website/docs/r/branch_default.html.markdown diff --git a/github/provider.go b/github/provider.go index f5d98f7f6b..23f5a4a471 100644 --- a/github/provider.go +++ b/github/provider.go @@ -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{ diff --git a/github/resource_github_branch_default.go b/github/resource_github_branch_default.go new file mode 100644 index 0000000000..893209796b --- /dev/null +++ b/github/resource_github_branch_default.go @@ -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) +} diff --git a/github/resource_github_branch_default_test.go b/github/resource_github_branch_default_test.go new file mode 100644 index 0000000000..f01b67c87b --- /dev/null +++ b/github/resource_github_branch_default_test.go @@ -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) + }) + + }) +} diff --git a/github/resource_github_repository.go b/github/resource_github_repository.go index 4845e9e40c..4bb7049f18 100644 --- a/github/resource_github_repository.go +++ b/github/resource_github_repository.go @@ -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, diff --git a/website/docs/r/branch_default.html.markdown b/website/docs/r/branch_default.html.markdown new file mode 100644 index 0000000000..2d2ff1ab95 --- /dev/null +++ b/website/docs/r/branch_default.html.markdown @@ -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 + +```hcl +# Add a collaborator to a repository +resource "github_repository_collaborator" "a_repo_collaborator" { + 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 +``` \ No newline at end of file diff --git a/website/docs/r/repository.html.markdown b/website/docs/r/repository.html.markdown index 1f9532c3f0..a743b80260 100644 --- a/website/docs/r/repository.html.markdown +++ b/website/docs/r/repository.html.markdown @@ -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. From 4365c2f8bf6c6cc62acd5d85f0ba653f80c831d9 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Sun, 11 Oct 2020 08:18:13 +0100 Subject: [PATCH 2/2] Fix branch_default example in docs --- website/docs/r/branch_default.html.markdown | 26 +++++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/website/docs/r/branch_default.html.markdown b/website/docs/r/branch_default.html.markdown index 2d2ff1ab95..d9885c1b6b 100644 --- a/website/docs/r/branch_default.html.markdown +++ b/website/docs/r/branch_default.html.markdown @@ -14,10 +14,26 @@ This resource allows you to set the default branch for a given repository. ## Example Usage ```hcl -# Add a collaborator to a repository -resource "github_repository_collaborator" "a_repo_collaborator" { - repository = "our-cool-repo" - branch = "my-default-branch" +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 } ``` @@ -34,4 +50,4 @@ GitHub Branch Defaults can be imported using an ID made up of `repository`, e.g. ``` $ terraform import github_branch_default.branch_default my-repo -``` \ No newline at end of file +```