Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fa393ef
feat: add enterprise teams resources and data sources
github-actions[bot] Dec 17, 2025
cdb5e93
feat: migrate enterprise teams to context-aware CRUD
github-actions[bot] Dec 18, 2025
f81c8ce
fix: linting
github-actions[bot] Dec 22, 2025
a96dab4
chore: add schema validations
github-actions[bot] Dec 22, 2025
6f38cdd
docs: add top-level Description fields to enterprise team resources
github-actions[bot] Dec 22, 2025
0a39091
refactor: prefer go-github enterprise team SDK when available
github-actions[bot] Dec 22, 2025
00828cb
docs: validate enterprise team membership fields at plan time
github-actions[bot] Dec 22, 2025
469df33
docs: add description to enterprise team membership data source
github-actions[bot] Dec 22, 2025
290b186
docs: add descriptions and plan-time validation for enterprise team o…
github-actions[bot] Dec 22, 2025
34f0331
refactor: use go-github v81 SDK for enterprise teams
github-actions[bot] Jan 8, 2026
8aa784f
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
70b47e0
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
6993d4b
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
fa90600
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
cf6682f
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
80f7bb4
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
f6c7cf0
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
c6fd72a
Apply suggestion from @Copilot
vmvarela Jan 8, 2026
5fc8bfb
fix: address PR review comments for enterprise team data source
github-actions[bot] Jan 9, 2026
033b274
fix: use diag.Errorf instead of diag.FromErr(fmt.Errorf)
github-actions[bot] Jan 9, 2026
f55f0f4
fix: use diag.Errorf for slug validation error
github-actions[bot] Jan 9, 2026
b94a53c
refactor: use constants for field names and testResourcePrefix in tests
github-actions[bot] Jan 9, 2026
4103e9d
test: use testResourcePrefix in enterprise teams data source test
github-actions[bot] Jan 9, 2026
9969a2f
feat(enterprise_team): address PR review feedback and improve code qu…
github-actions[bot] Jan 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions github/data_source_github_enterprise_team.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package github

import (
"context"
"strconv"
"strings"

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

func dataSourceGithubEnterpriseTeam() *schema.Resource {
return &schema.Resource{
Description: "Gets information about a GitHub enterprise team.",
ReadContext: dataSourceGithubEnterpriseTeamRead,

Schema: map[string]*schema.Schema{
"enterprise_slug": {
Type: schema.TypeString,
Required: true,
Description: "The slug of the enterprise.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"slug": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"slug", "team_id"},
Description: "The slug of the enterprise team.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"team_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"slug", "team_id"},
Description: "The numeric ID of the enterprise team.",
ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(1)),
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "The name of the enterprise team.",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "A description of the enterprise team.",
},
"organization_selection_type": {
Type: schema.TypeString,
Computed: true,
Description: "Specifies which organizations in the enterprise should have access to this team.",
},
"group_id": {
Type: schema.TypeString,
Computed: true,
Description: "The ID of the IdP group to assign team membership with.",
},
},
}
}

func dataSourceGithubEnterpriseTeamRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
client := meta.(*Owner).v3client
enterpriseSlug := strings.TrimSpace(d.Get("enterprise_slug").(string))

var te *github.EnterpriseTeam
if v, ok := d.GetOk("team_id"); ok {
teamID := int64(v.(int))
if teamID != 0 {
found, err := findEnterpriseTeamByID(ctx, client, enterpriseSlug, teamID)
if err != nil {
return diag.FromErr(err)
}
if found == nil {
return diag.Errorf("could not find enterprise team %d in enterprise %s", teamID, enterpriseSlug)
}
te = found
}
}

if te == nil {
teamSlug := strings.TrimSpace(d.Get("slug").(string))
if teamSlug == "" {
return diag.Errorf("one of slug or team_id must be set")
}
found, _, err := client.Enterprise.GetTeam(ctx, enterpriseSlug, teamSlug)
if err != nil {
return diag.FromErr(err)
}
te = found
}

