diff --git a/github/resource_github_repository.go b/github/resource_github_repository.go index 6c3188b167..a673d6d806 100644 --- a/github/resource_github_repository.go +++ b/github/resource_github_repository.go @@ -176,6 +176,11 @@ func resourceGithubRepository() *schema.Resource { Default: false, Description: "Set to 'true' to allow auto-merging pull requests on the repository.", }, + "allow_forking": { + Type: schema.TypeBool, + Optional: true, + Description: "Set to 'true' to allow forking on the repository. Only applicable for organization-owned repositories. If an enterprise has disabled forking within its organizations, the ability to fork will be disabled regardless of this setting. Can only be set for private and internal repositories.", + }, "squash_merge_commit_title": { Type: schema.TypeString, Optional: true, @@ -508,6 +513,15 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository { SecurityAndAnalysis: calculateSecurityAndAnalysis(d), } + // only configure allow_forking if explicitly set and repository is not public + // (public repositories can always be forked, so the setting doesn't apply) + if _, ok := d.GetOk("allow_forking"); ok { + visibility := calculateVisibility(d) + if visibility != "public" { + repository.AllowForking = github.Bool(d.Get("allow_forking").(bool)) + } + } + // only configure merge commit if we are in commit merge strategy allowMergeCommit, ok := d.Get("allow_merge_commit").(bool) if ok { @@ -692,6 +706,10 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta interface{}) erro // GitHub API doesn't respond following parameters when repository is archived if !d.Get("archived").(bool) { d.Set("allow_auto_merge", repo.GetAllowAutoMerge()) + // Only set allow_forking for private/internal repos (public repos can always be forked) + if repo.GetVisibility() != "public" { + d.Set("allow_forking", repo.GetAllowForking()) + } d.Set("allow_merge_commit", repo.GetAllowMergeCommit()) d.Set("allow_rebase_merge", repo.GetAllowRebaseMerge()) d.Set("allow_squash_merge", repo.GetAllowSquashMerge()) diff --git a/github/resource_github_repository_allow_forking_test.go b/github/resource_github_repository_allow_forking_test.go new file mode 100644 index 0000000000..066ee8fce0 --- /dev/null +++ b/github/resource_github_repository_allow_forking_test.go @@ -0,0 +1,103 @@ +package github + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccGithubRepositoryAllowForking(t *testing.T) { + randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum) + + t.Run("manages allow_forking setting for a repository", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-allow-forking-%[1]s" + description = "Terraform acceptance test for allow_forking (Issue #353)" + visibility = "private" + allow_forking = false + auto_init = true + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository.test", "allow_forking", + "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: 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("reads allow_forking setting from API", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-fork-read-%[1]s" + description = "Test allow_forking read from API" + visibility = "private" + allow_forking = false + auto_init = true + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository.test", "allow_forking", + "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: 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_test.go b/github/resource_github_repository_test.go index 4ea812e393..770927ec4a 100644 --- a/github/resource_github_repository_test.go +++ b/github/resource_github_repository_test.go @@ -36,6 +36,7 @@ func TestAccGithubRepositories(t *testing.T) { allow_squash_merge = false allow_rebase_merge = false allow_auto_merge = true + allow_forking = true merge_commit_title = "MERGE_MESSAGE" merge_commit_message = "PR_TITLE" auto_init = false @@ -56,6 +57,10 @@ func TestAccGithubRepositories(t *testing.T) { "github_repository.test", "allow_auto_merge", "true", ), + resource.TestCheckResourceAttr( + "github_repository.test", "allow_forking", + "true", + ), resource.TestCheckResourceAttr( "github_repository.test", "merge_commit_title", "MERGE_MESSAGE",