Skip to content
Open
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
19 changes: 19 additions & 0 deletions github/actions_runner_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package github

import (
"context"
"encoding/json"
"fmt"
)

Expand Down Expand Up @@ -59,6 +60,24 @@ type UpdateRunnerGroupRequest struct {
RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"`
SelectedWorkflows []string `json:"selected_workflows,omitempty"`
NetworkConfigurationID *string `json:"network_configuration_id,omitempty"`

// If true, the network configuration is removed by sending null.
// This takes precedence over NetworkConfigurationID.
RemoveNetworkConfiguration bool `json:"-"`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm not mistaken, we can solve this in a different way without resorting to adding a new "hidden" field to the struct...

We simply change line 62 above to this:

NetworkConfigurationID   *string  `json:"network_configuration_id,omitzero"`

and then when the user doesn't initialize the field (it is nil), the field will be ignored.
However, if the user wants to REMOVE the network configuration, they would send new("").

I think we should put this in CONTRIBUTING.md on line 418 right after this comment:

For optional boolean fields where you need to distinguish between `false`
and "not set", use `*bool` with `omitzero`.

}

// MarshalJSON implements the json.Marshaler interface.
func (r UpdateRunnerGroupRequest) MarshalJSON() ([]byte, error) {
type alias UpdateRunnerGroupRequest
if !r.RemoveNetworkConfiguration {
return json.Marshal(alias(r))
}
return json.Marshal(&struct {
alias
NetworkConfigurationID *string `json:"network_configuration_id"`
}{
alias: alias(r),
})
}

// SetRepoAccessRunnerGroupRequest represents a request to replace the list of repositories
Expand Down
88 changes: 88 additions & 0 deletions github/actions_runner_groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package github

import (
"encoding/json"
"fmt"
"net/http"
"testing"
Expand Down Expand Up @@ -289,6 +290,93 @@ func TestActionsService_UpdateOrganizationRunnerGroup(t *testing.T) {
})
}

func TestActionsService_UpdateOrganizationRunnerGroup_NetworkConfiguration(t *testing.T) {
t.Parallel()

tests := []struct {
name string
body UpdateRunnerGroupRequest
want string
}{
{
name: "omitted",
body: UpdateRunnerGroupRequest{},
want: `{}`,
},
{
name: "set",
body: UpdateRunnerGroupRequest{NetworkConfigurationID: new("network-id")},
want: `{"network_configuration_id":"network-id"}`,
},
{
name: "empty string",
body: UpdateRunnerGroupRequest{NetworkConfigurationID: new("")},
want: `{"network_configuration_id":""}`,
},
{
name: "rename only",
body: UpdateRunnerGroupRequest{Name: new("renamed")},
want: `{"name":"renamed"}`,
},
{
name: "remove",
body: UpdateRunnerGroupRequest{RemoveNetworkConfiguration: true},
want: `{"network_configuration_id":null}`,
},
{
name: "remove overrides ID",
body: UpdateRunnerGroupRequest{
NetworkConfigurationID: new("network-id"),
RemoveNetworkConfiguration: true,
},
want: `{"network_configuration_id":null}`,
},
{
name: "remove with other fields",
body: UpdateRunnerGroupRequest{
Name: new("renamed"),
Visibility: new("selected"),
AllowsPublicRepositories: new(false),
RestrictedToWorkflows: new(true),
SelectedWorkflows: []string{"o/r/.github/workflows/build.yml@refs/heads/main"},
RemoveNetworkConfiguration: true,
},
want: `{"name":"renamed","visibility":"selected","allows_public_repositories":false,"restricted_to_workflows":true,"selected_workflows":["o/r/.github/workflows/build.yml@refs/heads/main"],"network_configuration_id":null}`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
before := Stringify(tt.body)
testJSONMarshalOnly(t, tt.body, tt.want)
testJSONMarshalOnly(t, &tt.body, tt.want)
if got := Stringify(tt.body); got != before {
t.Errorf("json.Marshal changed request to %v, want %v", got, before)
}

var want map[string]json.RawMessage
if err := json.Unmarshal([]byte(tt.want), &want); err != nil {
t.Fatalf("json.Unmarshal returned error: %v", err)
}

client, mux, _ := setup(t)
mux.HandleFunc("/orgs/o/actions/runner-groups/2", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
testJSONBody(t, r, want)
fmt.Fprint(w, `{"id":2}`)
})

if _, _, err := client.Actions.UpdateOrganizationRunnerGroup(t.Context(), "o", 2, tt.body); err != nil {
t.Fatalf("Actions.UpdateOrganizationRunnerGroup returned error: %v", err)
}
if got := Stringify(tt.body); got != before {
t.Errorf("Actions.UpdateOrganizationRunnerGroup changed request to %v, want %v", got, before)
}
})
}
}