d.SetId(buildTwoPartID(enterpriseSlug, strconv.FormatInt(te.ID, 10)))
if err := d.Set("enterprise_slug", enterpriseSlug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("slug", te.Slug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("team_id", int(te.ID)); err != nil {
return diag.FromErr(err)
}
if err := d.Set("name", te.Name); err != nil {
return diag.FromErr(err)
}
if te.Description != nil {
if err := d.Set("description", *te.Description); err != nil {
return diag.FromErr(err)
}
} else {
if err := d.Set("description", ""); err != nil {
return diag.FromErr(err)
}
}
orgSel := ""
if te.OrganizationSelectionType != nil {
orgSel = *te.OrganizationSelectionType
}
if orgSel == "" {
orgSel = "disabled"
}
if err := d.Set("organization_selection_type", orgSel); err != nil {
return diag.FromErr(err)
}
if te.GroupID != "" {
if err := d.Set("group_id", te.GroupID); err != nil {
return diag.FromErr(err)
}
} else {
if err := d.Set("group_id", ""); err != nil {
return diag.FromErr(err)
}
}

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

import (
"context"
"strings"

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

func dataSourceGithubEnterpriseTeamMembership() *schema.Resource {
return &schema.Resource{
Description: "Gets information about a user's membership in a GitHub enterprise team.",
ReadContext: dataSourceGithubEnterpriseTeamMembershipRead,

Schema: map[string]*schema.Schema{
"enterprise_slug": {
Type: schema.TypeString,
Required: true,
Description: "The slug of the enterprise.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"team_slug": {
Type: schema.TypeString,
Required: true,
Description: "The slug of the enterprise team.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"username": {
Type: schema.TypeString,
Required: true,
Description: "The username of the user.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"user_id": {
Type: schema.TypeInt,
Computed: true,
Description: "The ID of the user.",
},
},
}
}

func dataSourceGithubEnterpriseTeamMembershipRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
client := meta.(*Owner).v3client
enterpriseSlug := strings.TrimSpace(d.Get("enterprise_slug").(string))
teamSlug := strings.TrimSpace(d.Get("team_slug").(string))
username := strings.TrimSpace(d.Get("username").(string))

// Get the membership using the SDK
user, _, err := client.Enterprise.GetTeamMembership(ctx, enterpriseSlug, teamSlug, username)
if err != nil {
return diag.FromErr(err)
}

d.SetId(buildEnterpriseTeamMembershipID(enterpriseSlug, teamSlug, username))
if err := d.Set("enterprise_slug", enterpriseSlug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("team_slug", teamSlug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("username", username); err != nil {
return diag.FromErr(err)
}
if user != nil && user.ID != nil {
if err := d.Set("user_id", int(*user.ID)); err != nil {
return diag.FromErr(err)
}
}

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

import (
"context"
"strings"

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

func dataSourceGithubEnterpriseTeamOrganizations() *schema.Resource {
return &schema.Resource{
Description: "Lists organizations assigned to a GitHub enterprise team.",
ReadContext: dataSourceGithubEnterpriseTeamOrganizationsRead,

Schema: map[string]*schema.Schema{
"enterprise_slug": {
Type: schema.TypeString,
Required: true,
Description: "The slug of the enterprise.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"team_slug": {
Type: schema.TypeString,
Required: true,
Description: "The slug of the enterprise team.",
ValidateDiagFunc: validation.ToDiagFunc(validation.All(validation.StringIsNotWhiteSpace, validation.StringIsNotEmpty)),
},
"organization_slugs": {
Type: schema.TypeSet,
Computed: true,
Description: "Set of organization slugs that the enterprise team is assigned to.",
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}

func dataSourceGithubEnterpriseTeamOrganizationsRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
client := meta.(*Owner).v3client
enterpriseSlug := strings.TrimSpace(d.Get("enterprise_slug").(string))
teamSlug := strings.TrimSpace(d.Get("team_slug").(string))
orgs, err := listAllEnterpriseTeamOrganizations(ctx, client, enterpriseSlug, teamSlug)
if err != nil {
return diag.FromErr(err)
}

slugs := make([]string, 0, len(orgs))
for _, org := range orgs {
if org.Login != nil && *org.Login != "" {
slugs = append(slugs, *org.Login)
}
}

d.SetId(buildEnterpriseTeamOrganizationsID(enterpriseSlug, teamSlug))
if err := d.Set("enterprise_slug", enterpriseSlug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("team_slug", teamSlug); err != nil {
return diag.FromErr(err)
}
if err := d.Set("organization_slugs", slugs); err != nil {
return diag.FromErr(err)
}
return nil
}
Loading