Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
172 changes: 86 additions & 86 deletions github/resource_github_actions_organization_workflow_permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

type GithubActionsOrganizationWorkflowPermissionsErrorResponse struct {
type githubActionsOrganizationWorkflowPermissionsErrorResponse struct {
Message string `json:"message"`
Errors string `json:"errors"`
DocumentationURL string `json:"documentation_url"`
Expand All @@ -25,9 +25,9 @@ type GithubActionsOrganizationWorkflowPermissionsErrorResponse struct {
func resourceGithubActionsOrganizationWorkflowPermissions() *schema.Resource {
return &schema.Resource{
Description: "This resource allows you to manage GitHub Actions workflow permissions for a GitHub Organization account. This controls the default permissions granted to the GITHUB_TOKEN when running workflows and whether GitHub Actions can approve pull request reviews.\n\nYou must have organization admin access to use this resource.",
CreateContext: resourceGithubActionsOrganizationWorkflowPermissionsCreateOrUpdate,
CreateContext: resourceGithubActionsOrganizationWorkflowPermissionsCreate,
ReadContext: resourceGithubActionsOrganizationWorkflowPermissionsRead,
UpdateContext: resourceGithubActionsOrganizationWorkflowPermissionsCreateOrUpdate,
UpdateContext: resourceGithubActionsOrganizationWorkflowPermissionsUpdate,
DeleteContext: resourceGithubActionsOrganizationWorkflowPermissionsDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
Expand Down Expand Up @@ -59,106 +59,85 @@ func resourceGithubActionsOrganizationWorkflowPermissions() *schema.Resource {

func handleEditWorkflowPermissionsError(ctx context.Context, err error, resp *github.Response) diag.Diagnostics {
var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) {
if ghErr.Response.StatusCode == http.StatusConflict {
tflog.Info(ctx, "Detected conflict with workflow permissions", map[string]any{
"status_code": ghErr.Response.StatusCode,
})
if errors.As(err, &ghErr) && ghErr.Response.StatusCode == http.StatusConflict {
tflog.Info(ctx, "Detected conflict with workflow permissions", map[string]any{
"status_code": ghErr.Response.StatusCode,
})

errorResponse := &GithubActionsOrganizationWorkflowPermissionsErrorResponse{}
errorResponse := &githubActionsOrganizationWorkflowPermissionsErrorResponse{}
if resp != nil && resp.Body != nil {
data, readError := io.ReadAll(resp.Body)
if readError == nil && data != nil {
unmarshalError := json.Unmarshal(data, errorResponse)
if unmarshalError != nil {
tflog.Error(ctx, "Failed to unmarshal error response", map[string]any{
if readError != nil {
tflog.Error(ctx, "Failed to read workflow permissions conflict response", map[string]any{
"error": readError.Error(),
})
return diag.FromErr(readError)
}

if len(data) > 0 {
if unmarshalError := json.Unmarshal(data, errorResponse); unmarshalError != nil {
tflog.Error(ctx, "Failed to unmarshal workflow permissions conflict response", map[string]any{
"error": unmarshalError.Error(),
})
return diag.FromErr(unmarshalError)
}

tflog.Debug(ctx, "Parsed workflow permissions conflict error", map[string]any{
"message": errorResponse.Message,
"errors": errorResponse.Errors,
"documentation_url": errorResponse.DocumentationURL,
"status": errorResponse.Status,
})
}
return diag.FromErr(fmt.Errorf("you are trying to modify a value restricted by the Enterprise's settings.\n Message: %s\n Errors: %s\n Documentation URL: %s\n Status: %s\nerr: %w", errorResponse.Message, errorResponse.Errors, errorResponse.DocumentationURL, errorResponse.Status, err))
}
}

tflog.Trace(ctx, "Returning generic error", map[string]any{
"error": err.Error(),
})
return diag.FromErr(fmt.Errorf("you are trying to modify a value restricted by the Enterprise's settings.\n Message: %s\n Errors: %s\n Documentation URL: %s\n Status: %s\nerr: %w", errorResponse.Message, errorResponse.Errors, errorResponse.DocumentationURL, errorResponse.Status, err))
}

return diag.FromErr(err)
}

func resourceGithubActionsOrganizationWorkflowPermissionsCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
tflog.Trace(ctx, "Entering Create/Update workflow permissions", map[string]any{
"organization_slug": d.Get("organization_slug").(string),
})

client := meta.(*Owner).v3client
func resourceGithubActionsOrganizationWorkflowPermissionsCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client

organizationSlug := d.Get("organization_slug").(string)
d.SetId(organizationSlug)
defaultPermissions := d.Get("default_workflow_permissions").(string)
canApprovePRReviews := d.Get("can_approve_pull_request_reviews").(bool)

if d.IsNewResource() {
tflog.Info(ctx, "Creating organization workflow permissions", map[string]any{
"organization_slug": organizationSlug,
})
} else {
tflog.Info(ctx, "Updating organization workflow permissions", map[string]any{
"organization_slug": organizationSlug,
})
}

workflowPerms := github.DefaultWorkflowPermissionOrganization{}

if v, ok := d.GetOk("default_workflow_permissions"); ok {
workflowPerms.DefaultWorkflowPermissions = github.Ptr(v.(string))
}
ctx = tflog.SetField(ctx, "organization_slug", organizationSlug)
tflog.Info(ctx, "Creating workflow permissions")

if v, ok := d.GetOk("can_approve_pull_request_reviews"); ok {
workflowPerms.CanApprovePullRequestReviews = github.Ptr(v.(bool))
workflowPerms := github.DefaultWorkflowPermissionOrganization{
DefaultWorkflowPermissions: github.Ptr(defaultPermissions),
CanApprovePullRequestReviews: github.Ptr(canApprovePRReviews),
}

tflog.Debug(ctx, "Calling GitHub API to update workflow permissions", map[string]any{
"organization_slug": organizationSlug,
"default_workflow_permissions": workflowPerms.DefaultWorkflowPermissions,
"can_approve_pull_request_reviews": workflowPerms.CanApprovePullRequestReviews,
tflog.Debug(ctx, "Calling GitHub API to create workflow permissions", map[string]any{
"default_workflow_permissions": defaultPermissions,
"can_approve_pull_request_reviews": canApprovePRReviews,
})
_, resp, err := client.Actions.UpdateDefaultWorkflowPermissionsInOrganization(ctx, organizationSlug, workflowPerms)
if err != nil {
return handleEditWorkflowPermissionsError(ctx, err, resp)
}

tflog.Trace(ctx, "Exiting Create/Update workflow permissions successfully", map[string]any{
"organization_slug": organizationSlug,
})
return nil
}
d.SetId(organizationSlug)

func resourceGithubActionsOrganizationWorkflowPermissionsRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
tflog.Trace(ctx, "Entering Read workflow permissions", map[string]any{
"organization_slug": d.Id(),
})
tflog.Trace(ctx, "Created workflow permissions successfully")

client := meta.(*Owner).v3client
return resourceGithubActionsOrganizationWorkflowPermissionsRead(ctx, d, m)
}

func resourceGithubActionsOrganizationWorkflowPermissionsRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client

organizationSlug := d.Id()
tflog.Debug(ctx, "Calling GitHub API to read workflow permissions", map[string]any{
"organization_slug": organizationSlug,
})

ctx = tflog.SetField(ctx, "id", d.Id())
ctx = tflog.SetField(ctx, "organization_slug", organizationSlug)
tflog.Info(ctx, "Reading workflow permissions")

workflowPerms, _, err := client.Actions.GetDefaultWorkflowPermissionsInOrganization(ctx, organizationSlug)
if err != nil {
return diag.FromErr(err)
}

tflog.Debug(ctx, "Retrieved workflow permissions from API", map[string]any{
"organization_slug": organizationSlug,
"default_workflow_permissions": workflowPerms.DefaultWorkflowPermissions,
"can_approve_pull_request_reviews": workflowPerms.CanApprovePullRequestReviews,
})
Expand All @@ -173,38 +152,61 @@ func resourceGithubActionsOrganizationWorkflowPermissionsRead(ctx context.Contex
return diag.FromErr(err)
}

tflog.Trace(ctx, "Exiting Read workflow permissions successfully", map[string]any{
"organization_slug": organizationSlug,
})
tflog.Trace(ctx, "Read workflow permissions successfully")

return nil
}

func resourceGithubActionsOrganizationWorkflowPermissionsDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
tflog.Trace(ctx, "Entering Delete workflow permissions", map[string]any{
"organization_slug": d.Id(),
func resourceGithubActionsOrganizationWorkflowPermissionsUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client

organizationSlug := d.Id()
defaultPermissions := d.Get("default_workflow_permissions").(string)
canApprovePRReviews := d.Get("can_approve_pull_request_reviews").(bool)

ctx = tflog.SetField(ctx, "id", d.Id())
ctx = tflog.SetField(ctx, "organization_slug", organizationSlug)
tflog.Info(ctx, "Updating workflow permissions")

workflowPerms := github.DefaultWorkflowPermissionOrganization{
DefaultWorkflowPermissions: github.Ptr(defaultPermissions),
CanApprovePullRequestReviews: github.Ptr(canApprovePRReviews),
}

tflog.Debug(ctx, "Calling GitHub API to update workflow permissions", map[string]any{
"default_workflow_permissions": defaultPermissions,
"can_approve_pull_request_reviews": canApprovePRReviews,
})
_, resp, err := client.Actions.UpdateDefaultWorkflowPermissionsInOrganization(ctx, organizationSlug, workflowPerms)
if err != nil {
return handleEditWorkflowPermissionsError(ctx, err, resp)
}

client := meta.(*Owner).v3client
d.SetId(organizationSlug)

tflog.Trace(ctx, "Updated workflow permissions successfully")

return resourceGithubActionsOrganizationWorkflowPermissionsRead(ctx, d, m)
}

func resourceGithubActionsOrganizationWorkflowPermissionsDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client

organizationSlug := d.Id()
tflog.Info(ctx, "Deleting organization workflow permissions (resetting to defaults)", map[string]any{
"organization_slug": organizationSlug,
})

ctx = tflog.SetField(ctx, "id", d.Id())
ctx = tflog.SetField(ctx, "organization_slug", organizationSlug)
tflog.Info(ctx, "Deleting organization workflow permissions (resetting to defaults)")

// Reset to safe defaults
workflowPerms := github.DefaultWorkflowPermissionOrganization{
DefaultWorkflowPermissions: github.Ptr("read"),
CanApprovePullRequestReviews: github.Ptr(false),
}

tflog.Debug(ctx, "Using safe default values", map[string]any{
"default_workflow_permissions": "read",
"can_approve_pull_request_reviews": false,
})

tflog.Debug(ctx, "Calling GitHub API to reset workflow permissions", map[string]any{
"organization_slug": organizationSlug,
"workflow_permissions": workflowPerms,
})

Expand All @@ -213,9 +215,7 @@ func resourceGithubActionsOrganizationWorkflowPermissionsDelete(ctx context.Cont
return handleEditWorkflowPermissionsError(ctx, err, resp)
}

tflog.Trace(ctx, "Exiting Delete workflow permissions successfully", map[string]any{
"organization_slug": organizationSlug,
})
tflog.Trace(ctx, "Deleted workflow permissions successfully")

return nil
}
Loading