Repository: google/go-github
Pull request #2315 (2022-03-16 10:35:22)

Add support for setting actions permissions on a repository
👋  Hello there!

Couldn't find a PR for it yet so added functionality requested in https://github.com/google/go-github/issues/2297
Sorry if I pushed myself before @cfarrend in doing it but I will need the changes.

Went through the [contributing guide](https://github.com/google/go-github/blob/master/CONTRIBUTING.md) and also added an example to test the change end2end.

Thanks everyone!

Fixes: #2297.

google-cla[bot]: Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

For more information, open the [CLA check for this pull request](https://github.com/google/go-github/pull/2315/checks?check_run_id=5568449276).
codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2315](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (16fa0b5) into [master](https://codecov.io/gh/google/go-github/commit/f85909825349bdaf6bf8c483c3d42abdb63bb59e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (f859098) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##           master    #2315   +/-   ##
=======================================
  Coverage   97.84%   97.85%           
=======================================
  Files         115      117    +2     
  Lines       10416    10462   +46     
=======================================
+ Hits        10192    10238   +46     
  Misses        156      156           
  Partials       68       68           
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/orgs\_actions\_allowed.go](https://codecov.io/gh/google/go-github/pull/2315/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL29yZ3NfYWN0aW9uc19hbGxvd2VkLmdv) | `100.00% <ø> (ø)` | |
| [github/repos\_actions\_allowed.go](https://codecov.io/gh/google/go-github/pull/2315/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3JlcG9zX2FjdGlvbnNfYWxsb3dlZC5nbw==) | `100.00% <100.00%> (ø)` | |
| [github/repos\_actions\_permissions.go](https://codecov.io/gh/google/go-github/pull/2315/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3JlcG9zX2FjdGlvbnNfcGVybWlzc2lvbnMuZ28=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Last update [f859098...16fa0b5](https://codecov.io/gh/google/go-github/pull/2315?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).


Patch:
diff --git a/example/actionpermissions/main.go b/example/actionpermissions/main.go
new file mode 100644
index 00000000..a84a8e54
--- /dev/null
+++ b/example/actionpermissions/main.go
@@ -0,0 +1,80 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The actionpermissions command utilizes go-github as a cli tool for
+// changing GitHub Actions related permission settings for a repository.
+package main
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/google/go-github/v43/github"
+	"golang.org/x/oauth2"
+)
+
+var (
+	name  = flag.String("name", "", "repo to change Actions permissions.")
+	owner = flag.String("owner", "", "owner of targeted repo.")
+)
+
+func main() {
+	flag.Parse()
+	token := os.Getenv("GITHUB_AUTH_TOKEN")
+	if token == "" {
+		log.Fatal("Unauthorized: No token present")
+	}
+	if *name == "" {
+		log.Fatal("No name: repo name must be given")
+	}
+	if *owner == "" {
+		log.Fatal("No owner: owner of repo must be given")
+	}
+	ctx := context.Background()
+	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
+	tc := oauth2.NewClient(ctx, ts)
+	client := github.NewClient(tc)
+
+	actionsPermissionsRepository, _, err := client.Repositories.GetActionsPermissions(ctx, *owner, *name)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Current ActionsPermissions %s\n", actionsPermissionsRepository.String())
+
+	actionsPermissionsRepository = &github.ActionsPermissionsRepository{Enabled: github.Bool(true), AllowedActions: github.String("selected")}
+	_, _, err = client.Repositories.EditActionsPermissions(ctx, *owner, *name, *actionsPermissionsRepository)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Current ActionsPermissions %s\n", actionsPermissionsRepository.String())
+
+	actionsAllowed, _, err := client.Repositories.GetActionsAllowed(ctx, *owner, *name)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Current ActionsAllowed %s\n", actionsAllowed.String())
+
+	actionsAllowed = &github.ActionsAllowed{GithubOwnedAllowed: github.Bool(true), VerifiedAllowed: github.Bool(false), PatternsAllowed: []string{"a/b"}}
+	_, _, err = client.Repositories.EditActionsAllowed(ctx, *owner, *name, *actionsAllowed)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Current ActionsAllowed %s\n", actionsAllowed.String())
+
+	actionsPermissionsRepository = &github.ActionsPermissionsRepository{Enabled: github.Bool(true), AllowedActions: github.String("all")}
+	_, _, err = client.Repositories.EditActionsPermissions(ctx, *owner, *name, *actionsPermissionsRepository)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Current ActionsPermissions %s\n", actionsPermissionsRepository.String())
+}
diff --git a/github/github-accessors.go b/github/github-accessors.go
index ce5fa26a..cad631db 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -60,6 +60,30 @@ func (a *ActionsPermissions) GetSelectedActionsURL() string {
 	return *a.SelectedActionsURL
 }
 
+// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise.
+func (a *ActionsPermissionsRepository) GetAllowedActions() string {
+	if a == nil || a.AllowedActions == nil {
+		return ""
+	}
+	return *a.AllowedActions
+}
+
+// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise.
+func (a *ActionsPermissionsRepository) GetEnabled() bool {
+	if a == nil || a.Enabled == nil {
+		return false
+	}
+	return *a.Enabled
+}
+
+// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise.
+func (a *ActionsPermissionsRepository) GetSelectedActionsURL() string {
+	if a == nil || a.SelectedActionsURL == nil {
+		return ""
+	}
+	return *a.SelectedActionsURL
+}
+
 // GetURL returns the URL field if it's non-nil, zero value otherwise.
 func (a *AdminEnforcement) GetURL() string {
 	if a == nil || a.URL == nil {
diff --git a/github/orgs_actions_allowed.go b/github/orgs_actions_allowed.go
index 9032d033..687ab2f6 100644
--- a/github/orgs_actions_allowed.go
+++ b/github/orgs_actions_allowed.go
@@ -10,9 +10,9 @@ import (
 	"fmt"
 )
 
-// ActionsAllowed represents selected actions that are allowed in an organization.
+// ActionsAllowed represents selected actions that are allowed.
 //
-// GitHub API docs: https://docs.github.com/en/rest/reference/actions#get-allowed-actions-for-an-organization
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-allowed-actions-and-workflows-for-an-organization--parameters
 type ActionsAllowed struct {
 	GithubOwnedAllowed *bool    `json:"github_owned_allowed,omitempty"`
 	VerifiedAllowed    *bool    `json:"verified_allowed,omitempty"`
diff --git a/github/repos_actions_allowed.go b/github/repos_actions_allowed.go
new file mode 100644
index 00000000..2770fccc
--- /dev/null
+++ b/github/repos_actions_allowed.go
@@ -0,0 +1,49 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+// GetActionsAllowed gets the actions that are allowed in a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#get-allowed-actions-and-workflows-for-a-repository
+func (s *RepositoriesService) GetActionsAllowed(ctx context.Context, org, repo string) (*ActionsAllowed, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	actionsAllowed := new(ActionsAllowed)
+	resp, err := s.client.Do(ctx, req, actionsAllowed)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return actionsAllowed, resp, nil
+}
+
+// EditActionsAllowed sets the actions that are allowed in a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-allowed-actions-and-workflows-for-a-repository
+func (s *RepositoriesService) EditActionsAllowed(ctx context.Context, org, repo string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo)
+	req, err := s.client.NewRequest("PUT", u, actionsAllowed)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	p := new(ActionsAllowed)
+	resp, err := s.client.Do(ctx, req, p)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return p, resp, nil
+}
diff --git a/github/repos_actions_permissions.go b/github/repos_actions_permissions.go
new file mode 100644
index 00000000..bff8c2f5
--- /dev/null
+++ b/github/repos_actions_permissions.go
@@ -0,0 +1,62 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+// ActionsPermissionsRepository represents a policy for repositories and allowed actions in a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-github-actions-permissions-for-a-repository--parameters
+type ActionsPermissionsRepository struct {
+	Enabled            *bool   `json:"enabled,omitempty"`
+	AllowedActions     *string `json:"allowed_actions,omitempty"`
+	SelectedActionsURL *string `json:"selected_actions_url,omitempty"`
+}
+
+func (a ActionsPermissionsRepository) String() string {
+	return Stringify(a)
+}
+
+// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#get-github-actions-permissions-for-a-repository
+func (s *RepositoriesService) GetActionsPermissions(ctx context.Context, owner, repo string) (*ActionsPermissionsRepository, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	permissions := new(ActionsPermissionsRepository)
+	resp, err := s.client.Do(ctx, req, permissions)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return permissions, resp, nil
+}
+
+// EditActionsPermissions sets the permissions policy for repositories and allowed actions in a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-github-actions-permissions-for-a-repository
+func (s *RepositoriesService) EditActionsPermissions(ctx context.Context, owner, repo string, actionsPermissionsRepository ActionsPermissionsRepository) (*ActionsPermissionsRepository, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo)
+	req, err := s.client.NewRequest("PUT", u, actionsPermissionsRepository)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	permissions := new(ActionsPermissionsRepository)
+	resp, err := s.client.Do(ctx, req, permissions)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return permissions, resp, nil
+}


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 39dd2edf..0045ad4b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -46,7 +46,7 @@ jobs:
         echo "::set-output name=go-mod-cache::$(go env GOMODCACHE)"
 
     - name: Cache go modules
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
           ${{ steps.cache-paths.outputs.go-cache }}
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index f0ce54ec..a796fe05 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -73,6 +73,36 @@ func TestActionsPermissions_GetSelectedActionsURL(tt *testing.T) {
 	a.GetSelectedActionsURL()
 }
 
+func TestActionsPermissionsRepository_GetAllowedActions(tt *testing.T) {
+	var zeroValue string
+	a := &ActionsPermissionsRepository{AllowedActions: &zeroValue}
+	a.GetAllowedActions()
+	a = &ActionsPermissionsRepository{}
+	a.GetAllowedActions()
+	a = nil
+	a.GetAllowedActions()
+}
+
+func TestActionsPermissionsRepository_GetEnabled(tt *testing.T) {
+	var zeroValue bool
+	a := &ActionsPermissionsRepository{Enabled: &zeroValue}
+	a.GetEnabled()
+	a = &ActionsPermissionsRepository{}
+	a.GetEnabled()
+	a = nil
+	a.GetEnabled()
+}
+
+func TestActionsPermissionsRepository_GetSelectedActionsURL(tt *testing.T) {
+	var zeroValue string
+	a := &ActionsPermissionsRepository{SelectedActionsURL: &zeroValue}
+	a.GetSelectedActionsURL()
+	a = &ActionsPermissionsRepository{}
+	a.GetSelectedActionsURL()
+	a = nil
+	a.GetSelectedActionsURL()
+}
+
 func TestAdminEnforcement_GetURL(tt *testing.T) {
 	var zeroValue string
 	a := &AdminEnforcement{URL: &zeroValue}
diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go
index c5bbca9d..142baa21 100644
--- a/github/github-stringify_test.go
+++ b/github/github-stringify_test.go
@@ -36,6 +36,18 @@ func TestActionsPermissions_String(t *testing.T) {
 	}
 }
 
+func TestActionsPermissionsRepository_String(t *testing.T) {
+	v := ActionsPermissionsRepository{
+		Enabled:            Bool(false),
+		AllowedActions:     String(""),
+		SelectedActionsURL: String(""),
+	}
+	want := `github.ActionsPermissionsRepository{Enabled:false, AllowedActions:"", SelectedActionsURL:""}`
+	if got := v.String(); got != want {
+		t.Errorf("ActionsPermissionsRepository.String = %v, want %v", got, want)
+	}
+}
+
 func TestAdminStats_String(t *testing.T) {
 	v := AdminStats{
 		Issues:     &IssueStats{},
diff --git a/github/repos_actions_allowed_test.go b/github/repos_actions_allowed_test.go
new file mode 100644
index 00000000..6736f909
--- /dev/null
+++ b/github/repos_actions_allowed_test.go
@@ -0,0 +1,93 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestRepositoryService_GetActionsAllowed(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/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":["a/b"]}`)
+	})
+
+	ctx := context.Background()
+	org, _, err := client.Repositories.GetActionsAllowed(ctx, "o", "r")
+	if err != nil {
+		t.Errorf("Repositories.GetActionsAllowed returned error: %v", err)
+	}
+	want := &ActionsAllowed{GithubOwnedAllowed: Bool(true), VerifiedAllowed: Bool(false), PatternsAllowed: []string{"a/b"}}
+	if !cmp.Equal(org, want) {
+		t.Errorf("Repositories.GetActionsAllowed returned %+v, want %+v", org, want)
+	}
+
+	const methodName = "GetActionsAllowed"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.GetActionsAllowed(ctx, "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetActionsAllowed(ctx, "o", "r")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_EditActionsAllowed(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+	input := &ActionsAllowed{GithubOwnedAllowed: Bool(true), VerifiedAllowed: Bool(false), PatternsAllowed: []string{"a/b"}}
+
+	mux.HandleFunc("/repos/o/r/actions/permissions/selected-actions", func(w http.ResponseWriter, r *http.Request) {
+		v := new(ActionsAllowed)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "PUT")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+
+		fmt.Fprint(w, `{"github_owned_allowed":true, "verified_allowed":false, "patterns_allowed":["a/b"]}`)
+	})
+
+	ctx := context.Background()
+	org, _, err := client.Repositories.EditActionsAllowed(ctx, "o", "r", *input)
+	if err != nil {
+		t.Errorf("Repositories.EditActionsAllowed returned error: %v", err)
+	}
+
+	want := &ActionsAllowed{GithubOwnedAllowed: Bool(true), VerifiedAllowed: Bool(false), PatternsAllowed: []string{"a/b"}}
+	if !cmp.Equal(org, want) {
+		t.Errorf("Repositories.EditActionsAllowed returned %+v, want %+v", org, want)
+	}
+
+	const methodName = "EditActionsAllowed"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.EditActionsAllowed(ctx, "\n", "\n", *input)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.EditActionsAllowed(ctx, "o", "r", *input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
diff --git a/github/repos_actions_permissions_test.go b/github/repos_actions_permissions_test.go
new file mode 100644
index 00000000..1d6012f6
--- /dev/null
+++ b/github/repos_actions_permissions_test.go
@@ -0,0 +1,112 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestRepositoriesService_GetActionsPermissions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/actions/permissions", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{"enabled": true, "allowed_actions": "all"}`)
+	})
+
+	ctx := context.Background()
+	org, _, err := client.Repositories.GetActionsPermissions(ctx, "o", "r")
+	if err != nil {
+		t.Errorf("Repositories.GetActionsPermissions returned error: %v", err)
+	}
+	want := &ActionsPermissionsRepository{Enabled: Bool(true), AllowedActions: String("all")}
+	if !cmp.Equal(org, want) {
+		t.Errorf("Repositories.GetActionsPermissions returned %+v, want %+v", org, want)
+	}
+
+	const methodName = "GetActionsPermissions"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.GetActionsPermissions(ctx, "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetActionsPermissions(ctx, "o", "r")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_EditActionsPermissions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	input := &ActionsPermissionsRepository{Enabled: Bool(true), AllowedActions: String("selected")}
+
+	mux.HandleFunc("/repos/o/r/actions/permissions", func(w http.ResponseWriter, r *http.Request) {
+		v := new(ActionsPermissionsRepository)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "PUT")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+
+		fmt.Fprint(w, `{"enabled": true, "allowed_actions": "selected"}`)
+	})
+
+	ctx := context.Background()
+	org, _, err := client.Repositories.EditActionsPermissions(ctx, "o", "r", *input)
+	if err != nil {
+		t.Errorf("Repositories.EditActionsPermissions returned error: %v", err)
+	}
+
+	want := &ActionsPermissionsRepository{Enabled: Bool(true), AllowedActions: String("selected")}
+	if !cmp.Equal(org, want) {
+		t.Errorf("Repositories.EditActionsPermissions returned %+v, want %+v", org, want)
+	}
+
+	const methodName = "EditActionsPermissions"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.EditActionsPermissions(ctx, "\n", "\n", *input)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.EditActionsPermissions(ctx, "o", "r", *input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestActionsPermissionsRepository_Marshal(t *testing.T) {
+	testJSONMarshal(t, &ActionsPermissions{}, "{}")
+
+	u := &ActionsPermissionsRepository{
+		Enabled:            Bool(true),
+		AllowedActions:     String("all"),
+		SelectedActionsURL: String("someURL"),
+	}
+
+	want := `{
+		"enabled": true,
+		"allowed_actions": "all",
+		"selected_actions_url": "someURL"
+	}`
+
+	testJSONMarshal(t, u, want)
+}