Skip to content

Commit

Permalink
feat: Added organization role support
Browse files Browse the repository at this point in the history
Signed-off-by: Steve Hipwell <[email protected]>
  • Loading branch information
stevehipwell committed Dec 9, 2024
1 parent 1c11053 commit b04dee2
Show file tree
Hide file tree
Showing 37 changed files with 2,282 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MD013: false
MD024:
siblings_only: true
MD028: false
3 changes: 2 additions & 1 deletion github/data_source_github_organization_custom_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (

func dataSourceGithubOrganizationCustomRole() *schema.Resource {
return &schema.Resource{
Read: dataSourceGithubOrganizationCustomRoleRead,
DeprecationMessage: "This data source is deprecated and will be removed in a future release. Use the github_organization_repository_role data source instead.",

Read: dataSourceGithubOrganizationCustomRoleRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Expand Down
95 changes: 95 additions & 0 deletions github/data_source_github_organization_repository_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package github

import (
"context"
"fmt"
"strconv"

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

func dataSourceGithubOrganizationRepositoryRole() *schema.Resource {
return &schema.Resource{
Description: "Lookup a custom organization repository role.",

Read: dataSourceGithubOrganizationRepositoryRoleRead,

Schema: map[string]*schema.Schema{
"role_id": {
Description: "The ID of the organization repository role.",
Type: schema.TypeInt,
Required: true,
},
"name": {
Description: "The name of the organization repository role.",
Type: schema.TypeString,
Computed: true,
},
"description": {
Description: "The description of the organization repository role.",
Type: schema.TypeString,
Computed: true,
},
"base_role": {
Description: "The system role from which this role inherits permissions.",
Type: schema.TypeString,
Computed: true,
},
"permissions": {
Description: "The permissions included in this role.",
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
},
}
}

func dataSourceGithubOrganizationRepositoryRoleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client
ctx := context.Background()
orgName := meta.(*Owner).name

roleId := int64(d.Get("role_id").(int))

// TODO: Use this code when go-github adds the functionality to get a custom repo role
// role, _, err := client.Organizations.GetCustomRepoRole(ctx, orgName, roleId)
// if err != nil {
// return err
// }

roles, _, err := client.Organizations.ListCustomRepoRoles(ctx, orgName)
if err != nil {
return err
}

var role *github.CustomRepoRoles
for _, r := range roles.CustomRepoRoles {
if r.GetID() == roleId {
role = r
break
}
}
if role == nil {
return fmt.Errorf("custom organization repo role with ID %d not found", roleId)
}

r := map[string]any{
"role_id": role.GetID(),
"name": role.GetName(),
"description": role.GetDescription(),
"base_role": role.GetBaseRole(),
"permissions": role.Permissions,
}

d.SetId(strconv.FormatInt(role.GetID(), 10))

for k, v := range r {
if err := d.Set(k, v); err != nil {
return err
}
}

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

import (
"fmt"
"testing"

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

func TestAccGithubOrganizationRepositoryRoleDataSource(t *testing.T) {
t.Run("queries an organization repository role", func(t *testing.T) {
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
roleName := fmt.Sprintf(`tf-acc-test-%s`, randomID)

config := fmt.Sprintf(`
resource "github_organization_repository_role" "test" {
name = "%s"
description = "Test role description"
base_role = "read"
permissions = [
"reopen_issue",
"reopen_pull_request",
]
}
data "github_organization_repository_role" "test" {
role_id = github_organization_repository_role.test.role_id
depends_on = [ github_organization_repository_role.test ]
}
`, roleName)

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, enterprise) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair("data.github_organization_repository_role.test", "name", "github_organization_repository_role.test", "name"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_role.test", "description", "github_organization_repository_role.test", "description"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_role.test", "base_role", "github_organization_repository_role.test", "base_role"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_role.test", "permissions.#", "github_organization_repository_role.test", "permissions.#"),
),
},
},
})
})
}
84 changes: 84 additions & 0 deletions github/data_source_github_organization_repository_roles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package github

import (
"context"
"fmt"

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

func dataSourceGithubOrganizationRepositoryRoles() *schema.Resource {
return &schema.Resource{
Description: "Lookup all custom repository roles in an organization.",

Read: dataSourceGithubOrganizationRepositoryRolesRead,

Schema: map[string]*schema.Schema{
"roles": {
Description: "Available organization repository roles.",
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"role_id": {
Description: "The ID of the organization repository role.",
Type: schema.TypeInt,
Computed: true,
},
"name": {
Description: "The name of the organization repository role.",
Type: schema.TypeString,
Computed: true,
},
"description": {
Description: "The description of the organization repository role.",
Type: schema.TypeString,
Computed: true,
},
"base_role": {
Description: "The system role from which this role inherits permissions.",
Type: schema.TypeString,
Computed: true,
},
"permissions": {
Description: "The permissions included in this role.",
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
},
},
},
},
}
}

func dataSourceGithubOrganizationRepositoryRolesRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client
ctx := context.Background()
orgName := meta.(*Owner).name

ret, _, err := client.Organizations.ListCustomRepoRoles(ctx, orgName)
if err != nil {
return err
}

allRoles := make([]any, ret.GetTotalCount())
for i, role := range ret.CustomRepoRoles {
r := map[string]any{
"role_id": role.GetID(),
"name": role.GetName(),
"description": role.GetDescription(),
"base_role": role.GetBaseRole(),
"permissions": role.Permissions,
}
allRoles[i] = r
}

d.SetId(fmt.Sprintf("%s/github-org-repo-roles", orgName))
if err := d.Set("roles", allRoles); err != nil {
return fmt.Errorf("error setting roles: %s", err)
}

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

import (
"testing"

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

func TestAccDataSourceGithubOrganizationRepositoryRoles(t *testing.T) {
t.Run("get empty organization roles without error", func(t *testing.T) {
config := `
data "github_organization_repository_roles" "test" {}
`

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, organization) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.github_organization_repository_roles.test", "roles.#"),
resource.TestCheckResourceAttr("data.github_organization_repository_roles.test", "roles.#", "0"),
),
},
},
})
})

