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

feat: support workflow permissions in repository #2309

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func Provider() *schema.Provider {
"github_user_ssh_key": resourceGithubUserSshKey(),
"github_enterprise_organization": resourceGithubEnterpriseOrganization(),
"github_enterprise_actions_runner_group": resourceGithubActionsEnterpriseRunnerGroup(),
"github_workflow_repository_permissions": resourceGithubWorkflowRepositoryPermissions(),
},

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

import (
"context"

"github.com/google/go-github/v62/github"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func resourceGithubWorkflowRepositoryPermissions() *schema.Resource {
return &schema.Resource{
Create: resourceGithubWorkflowRepositoryPermissionsCreateOrUpdate,
Read: resourceGithubWorkflowRepositoryPermissionsRead,
Update: resourceGithubWorkflowRepositoryPermissionsCreateOrUpdate,
Delete: resourceGithubWorkflowRepositoryPermissionsDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"default_workflow_permissions": {
Type: schema.TypeString,
Optional: true,
Description: "The default workflow permissions granted to the GITHUB_TOKEN when running workflows.",
ValidateDiagFunc: toDiagFunc(validation.StringInSlice([]string{"read", "write"}, false), "default_workflow_permissions"),
},
"can_approve_pull_request_reviews": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Whether GitHub Actions can approve pull requests. Enabling this can be a security risk.",
},
"repository": {
Type: schema.TypeString,
Required: true,
Description: "The GitHub repository.",
ValidateDiagFunc: toDiagFunc(validation.StringLenBetween(1, 100), "repository"),
},
},
}
}

func resourceGithubWorkflowRepositoryPermissionsCreateOrUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client

owner := meta.(*Owner).name
repoName := d.Get("repository").(string)
ctx := context.Background()
if !d.IsNewResource() {
ctx = context.WithValue(ctx, ctxId, d.Id())
}

defaultWorkflowPermissions := d.Get("default_workflow_permissions").(string)
canApprovePullRequestReviews := d.Get("can_approve_pull_request_reviews").(bool)

repoWorkflowPermissions := github.DefaultWorkflowPermissionRepository{
DefaultWorkflowPermissions: &defaultWorkflowPermissions,
CanApprovePullRequestReviews: &canApprovePullRequestReviews,
}

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

d.SetId(repoName)
return resourceGithubWorkflowRepositoryPermissionsRead(d, meta)
}

func resourceGithubWorkflowRepositoryPermissionsRead(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())

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

if err = d.Set("default_workflow_permissions", workflowsPermissions.GetDefaultWorkflowPermissions()); err != nil {
return err
}
if err = d.Set("can_approve_pull_request_reviews", workflowsPermissions.GetCanApprovePullRequestReviews()); err != nil {
return err
}
if err = d.Set("repository", repoName); err != nil {
return err
}

return nil
}

func resourceGithubWorkflowRepositoryPermissionsDelete(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())

// Reset the repo to "default" settings
repoWorkflowPermissions := github.DefaultWorkflowPermissionRepository{
DefaultWorkflowPermissions: github.String("read"),
CanApprovePullRequestReviews: github.Bool(false),
}

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

return nil
}
125 changes: 125 additions & 0 deletions github/resource_github_workflow_repository_permissions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package github

import (
"fmt"
"testing"

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

func TestAccGithubWorkflowRepositoryPermissions(t *testing.T) {

t.Run("test setting of basic workflow repository permissions", func(t *testing.T) {

defaultWorkflowPermissions := "read"
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "tf-acc-test-topic-%[1]s"
description = "Terraform acceptance tests %[1]s"
topics = ["terraform", "testing"]
}

resource "github_workflow_repository_permissions" "test" {
default_workflow_permissions = "%s"
repository = github_repository.test.name
}
`, randomID, defaultWorkflowPermissions)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"github_workflow_repository_permissions.test", "default_workflow_permissions", defaultWorkflowPermissions,
),
)

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("imports entire set of github workflow repository permissions without error", func(t *testing.T) {

defaultWorkflowPermissions := "read"
canApprovePullRequestReviews := "true"

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

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "tf-acc-test-topic-%[1]s"
description = "Terraform acceptance tests %[1]s"
topics = ["terraform", "testing"]
}

resource "github_workflow_repository_permissions" "test" {
default_workflow_permissions = "%s"
can_approve_pull_request_reviews = %s
repository = github_repository.test.name
}
`, randomID, defaultWorkflowPermissions, canApprovePullRequestReviews)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"github_workflow_repository_permissions.test", "default_workflow_permissions", defaultWorkflowPermissions,
),
resource.TestCheckResourceAttr(
"github_workflow_repository_permissions.test", "can_approve_pull_request_reviews", canApprovePullRequestReviews,
),
)

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,
},
{
ResourceName: "github_workflow_repository_permissions.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

})
}
41 changes: 41 additions & 0 deletions website/docs/r/workflow_repository_permissions.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
layout: "github"
page_title: "GitHub: github_workflow_repository_permissions"
description: |-
Enables and manages Workflow permissions for a GitHub repository
---

# github_workflow_repository_permissions

This resource allows you to manage GitHub Workflow permissions for a given repository.
You must have admin access to a repository to use this resource.

## Example Usage

```hcl
resource "github_repository" "example" {
name = "my-repository"
}
resource "github_workflow_repository_permissions" "test" {
default_workflow_permissions = "read"
can_approve_pull_request_reviews = true
repository = github_repository.example.name
}
```

## Argument Reference

The following arguments are supported:

* `repository` - (Required) The GitHub repository
* `default_workflow_permissions` - (Optional) The default workflow permissions granted to the GITHUB_TOKEN when running workflows. Can be one of: `read` or `write`.
* `can_approve_pull_request_reviews` - (Optional) Whether GitHub Actions can approve pull requests. Enabling this can be a security risk.

## Import

This resource can be imported using the name of the GitHub repository:

```
$ terraform import github_workflow_repository_permissions.test my-repository
```