From 9a18fb80ec5ac68db6f33815d3c9dee1664493c3 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 7 Jul 2026 22:17:11 +0300 Subject: [PATCH 1/4] Adds failing test case Signed-off-by: Timo Sand --- github/actions_permissions_orgs_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/github/actions_permissions_orgs_test.go b/github/actions_permissions_orgs_test.go index dc949ae04c0..3ee061f832d 100644 --- a/github/actions_permissions_orgs_test.go +++ b/github/actions_permissions_orgs_test.go @@ -290,6 +290,30 @@ func TestActionsService_UpdateActionsAllowed(t *testing.T) { }) } +func TestActionsService_UpdateActionsAllowed_emptyPatterns(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: []string{}} + + mux.HandleFunc("/orgs/o/actions/permissions/selected-actions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + testJSONBody(t, r, input) + fmt.Fprint(w, `{"github_owned_allowed":true, "verified_allowed":false, "patterns_allowed":[]}`) + }) + + ctx := t.Context() + org, _, err := client.Actions.UpdateActionsAllowed(ctx, "o", *input) + if err != nil { + t.Errorf("Actions.UpdateActionsAllowed returned error: %v", err) + } + + want := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: []string{}} + if !cmp.Equal(org, want) { + t.Errorf("Actions.UpdateActionsAllowed returned %+v, want %+v", org, want) + } +} + func TestActionsService_GetDefaultWorkflowPermissionsInOrganization(t *testing.T) { t.Parallel() client, mux, _ := setup(t) From f5d3831f9a156f79db8ab9f431a83556bc8f2819 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 7 Jul 2026 22:25:35 +0300 Subject: [PATCH 2/4] Change `PatternsAllowed` to `omitzero` and add further test cases Signed-off-by: Timo Sand --- github/actions_permissions_orgs.go | 2 +- github/actions_permissions_orgs_test.go | 82 +++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/github/actions_permissions_orgs.go b/github/actions_permissions_orgs.go index a2efaaf59d7..dc3261a3906 100644 --- a/github/actions_permissions_orgs.go +++ b/github/actions_permissions_orgs.go @@ -36,7 +36,7 @@ type ActionsEnabledOnOrgRepos struct { type ActionsAllowed struct { GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` VerifiedAllowed *bool `json:"verified_allowed,omitempty"` - PatternsAllowed []string `json:"patterns_allowed,omitempty"` + PatternsAllowed []string `json:"patterns_allowed,omitzero"` } func (a ActionsAllowed) String() string { diff --git a/github/actions_permissions_orgs_test.go b/github/actions_permissions_orgs_test.go index 3ee061f832d..b8dddddba72 100644 --- a/github/actions_permissions_orgs_test.go +++ b/github/actions_permissions_orgs_test.go @@ -252,6 +252,40 @@ func TestActionsService_GetActionsAllowed(t *testing.T) { }) } +func TestActionsService_GetActionsAllowed_emptyPatterns(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/permissions/selected-actions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"github_owned_allowed":true, "verified_allowed":false, "patterns_allowed":[]}`) + }) + + ctx := t.Context() + org, _, err := client.Actions.GetActionsAllowed(ctx, "o") + if err != nil { + t.Errorf("Actions.GetActionsAllowed returned error: %v", err) + } + want := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: []string{}} + if !cmp.Equal(org, want) { + t.Errorf("Actions.GetActionsAllowed returned %+v, want %+v", org, want) + } + + const methodName = "GetActionsAllowed" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.GetActionsAllowed(ctx, "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Actions.GetActionsAllowed(ctx, "o") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + func TestActionsService_UpdateActionsAllowed(t *testing.T) { t.Parallel() client, mux, _ := setup(t) @@ -314,6 +348,54 @@ func TestActionsService_UpdateActionsAllowed_emptyPatterns(t *testing.T) { } } +func TestActionsService_UpdateActionsAllowed_nilPatterns(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: nil} + + mux.HandleFunc("/orgs/o/actions/permissions/selected-actions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + testJSONBody(t, r, input) + fmt.Fprint(w, `{"github_owned_allowed":true, "verified_allowed":false, "patterns_allowed":["a/b"]}`) + }) + + ctx := t.Context() + org, _, err := client.Actions.UpdateActionsAllowed(ctx, "o", *input) + if err != nil { + t.Errorf("Actions.UpdateActionsAllowed returned error: %v", err) + } + + want := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: []string{"a/b"}} + if !cmp.Equal(org, want) { + t.Errorf("Actions.UpdateActionsAllowed returned %+v, want %+v", org, want) + } +} + +func TestActionsService_UpdateActionsAllowed_omittedPatterns(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false)} + + mux.HandleFunc("/orgs/o/actions/permissions/selected-actions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + testJSONBody(t, r, input) + fmt.Fprint(w, `{"github_owned_allowed":true, "verified_allowed":false, "patterns_allowed":["a/b"]}`) + }) + + ctx := t.Context() + org, _, err := client.Actions.UpdateActionsAllowed(ctx, "o", *input) + if err != nil { + t.Errorf("Actions.UpdateActionsAllowed returned error: %v", err) + } + + want := &ActionsAllowed{GithubOwnedAllowed: Ptr(true), VerifiedAllowed: Ptr(false), PatternsAllowed: []string{"a/b"}} + if !cmp.Equal(org, want) { + t.Errorf("Actions.UpdateActionsAllowed returned %+v, want %+v", org, want) + } +} + func TestActionsService_GetDefaultWorkflowPermissionsInOrganization(t *testing.T) { t.Parallel() client, mux, _ := setup(t) From 8c14942a1c21a5f295a7808b8b60f39940fc5d77 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 8 Jul 2026 17:42:39 +0300 Subject: [PATCH 3/4] Add comment to `PatternsAllowed` and it's usage of `omitzero` Signed-off-by: Timo Sand --- github/actions_permissions_orgs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/actions_permissions_orgs.go b/github/actions_permissions_orgs.go index dc3261a3906..94ab73660ec 100644 --- a/github/actions_permissions_orgs.go +++ b/github/actions_permissions_orgs.go @@ -36,7 +36,7 @@ type ActionsEnabledOnOrgRepos struct { type ActionsAllowed struct { GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` VerifiedAllowed *bool `json:"verified_allowed,omitempty"` - PatternsAllowed []string `json:"patterns_allowed,omitzero"` + PatternsAllowed []string `json:"patterns_allowed,omitzero"` // omitzero is used to allow empty array to be sent in the request body, to configure the organization to allow no 3rd-party actions. It needs to still omit a `nil` value, so that it's possible to patch the other values without changing the allowed actions. } func (a ActionsAllowed) String() string { From 7283a32e57e4043816357c7e4362f3da8763b4f3 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 8 Jul 2026 21:27:03 +0300 Subject: [PATCH 4/4] Address comment placement feedback Signed-off-by: Timo Sand --- github/actions_permissions_orgs.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/github/actions_permissions_orgs.go b/github/actions_permissions_orgs.go index 94ab73660ec..88bfd87812d 100644 --- a/github/actions_permissions_orgs.go +++ b/github/actions_permissions_orgs.go @@ -34,9 +34,12 @@ type ActionsEnabledOnOrgRepos struct { // // GitHub API docs: https://docs.github.com/rest/actions/permissions?apiVersion=2022-11-28 type ActionsAllowed struct { - GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` - VerifiedAllowed *bool `json:"verified_allowed,omitempty"` - PatternsAllowed []string `json:"patterns_allowed,omitzero"` // omitzero is used to allow empty array to be sent in the request body, to configure the organization to allow no 3rd-party actions. It needs to still omit a `nil` value, so that it's possible to patch the other values without changing the allowed actions. + GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` + VerifiedAllowed *bool `json:"verified_allowed,omitempty"` + // PatternsAllowed uses `omitzero` to allow an empty array to be sent in the request body in order to + // configure the organization to allow no 3rd-party actions. It needs to still omit a `nil` value so + // that it's possible to patch the other values without changing the allowed actions. + PatternsAllowed []string `json:"patterns_allowed,omitzero"` } func (a ActionsAllowed) String() string {