t.Run("get organization roles without error", func(t *testing.T) {
config := `
resource "github_organization_repository_role" "test" {
name = "%s"
description = "Test role description"
base_role = "read"
permissions = [
"reopen_issue",
"reopen_pull_request",
]
}
data "github_organization_repository_roles" "test" {
depends_on = [ github_organization_repository_role.test ]
}
`

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, enterprise) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.github_organization_repository_roles.test", "roles.#"),
resource.TestCheckResourceAttr("data.github_organization_repository_roles.test", "roles.#", "1"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_roles.test", "roles.0.name", "github_organization_repository_role.test", "name"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_roles.test", "roles.0.description", "github_organization_repository_role.test", "description"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_roles.test", "roles.0.base_role", "github_organization_repository_role.test", "base_role"),
resource.TestCheckResourceAttrPair("data.github_organization_repository_roles.test", "roles.0.permissions.#", "github_organization_repository_role.test", "permissions.#"),
),
},
},
})
})
}
82 changes: 82 additions & 0 deletions github/data_source_github_organization_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package github

import (
"context"
"strconv"

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

func dataSourceGithubOrganizationRole() *schema.Resource {
return &schema.Resource{
Description: "Lookup a custom organization role.",

Read: dataSourceGithubOrganizationRoleRead,

Schema: map[string]*schema.Schema{
"role_id": {
Description: "The ID of the organization role.",
Type: schema.TypeInt,
Required: true,
},
"name": {
Description: "The name of the organization role.",
Type: schema.TypeString,
Computed: true,
},
"description": {
Description: "The description of the organization role.",
Type: schema.TypeString,
Computed: true,
},
"source": {
Description: "The source of this role; one of `Predefined`, `Organization`, or `Enterprise`.",
Type: schema.TypeString,
Computed: true,
},
"base_role": {
Description: "The system role from which this role inherits permissions.",
Type: schema.TypeString,
Computed: true,
},
"permissions": {
Description: "A list of permissions included in this role.",
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
},
}
}

func dataSourceGithubOrganizationRoleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client
ctx := context.Background()
orgName := meta.(*Owner).name

roleId := int64(d.Get("role_id").(int))

role, _, err := client.Organizations.GetOrgRole(ctx, orgName, roleId)
if err != nil {
return err
}

r := map[string]any{
"role_id": role.GetID(),
"name": role.GetName(),
"description": role.GetDescription(),
"source": role.GetSource(),
"base_role": role.GetBaseRole(),
"permissions": role.Permissions,
}

d.SetId(strconv.FormatInt(role.GetID(), 10))

for k, v := range r {
if err := d.Set(k, v); err != nil {
return err
}
}

return nil
}
Loading

0 comments on commit b04dee2

Please sign in to comment.