From 009c4e5d2701a572a5381147a0eaacdb3ec65f61 Mon Sep 17 00:00:00 2001 From: deltreey Date: Thu, 28 May 2026 12:29:01 -0500 Subject: [PATCH] fix actions permissions API call --- ...github_actions_organization_permissions.go | 43 +++---- ...b_actions_organization_permissions_test.go | 109 ++++++++++++++++++ 2 files changed, 132 insertions(+), 20 deletions(-) diff --git a/github/resource_github_actions_organization_permissions.go b/github/resource_github_actions_organization_permissions.go index 9bff636de0..70dd7fca24 100644 --- a/github/resource_github_actions_organization_permissions.go +++ b/github/resource_github_actions_organization_permissions.go @@ -2,7 +2,6 @@ package github import ( "context" - "errors" "log" "github.com/google/go-github/v88/github" @@ -120,19 +119,23 @@ func resourceGithubActionsOrganizationAllowedObject(d *schema.ResourceData) *git } func resourceGithubActionsEnabledRepositoriesObject(d *schema.ResourceData) ([]int64, error) { - var enabled []int64 - config := d.Get("enabled_repositories_config").([]any) + if len(config) == 0 || config[0] == nil { + return []int64{}, nil + } + + enabled := []int64{} if len(config) > 0 { - data := config[0].(map[string]any) + data, ok := config[0].(map[string]any) + if !ok { + return []int64{}, nil + } switch x := data["repository_ids"].(type) { case *schema.Set: for _, value := range x.List() { enabled = append(enabled, int64(value.(int))) } } - } else { - return nil, errors.New("the enabled_repositories_config {} block must be specified if enabled_repositories == 'selected'") } return enabled, nil } @@ -150,14 +153,20 @@ func resourceGithubActionsOrganizationPermissionsCreateOrUpdate(d *schema.Resour return err } - allowedActions := d.Get("allowed_actions").(string) enabledRepositories := d.Get("enabled_repositories").(string) actionsPermissions := github.ActionsPermissions{ - AllowedActions: &allowedActions, EnabledRepositories: &enabledRepositories, } + allowedActions := "" + if v, ok := d.GetOk("allowed_actions"); ok && enabledRepositories != "none" { + allowedActions = v.(string) + if allowedActions != "" { + actionsPermissions.AllowedActions = &allowedActions + } + } + if v, ok := d.GetOk("sha_pinning_required"); ok { actionsPermissions.SHAPinningRequired = new(v.(bool)) } @@ -270,18 +279,12 @@ func resourceGithubActionsOrganizationPermissionsRead(d *schema.ResourceData, me for index := range allRepos { repoList = append(repoList, *allRepos[index].ID) } - if allRepos != nil { - if err = d.Set("enabled_repositories_config", []any{ - map[string]any{ - "repository_ids": repoList, - }, - }); err != nil { - return err - } - } else { - if err = d.Set("enabled_repositories_config", []any{}); err != nil { - return err - } + if err = d.Set("enabled_repositories_config", []any{ + map[string]any{ + "repository_ids": repoList, + }, + }); err != nil { + return err } } diff --git a/github/resource_github_actions_organization_permissions_test.go b/github/resource_github_actions_organization_permissions_test.go index 8aa3b9516e..c33bf74b0b 100644 --- a/github/resource_github_actions_organization_permissions_test.go +++ b/github/resource_github_actions_organization_permissions_test.go @@ -1,9 +1,13 @@ package github import ( + "encoding/json" "fmt" + "net/http" + "net/http/httptest" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) @@ -239,3 +243,108 @@ func TestAccGithubActionsOrganizationPermissions(t *testing.T) { }) }) } + +func TestGithubActionsOrganizationPermissionsOmitsAllowedActionsForNone(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodPut && r.URL.Path == "/orgs/test-org/actions/permissions": + var body map[string]any + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + t.Fatalf("decoding request body: %s", err) + } + if _, ok := body["allowed_actions"]; ok { + t.Fatalf("allowed_actions should be omitted when enabled_repositories is none, got %#v", body) + } + if got := body["enabled_repositories"]; got != "none" { + t.Fatalf("enabled_repositories = %#v, want none", got) + } + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"enabled_repositories":"none","sha_pinning_required":false}`)) + case r.Method == http.MethodGet && r.URL.Path == "/orgs/test-org/actions/permissions": + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"enabled_repositories":"none","sha_pinning_required":false}`)) + default: + t.Fatalf("unexpected request %s %s", r.Method, r.URL.String()) + } + })) + defer server.Close() + + resource := resourceGithubActionsOrganizationPermissions() + data := schema.TestResourceDataRaw(t, resource.Schema, map[string]any{ + "enabled_repositories": "none", + }) + meta := &Owner{ + name: "test-org", + IsOrganization: true, + v3client: mustGitHubClient(t, server.URL+"/"), + } + + if err := resourceGithubActionsOrganizationPermissionsCreateOrUpdate(data, meta); err != nil { + t.Fatalf("creating actions organization permissions: %s", err) + } +} + +func TestGithubActionsEnabledRepositoriesObjectAllowsEmptyConfig(t *testing.T) { + resource := resourceGithubActionsOrganizationPermissions() + data := schema.TestResourceDataRaw(t, resource.Schema, map[string]any{ + "enabled_repositories_config": []any{nil}, + }) + + defer func() { + if r := recover(); r != nil { + t.Fatalf("empty enabled_repositories_config should not panic: %v", r) + } + }() + + ids, err := resourceGithubActionsEnabledRepositoriesObject(data) + if err != nil { + t.Fatalf("empty enabled_repositories_config returned error: %s", err) + } + if len(ids) != 0 { + t.Fatalf("repository ids = %#v, want empty", ids) + } +} + +func TestGithubActionsOrganizationPermissionsReadPreservesEmptySelectedRepositories(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodGet && r.URL.Path == "/orgs/test-org/actions/permissions": + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"enabled_repositories":"selected","allowed_actions":"local_only","sha_pinning_required":false}`)) + case r.Method == http.MethodGet && r.URL.Path == "/orgs/test-org/actions/permissions/repositories": + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"total_count":0,"repositories":[]}`)) + default: + t.Fatalf("unexpected request %s %s", r.Method, r.URL.String()) + } + })) + defer server.Close() + + resource := resourceGithubActionsOrganizationPermissions() + data := schema.TestResourceDataRaw(t, resource.Schema, map[string]any{ + "allowed_actions": "local_only", + "enabled_repositories": "selected", + "enabled_repositories_config": []any{ + map[string]any{"repository_ids": []any{}}, + }, + }) + data.SetId("test-org") + meta := &Owner{ + name: "test-org", + IsOrganization: true, + v3client: mustGitHubClient(t, server.URL+"/"), + } + + if err := resourceGithubActionsOrganizationPermissionsRead(data, meta); err != nil { + t.Fatalf("reading actions organization permissions: %s", err) + } + + config := data.Get("enabled_repositories_config").([]any) + if len(config) != 1 { + t.Fatalf("enabled_repositories_config length = %d, want 1", len(config)) + } + repositoryIDs := config[0].(map[string]any)["repository_ids"].(*schema.Set) + if repositoryIDs.Len() != 0 { + t.Fatalf("repository_ids length = %d, want 0", repositoryIDs.Len()) + } +}