func TestActionsService_ListRepositoryAccessRunnerGroup(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
Expand Down
19 changes: 19 additions & 0 deletions github/enterprise_actions_runner_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package github

import (
"context"
"encoding/json"
"fmt"
)

Expand Down Expand Up @@ -65,6 +66,24 @@ type UpdateEnterpriseRunnerGroupRequest struct {
RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"`
SelectedWorkflows []string `json:"selected_workflows,omitempty"`
NetworkConfigurationID *string `json:"network_configuration_id,omitempty"`

// If true, the network configuration is removed by sending null.
// This takes precedence over NetworkConfigurationID.
RemoveNetworkConfiguration bool `json:"-"`
}

// MarshalJSON implements the json.Marshaler interface.
func (r UpdateEnterpriseRunnerGroupRequest) MarshalJSON() ([]byte, error) {
type alias UpdateEnterpriseRunnerGroupRequest
if !r.RemoveNetworkConfiguration {
return json.Marshal(alias(r))
}
return json.Marshal(&struct {
alias
NetworkConfigurationID *string `json:"network_configuration_id"`
}{
alias: alias(r),
})
}

// SetOrgAccessRunnerGroupRequest represents a request to replace the list of organizations
Expand Down
88 changes: 88 additions & 0 deletions github/enterprise_actions_runner_groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package github

import (
"encoding/json"
"fmt"
"net/http"
"testing"
Expand Down Expand Up @@ -281,6 +282,93 @@ func TestEnterpriseService_UpdateEnterpriseRunnerGroup(t *testing.T) {
})
}

func TestEnterpriseService_UpdateEnterpriseRunnerGroup_NetworkConfiguration(t *testing.T) {
t.Parallel()

tests := []struct {
name string
body UpdateEnterpriseRunnerGroupRequest
want string
}{
{
name: "omitted",
body: UpdateEnterpriseRunnerGroupRequest{},
want: `{}`,
},
{
name: "set",
body: UpdateEnterpriseRunnerGroupRequest{NetworkConfigurationID: new("network-id")},
want: `{"network_configuration_id":"network-id"}`,
},
{
name: "empty string",
body: UpdateEnterpriseRunnerGroupRequest{NetworkConfigurationID: new("")},
want: `{"network_configuration_id":""}`,
},
{
name: "rename only",
body: UpdateEnterpriseRunnerGroupRequest{Name: new("renamed")},
want: `{"name":"renamed"}`,
},
{
name: "remove",
body: UpdateEnterpriseRunnerGroupRequest{RemoveNetworkConfiguration: true},
want: `{"network_configuration_id":null}`,
},
{
name: "remove overrides ID",
body: UpdateEnterpriseRunnerGroupRequest{
NetworkConfigurationID: new("network-id"),
RemoveNetworkConfiguration: true,
},
want: `{"network_configuration_id":null}`,
},
{
name: "remove with other fields",
body: UpdateEnterpriseRunnerGroupRequest{
Name: new("renamed"),
Visibility: new("selected"),
AllowsPublicRepositories: new(false),
RestrictedToWorkflows: new(true),
SelectedWorkflows: []string{"o/r/.github/workflows/build.yml@refs/heads/main"},
RemoveNetworkConfiguration: true,
},
want: `{"name":"renamed","visibility":"selected","allows_public_repositories":false,"restricted_to_workflows":true,"selected_workflows":["o/r/.github/workflows/build.yml@refs/heads/main"],"network_configuration_id":null}`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
before := Stringify(tt.body)
testJSONMarshalOnly(t, tt.body, tt.want)
testJSONMarshalOnly(t, &tt.body, tt.want)
if got := Stringify(tt.body); got != before {
t.Errorf("json.Marshal changed request to %v, want %v", got, before)
}

var want map[string]json.RawMessage
if err := json.Unmarshal([]byte(tt.want), &want); err != nil {
t.Fatalf("json.Unmarshal returned error: %v", err)
}

client, mux, _ := setup(t)
mux.HandleFunc("/enterprises/o/actions/runner-groups/2", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
testJSONBody(t, r, want)
fmt.Fprint(w, `{"id":2}`)
})

if _, _, err := client.Enterprise.UpdateEnterpriseRunnerGroup(t.Context(), "o", 2, tt.body); err != nil {
t.Fatalf("Enterprise.UpdateEnterpriseRunnerGroup returned error: %v", err)
}
if got := Stringify(tt.body); got != before {
t.Errorf("Enterprise.UpdateEnterpriseRunnerGroup changed request to %v, want %v", got, before)
}
})
}
}

func TestEnterpriseService_ListOrganizationAccessRunnerGroup(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
Expand Down
16 changes: 16 additions & 0 deletions github/github-accessors.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions github/github-accessors_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading