From f48c67e05de9363cbf6ac8e5a8d4f448214012df Mon Sep 17 00:00:00 2001 From: Austen Stone Date: Mon, 16 Mar 2026 18:29:20 -0400 Subject: [PATCH 1/4] Add custom image endpoints for GitHub-hosted runners Add 6 new endpoints for managing custom images on GitHub-hosted runners, for both organization and enterprise levels: - ListHostedRunnerCustomImages: GET .../hosted-runners/images/custom - GetHostedRunnerCustomImage: GET .../hosted-runners/images/custom/{id} - DeleteHostedRunnerCustomImage: DELETE .../hosted-runners/images/custom/{id} - ListHostedRunnerCustomImageVersions: GET .../hosted-runners/images/custom/{id}/versions - GetHostedRunnerCustomImageVersion: GET .../hosted-runners/images/custom/{id}/versions/{ver} - DeleteHostedRunnerCustomImageVersion: DELETE .../hosted-runners/images/custom/{id}/versions/{ver} New types: HostedRunnerCustomImage, HostedRunnerCustomImages, HostedRunnerCustomImageVersion, HostedRunnerCustomImageVersions Fixes #XXXX --- github/actions_hosted_runners.go | 146 +++++++++ github/actions_hosted_runners_test.go | 286 ++++++++++++++++++ github/enterprise_actions_hosted_runners.go | 114 +++++++ .../enterprise_actions_hosted_runners_test.go | 286 ++++++++++++++++++ 4 files changed, 832 insertions(+) diff --git a/github/actions_hosted_runners.go b/github/actions_hosted_runners.go index eb805393ff3..096c29cae55 100644 --- a/github/actions_hosted_runners.go +++ b/github/actions_hosted_runners.go @@ -160,6 +160,38 @@ func (s *ActionsService) CreateHostedRunner(ctx context.Context, org string, req return hostedRunner, resp, nil } +// HostedRunnerCustomImage represents a custom image definition for GitHub-hosted runners. +type HostedRunnerCustomImage struct { + ID *int64 `json:"id,omitempty"` + Platform *string `json:"platform,omitempty"` + Name *string `json:"name,omitempty"` + Source *string `json:"source,omitempty"` + VersionsCount *int `json:"versions_count,omitempty"` + TotalVersionsSize *int `json:"total_versions_size,omitempty"` + LatestVersion *string `json:"latest_version,omitempty"` + State *string `json:"state,omitempty"` +} + +// HostedRunnerCustomImages represents a collection of custom images for GitHub-hosted runners. +type HostedRunnerCustomImages struct { + TotalCount int `json:"total_count"` + ImageVersions []*HostedRunnerCustomImage `json:"image_versions"` +} + +// HostedRunnerCustomImageVersion represents a version of a custom image for GitHub-hosted runners. +type HostedRunnerCustomImageVersion struct { + Version *string `json:"version,omitempty"` + SizeGB *int `json:"size_gb,omitempty"` + State *string `json:"state,omitempty"` + CreatedOn *Timestamp `json:"created_on,omitempty"` +} + +// HostedRunnerCustomImageVersions represents a collection of versions of a custom image. +type HostedRunnerCustomImageVersions struct { + TotalCount int `json:"total_count"` + ImageVersions []*HostedRunnerCustomImageVersion `json:"image_versions"` +} + // HostedRunnerImageSpecs represents the details of a GitHub-hosted runner image. type HostedRunnerImageSpecs struct { ID string `json:"id"` @@ -365,3 +397,117 @@ func (s *ActionsService) DeleteHostedRunner(ctx context.Context, org string, run return hostedRunner, resp, nil } + +// ListHostedRunnerCustomImages lists custom images for GitHub-hosted runners in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#list-custom-images-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/custom +func (s *ActionsService) ListHostedRunnerCustomImages(ctx context.Context, org string) (*HostedRunnerCustomImageVersions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + images := new(HostedRunnerCustomImageVersions) + resp, err := s.client.Do(ctx, req, images) + if err != nil { + return nil, resp, err + } + + return images, resp, nil +} + +// GetHostedRunnerCustomImage gets a custom image definition for GitHub-hosted runners in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-a-custom-image-definition-for-github-actions-hosted-runners +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id} +func (s *ActionsService) GetHostedRunnerCustomImage(ctx context.Context, org string, imageDefinitionID int64) (*HostedRunnerCustomImage, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom/%v", org, imageDefinitionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + image := new(HostedRunnerCustomImage) + resp, err := s.client.Do(ctx, req, image) + if err != nil { + return nil, resp, err + } + + return image, resp, nil +} + +// DeleteHostedRunnerCustomImage deletes a custom image from the organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#delete-a-custom-image-from-the-organization +// +//meta:operation DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id} +func (s *ActionsService) DeleteHostedRunnerCustomImage(ctx context.Context, org string, imageDefinitionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom/%v", org, imageDefinitionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListHostedRunnerCustomImageVersions lists image versions of a custom image for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#list-image-versions-of-a-custom-image-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions +func (s *ActionsService) ListHostedRunnerCustomImageVersions(ctx context.Context, org string, imageDefinitionID int64) (*HostedRunnerCustomImageVersions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom/%v/versions", org, imageDefinitionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + versions := new(HostedRunnerCustomImageVersions) + resp, err := s.client.Do(ctx, req, versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// GetHostedRunnerCustomImageVersion gets an image version of a custom image for GitHub-hosted runners in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-an-image-version-of-a-custom-image-for-github-actions-hosted-runners +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version} +func (s *ActionsService) GetHostedRunnerCustomImageVersion(ctx context.Context, org string, imageDefinitionID int64, version string) (*HostedRunnerCustomImageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom/%v/versions/%v", org, imageDefinitionID, version) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + imageVersion := new(HostedRunnerCustomImageVersion) + resp, err := s.client.Do(ctx, req, imageVersion) + if err != nil { + return nil, resp, err + } + + return imageVersion, resp, nil +} + +// DeleteHostedRunnerCustomImageVersion deletes an image version of a custom image from the organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#delete-an-image-version-of-custom-image-from-the-organization +// +//meta:operation DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version} +func (s *ActionsService) DeleteHostedRunnerCustomImageVersion(ctx context.Context, org string, imageDefinitionID int64, version string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom/%v/versions/%v", org, imageDefinitionID, version) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/github/actions_hosted_runners_test.go b/github/actions_hosted_runners_test.go index 44aa82541dc..8efe57eb445 100644 --- a/github/actions_hosted_runners_test.go +++ b/github/actions_hosted_runners_test.go @@ -858,3 +858,289 @@ func TestActionsService_DeleteHostedRunner(t *testing.T) { return resp, err }) } + +func TestActionsService_ListHostedRunnerCustomImages(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "total_count": 2, + "image_versions": [ + { + "version": "1.1.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-09T23:39:01Z" + }, + { + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + } + ] + }`) + }) + + ctx := t.Context() + images, _, err := client.Actions.ListHostedRunnerCustomImages(ctx, "o") + if err != nil { + t.Errorf("Actions.ListHostedRunnerCustomImages returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersions{ + TotalCount: 2, + ImageVersions: []*HostedRunnerCustomImageVersion{ + { + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + }, + { + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + }, + }, + } + + if !cmp.Equal(images, want) { + t.Errorf("Actions.ListHostedRunnerCustomImages returned %+v, want %+v", images, want) + } + + const methodName = "ListHostedRunnerCustomImages" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.ListHostedRunnerCustomImages(ctx, "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Actions.ListHostedRunnerCustomImages(ctx, "o") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestActionsService_GetHostedRunnerCustomImage(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "id": 1, + "platform": "linux-x64", + "name": "CustomImage", + "source": "custom", + "versions_count": 4, + "total_versions_size": 200, + "latest_version": "1.3.0", + "state": "Ready" + }`) + }) + + ctx := t.Context() + image, _, err := client.Actions.GetHostedRunnerCustomImage(ctx, "o", 1) + if err != nil { + t.Errorf("Actions.GetHostedRunnerCustomImage returned error: %v", err) + } + + want := &HostedRunnerCustomImage{ + ID: Ptr(int64(1)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage"), + Source: Ptr("custom"), + VersionsCount: Ptr(4), + TotalVersionsSize: Ptr(200), + LatestVersion: Ptr("1.3.0"), + State: Ptr("Ready"), + } + + if !cmp.Equal(image, want) { + t.Errorf("Actions.GetHostedRunnerCustomImage returned %+v, want %+v", image, want) + } + + const methodName = "GetHostedRunnerCustomImage" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.GetHostedRunnerCustomImage(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Actions.GetHostedRunnerCustomImage(ctx, "o", 1) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestActionsService_DeleteHostedRunnerCustomImage(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom/1", func(_ http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + ctx := t.Context() + _, err := client.Actions.DeleteHostedRunnerCustomImage(ctx, "o", 1) + if err != nil { + t.Errorf("Actions.DeleteHostedRunnerCustomImage returned error: %v", err) + } + + const methodName = "DeleteHostedRunnerCustomImage" + testBadOptions(t, methodName, func() (err error) { + _, err = client.Actions.DeleteHostedRunnerCustomImage(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.Actions.DeleteHostedRunnerCustomImage(ctx, "o", 1) + }) +} + +func TestActionsService_ListHostedRunnerCustomImageVersions(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom/1/versions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "total_count": 2, + "image_versions": [ + { + "version": "1.1.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-09T23:39:01Z" + }, + { + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + } + ] + }`) + }) + + ctx := t.Context() + versions, _, err := client.Actions.ListHostedRunnerCustomImageVersions(ctx, "o", 1) + if err != nil { + t.Errorf("Actions.ListHostedRunnerCustomImageVersions returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersions{ + TotalCount: 2, + ImageVersions: []*HostedRunnerCustomImageVersion{ + { + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + }, + { + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + }, + }, + } + + if !cmp.Equal(versions, want) { + t.Errorf("Actions.ListHostedRunnerCustomImageVersions returned %+v, want %+v", versions, want) + } + + const methodName = "ListHostedRunnerCustomImageVersions" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.ListHostedRunnerCustomImageVersions(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Actions.ListHostedRunnerCustomImageVersions(ctx, "o", 1) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestActionsService_GetHostedRunnerCustomImageVersion(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom/1/versions/1.0.0", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + }`) + }) + + ctx := t.Context() + version, _, err := client.Actions.GetHostedRunnerCustomImageVersion(ctx, "o", 1, "1.0.0") + if err != nil { + t.Errorf("Actions.GetHostedRunnerCustomImageVersion returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersion{ + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + } + + if !cmp.Equal(version, want) { + t.Errorf("Actions.GetHostedRunnerCustomImageVersion returned %+v, want %+v", version, want) + } + + const methodName = "GetHostedRunnerCustomImageVersion" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.GetHostedRunnerCustomImageVersion(ctx, "\n", 1, "1.0.0") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Actions.GetHostedRunnerCustomImageVersion(ctx, "o", 1, "1.0.0") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestActionsService_DeleteHostedRunnerCustomImageVersion(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/actions/hosted-runners/images/custom/1/versions/1.0.0", func(_ http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + ctx := t.Context() + _, err := client.Actions.DeleteHostedRunnerCustomImageVersion(ctx, "o", 1, "1.0.0") + if err != nil { + t.Errorf("Actions.DeleteHostedRunnerCustomImageVersion returned error: %v", err) + } + + const methodName = "DeleteHostedRunnerCustomImageVersion" + testBadOptions(t, methodName, func() (err error) { + _, err = client.Actions.DeleteHostedRunnerCustomImageVersion(ctx, "\n", 1, "1.0.0") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.Actions.DeleteHostedRunnerCustomImageVersion(ctx, "o", 1, "1.0.0") + }) +} diff --git a/github/enterprise_actions_hosted_runners.go b/github/enterprise_actions_hosted_runners.go index 7465796445b..c728d6d6b7c 100644 --- a/github/enterprise_actions_hosted_runners.go +++ b/github/enterprise_actions_hosted_runners.go @@ -228,3 +228,117 @@ func (s *EnterpriseService) DeleteHostedRunner(ctx context.Context, enterprise s return hostedRunner, resp, nil } + +// ListHostedRunnerCustomImages lists custom images for GitHub-hosted runners in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#list-custom-images-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/custom +func (s *EnterpriseService) ListHostedRunnerCustomImages(ctx context.Context, enterprise string) (*HostedRunnerCustomImageVersions, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + images := new(HostedRunnerCustomImageVersions) + resp, err := s.client.Do(ctx, req, images) + if err != nil { + return nil, resp, err + } + + return images, resp, nil +} + +// GetHostedRunnerCustomImage gets a custom image definition for GitHub-hosted runners in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-an-enterprise-custom-image-definition-for-github-actions-hosted-runners +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/custom/{image_definition_id} +func (s *EnterpriseService) GetHostedRunnerCustomImage(ctx context.Context, enterprise string, imageDefinitionID int64) (*HostedRunnerCustomImage, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom/%v", enterprise, imageDefinitionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + image := new(HostedRunnerCustomImage) + resp, err := s.client.Do(ctx, req, image) + if err != nil { + return nil, resp, err + } + + return image, resp, nil +} + +// DeleteHostedRunnerCustomImage deletes a custom image from the enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#delete-a-custom-image-from-the-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/hosted-runners/images/custom/{image_definition_id} +func (s *EnterpriseService) DeleteHostedRunnerCustomImage(ctx context.Context, enterprise string, imageDefinitionID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom/%v", enterprise, imageDefinitionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListHostedRunnerCustomImageVersions lists image versions of a custom image for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#list-image-versions-of-a-custom-image-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/custom/{image_definition_id}/versions +func (s *EnterpriseService) ListHostedRunnerCustomImageVersions(ctx context.Context, enterprise string, imageDefinitionID int64) (*HostedRunnerCustomImageVersions, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom/%v/versions", enterprise, imageDefinitionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + versions := new(HostedRunnerCustomImageVersions) + resp, err := s.client.Do(ctx, req, versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// GetHostedRunnerCustomImageVersion gets an image version of a custom image for GitHub-hosted runners in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-an-image-version-of-an-enterprise-custom-image-for-github-actions-hosted-runners +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version} +func (s *EnterpriseService) GetHostedRunnerCustomImageVersion(ctx context.Context, enterprise string, imageDefinitionID int64, version string) (*HostedRunnerCustomImageVersion, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom/%v/versions/%v", enterprise, imageDefinitionID, version) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + imageVersion := new(HostedRunnerCustomImageVersion) + resp, err := s.client.Do(ctx, req, imageVersion) + if err != nil { + return nil, resp, err + } + + return imageVersion, resp, nil +} + +// DeleteHostedRunnerCustomImageVersion deletes an image version of a custom image from the enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#delete-an-image-version-of-custom-image-from-the-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version} +func (s *EnterpriseService) DeleteHostedRunnerCustomImageVersion(ctx context.Context, enterprise string, imageDefinitionID int64, version string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom/%v/versions/%v", enterprise, imageDefinitionID, version) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/github/enterprise_actions_hosted_runners_test.go b/github/enterprise_actions_hosted_runners_test.go index 0d03434f66c..576fc3fe5b5 100644 --- a/github/enterprise_actions_hosted_runners_test.go +++ b/github/enterprise_actions_hosted_runners_test.go @@ -857,3 +857,289 @@ func TestEnterpriseService_DeleteHostedRunner(t *testing.T) { return resp, err }) } + +func TestEnterpriseService_ListHostedRunnerCustomImages(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "total_count": 2, + "image_versions": [ + { + "version": "1.1.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-09T23:39:01Z" + }, + { + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + } + ] + }`) + }) + + ctx := t.Context() + images, _, err := client.Enterprise.ListHostedRunnerCustomImages(ctx, "e") + if err != nil { + t.Errorf("Enterprise.ListHostedRunnerCustomImages returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersions{ + TotalCount: 2, + ImageVersions: []*HostedRunnerCustomImageVersion{ + { + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + }, + { + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + }, + }, + } + + if !cmp.Equal(images, want) { + t.Errorf("Enterprise.ListHostedRunnerCustomImages returned %+v, want %+v", images, want) + } + + const methodName = "ListHostedRunnerCustomImages" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Enterprise.ListHostedRunnerCustomImages(ctx, "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.ListHostedRunnerCustomImages(ctx, "e") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_GetHostedRunnerCustomImage(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "id": 1, + "platform": "linux-x64", + "name": "CustomImage", + "source": "custom", + "versions_count": 4, + "total_versions_size": 200, + "latest_version": "1.3.0", + "state": "Ready" + }`) + }) + + ctx := t.Context() + image, _, err := client.Enterprise.GetHostedRunnerCustomImage(ctx, "e", 1) + if err != nil { + t.Errorf("Enterprise.GetHostedRunnerCustomImage returned error: %v", err) + } + + want := &HostedRunnerCustomImage{ + ID: Ptr(int64(1)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage"), + Source: Ptr("custom"), + VersionsCount: Ptr(4), + TotalVersionsSize: Ptr(200), + LatestVersion: Ptr("1.3.0"), + State: Ptr("Ready"), + } + + if !cmp.Equal(image, want) { + t.Errorf("Enterprise.GetHostedRunnerCustomImage returned %+v, want %+v", image, want) + } + + const methodName = "GetHostedRunnerCustomImage" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Enterprise.GetHostedRunnerCustomImage(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.GetHostedRunnerCustomImage(ctx, "e", 1) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_DeleteHostedRunnerCustomImage(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom/1", func(_ http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + ctx := t.Context() + _, err := client.Enterprise.DeleteHostedRunnerCustomImage(ctx, "e", 1) + if err != nil { + t.Errorf("Enterprise.DeleteHostedRunnerCustomImage returned error: %v", err) + } + + const methodName = "DeleteHostedRunnerCustomImage" + testBadOptions(t, methodName, func() (err error) { + _, err = client.Enterprise.DeleteHostedRunnerCustomImage(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.Enterprise.DeleteHostedRunnerCustomImage(ctx, "e", 1) + }) +} + +func TestEnterpriseService_ListHostedRunnerCustomImageVersions(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom/1/versions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "total_count": 2, + "image_versions": [ + { + "version": "1.1.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-09T23:39:01Z" + }, + { + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + } + ] + }`) + }) + + ctx := t.Context() + versions, _, err := client.Enterprise.ListHostedRunnerCustomImageVersions(ctx, "e", 1) + if err != nil { + t.Errorf("Enterprise.ListHostedRunnerCustomImageVersions returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersions{ + TotalCount: 2, + ImageVersions: []*HostedRunnerCustomImageVersion{ + { + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + }, + { + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + }, + }, + } + + if !cmp.Equal(versions, want) { + t.Errorf("Enterprise.ListHostedRunnerCustomImageVersions returned %+v, want %+v", versions, want) + } + + const methodName = "ListHostedRunnerCustomImageVersions" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Enterprise.ListHostedRunnerCustomImageVersions(ctx, "\n", 1) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.ListHostedRunnerCustomImageVersions(ctx, "e", 1) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_GetHostedRunnerCustomImageVersion(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom/1/versions/1.0.0", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "version": "1.0.0", + "size_gb": 75, + "state": "Ready", + "created_on": "2024-11-08T20:39:01Z" + }`) + }) + + ctx := t.Context() + version, _, err := client.Enterprise.GetHostedRunnerCustomImageVersion(ctx, "e", 1, "1.0.0") + if err != nil { + t.Errorf("Enterprise.GetHostedRunnerCustomImageVersion returned error: %v", err) + } + + want := &HostedRunnerCustomImageVersion{ + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + } + + if !cmp.Equal(version, want) { + t.Errorf("Enterprise.GetHostedRunnerCustomImageVersion returned %+v, want %+v", version, want) + } + + const methodName = "GetHostedRunnerCustomImageVersion" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Enterprise.GetHostedRunnerCustomImageVersion(ctx, "\n", 1, "1.0.0") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.GetHostedRunnerCustomImageVersion(ctx, "e", 1, "1.0.0") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_DeleteHostedRunnerCustomImageVersion(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/actions/hosted-runners/images/custom/1/versions/1.0.0", func(_ http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + ctx := t.Context() + _, err := client.Enterprise.DeleteHostedRunnerCustomImageVersion(ctx, "e", 1, "1.0.0") + if err != nil { + t.Errorf("Enterprise.DeleteHostedRunnerCustomImageVersion returned error: %v", err) + } + + const methodName = "DeleteHostedRunnerCustomImageVersion" + testBadOptions(t, methodName, func() (err error) { + _, err = client.Enterprise.DeleteHostedRunnerCustomImageVersion(ctx, "\n", 1, "1.0.0") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.Enterprise.DeleteHostedRunnerCustomImageVersion(ctx, "e", 1, "1.0.0") + }) +} From ceb848b2bcfaae096270851a1e1d7c10b4718286 Mon Sep 17 00:00:00 2001 From: Austen Stone Date: Mon, 16 Mar 2026 18:53:06 -0400 Subject: [PATCH 2/4] fix: ListHostedRunnerCustomImages return type should be HostedRunnerCustomImages not HostedRunnerCustomImageVersions --- github/actions_hosted_runners.go | 4 +- github/actions_hosted_runners_test.go | 52 ++++++++++++------- github/enterprise_actions_hosted_runners.go | 4 +- .../enterprise_actions_hosted_runners_test.go | 52 ++++++++++++------- 4 files changed, 72 insertions(+), 40 deletions(-) diff --git a/github/actions_hosted_runners.go b/github/actions_hosted_runners.go index 096c29cae55..e996b2b7037 100644 --- a/github/actions_hosted_runners.go +++ b/github/actions_hosted_runners.go @@ -403,14 +403,14 @@ func (s *ActionsService) DeleteHostedRunner(ctx context.Context, org string, run // GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#list-custom-images-for-an-organization // //meta:operation GET /orgs/{org}/actions/hosted-runners/images/custom -func (s *ActionsService) ListHostedRunnerCustomImages(ctx context.Context, org string) (*HostedRunnerCustomImageVersions, *Response, error) { +func (s *ActionsService) ListHostedRunnerCustomImages(ctx context.Context, org string) (*HostedRunnerCustomImages, *Response, error) { u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/custom", org) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } - images := new(HostedRunnerCustomImageVersions) + images := new(HostedRunnerCustomImages) resp, err := s.client.Do(ctx, req, images) if err != nil { return nil, resp, err diff --git a/github/actions_hosted_runners_test.go b/github/actions_hosted_runners_test.go index 8efe57eb445..ada4155db9a 100644 --- a/github/actions_hosted_runners_test.go +++ b/github/actions_hosted_runners_test.go @@ -869,16 +869,24 @@ func TestActionsService_ListHostedRunnerCustomImages(t *testing.T) { "total_count": 2, "image_versions": [ { - "version": "1.1.0", - "size_gb": 75, - "state": "Ready", - "created_on": "2024-11-09T23:39:01Z" + "id": 1, + "platform": "linux-x64", + "name": "CustomImage1", + "source": "custom", + "versions_count": 4, + "total_versions_size": 200, + "latest_version": "1.3.0", + "state": "Ready" }, { - "version": "1.0.0", - "size_gb": 75, - "state": "Ready", - "created_on": "2024-11-08T20:39:01Z" + "id": 2, + "platform": "linux-x64", + "name": "CustomImage2", + "source": "custom", + "versions_count": 2, + "total_versions_size": 150, + "latest_version": "1.0.0", + "state": "Ready" } ] }`) @@ -890,20 +898,28 @@ func TestActionsService_ListHostedRunnerCustomImages(t *testing.T) { t.Errorf("Actions.ListHostedRunnerCustomImages returned error: %v", err) } - want := &HostedRunnerCustomImageVersions{ + want := &HostedRunnerCustomImages{ TotalCount: 2, - ImageVersions: []*HostedRunnerCustomImageVersion{ + ImageVersions: []*HostedRunnerCustomImage{ { - Version: Ptr("1.1.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + ID: Ptr(int64(1)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage1"), + Source: Ptr("custom"), + VersionsCount: Ptr(4), + TotalVersionsSize: Ptr(200), + LatestVersion: Ptr("1.3.0"), + State: Ptr("Ready"), }, { - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + ID: Ptr(int64(2)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage2"), + Source: Ptr("custom"), + VersionsCount: Ptr(2), + TotalVersionsSize: Ptr(150), + LatestVersion: Ptr("1.0.0"), + State: Ptr("Ready"), }, }, } diff --git a/github/enterprise_actions_hosted_runners.go b/github/enterprise_actions_hosted_runners.go index c728d6d6b7c..5d142f2dd35 100644 --- a/github/enterprise_actions_hosted_runners.go +++ b/github/enterprise_actions_hosted_runners.go @@ -234,14 +234,14 @@ func (s *EnterpriseService) DeleteHostedRunner(ctx context.Context, enterprise s // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#list-custom-images-for-an-enterprise // //meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/custom -func (s *EnterpriseService) ListHostedRunnerCustomImages(ctx context.Context, enterprise string) (*HostedRunnerCustomImageVersions, *Response, error) { +func (s *EnterpriseService) ListHostedRunnerCustomImages(ctx context.Context, enterprise string) (*HostedRunnerCustomImages, *Response, error) { u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/custom", enterprise) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } - images := new(HostedRunnerCustomImageVersions) + images := new(HostedRunnerCustomImages) resp, err := s.client.Do(ctx, req, images) if err != nil { return nil, resp, err diff --git a/github/enterprise_actions_hosted_runners_test.go b/github/enterprise_actions_hosted_runners_test.go index 576fc3fe5b5..02b74f0293d 100644 --- a/github/enterprise_actions_hosted_runners_test.go +++ b/github/enterprise_actions_hosted_runners_test.go @@ -868,16 +868,24 @@ func TestEnterpriseService_ListHostedRunnerCustomImages(t *testing.T) { "total_count": 2, "image_versions": [ { - "version": "1.1.0", - "size_gb": 75, - "state": "Ready", - "created_on": "2024-11-09T23:39:01Z" + "id": 1, + "platform": "linux-x64", + "name": "CustomImage1", + "source": "custom", + "versions_count": 4, + "total_versions_size": 200, + "latest_version": "1.3.0", + "state": "Ready" }, { - "version": "1.0.0", - "size_gb": 75, - "state": "Ready", - "created_on": "2024-11-08T20:39:01Z" + "id": 2, + "platform": "linux-x64", + "name": "CustomImage2", + "source": "custom", + "versions_count": 2, + "total_versions_size": 150, + "latest_version": "1.0.0", + "state": "Ready" } ] }`) @@ -889,20 +897,28 @@ func TestEnterpriseService_ListHostedRunnerCustomImages(t *testing.T) { t.Errorf("Enterprise.ListHostedRunnerCustomImages returned error: %v", err) } - want := &HostedRunnerCustomImageVersions{ + want := &HostedRunnerCustomImages{ TotalCount: 2, - ImageVersions: []*HostedRunnerCustomImageVersion{ + ImageVersions: []*HostedRunnerCustomImage{ { - Version: Ptr("1.1.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + ID: Ptr(int64(1)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage1"), + Source: Ptr("custom"), + VersionsCount: Ptr(4), + TotalVersionsSize: Ptr(200), + LatestVersion: Ptr("1.3.0"), + State: Ptr("Ready"), }, { - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + ID: Ptr(int64(2)), + Platform: Ptr("linux-x64"), + Name: Ptr("CustomImage2"), + Source: Ptr("custom"), + VersionsCount: Ptr(2), + TotalVersionsSize: Ptr(150), + LatestVersion: Ptr("1.0.0"), + State: Ptr("Ready"), }, }, } From 29b8b2257e24038a02f60de8f307de3a33678d9f Mon Sep 17 00:00:00 2001 From: Austen Stone Date: Tue, 17 Mar 2026 10:57:06 -0400 Subject: [PATCH 3/4] Use var declaration style and regenerate accessors --- github/actions_hosted_runners.go | 16 +-- github/enterprise_actions_hosted_runners.go | 16 +-- github/github-accessors.go | 96 ++++++++++++++ github/github-accessors_test.go | 132 ++++++++++++++++++++ 4 files changed, 244 insertions(+), 16 deletions(-) diff --git a/github/actions_hosted_runners.go b/github/actions_hosted_runners.go index e996b2b7037..8588cc45b89 100644 --- a/github/actions_hosted_runners.go +++ b/github/actions_hosted_runners.go @@ -410,8 +410,8 @@ func (s *ActionsService) ListHostedRunnerCustomImages(ctx context.Context, org s return nil, nil, err } - images := new(HostedRunnerCustomImages) - resp, err := s.client.Do(ctx, req, images) + var images *HostedRunnerCustomImages + resp, err := s.client.Do(ctx, req, &images) if err != nil { return nil, resp, err } @@ -431,8 +431,8 @@ func (s *ActionsService) GetHostedRunnerCustomImage(ctx context.Context, org str return nil, nil, err } - image := new(HostedRunnerCustomImage) - resp, err := s.client.Do(ctx, req, image) + var image *HostedRunnerCustomImage + resp, err := s.client.Do(ctx, req, &image) if err != nil { return nil, resp, err } @@ -467,8 +467,8 @@ func (s *ActionsService) ListHostedRunnerCustomImageVersions(ctx context.Context return nil, nil, err } - versions := new(HostedRunnerCustomImageVersions) - resp, err := s.client.Do(ctx, req, versions) + var versions *HostedRunnerCustomImageVersions + resp, err := s.client.Do(ctx, req, &versions) if err != nil { return nil, resp, err } @@ -488,8 +488,8 @@ func (s *ActionsService) GetHostedRunnerCustomImageVersion(ctx context.Context, return nil, nil, err } - imageVersion := new(HostedRunnerCustomImageVersion) - resp, err := s.client.Do(ctx, req, imageVersion) + var imageVersion *HostedRunnerCustomImageVersion + resp, err := s.client.Do(ctx, req, &imageVersion) if err != nil { return nil, resp, err } diff --git a/github/enterprise_actions_hosted_runners.go b/github/enterprise_actions_hosted_runners.go index 5d142f2dd35..ad2f3e769fe 100644 --- a/github/enterprise_actions_hosted_runners.go +++ b/github/enterprise_actions_hosted_runners.go @@ -241,8 +241,8 @@ func (s *EnterpriseService) ListHostedRunnerCustomImages(ctx context.Context, en return nil, nil, err } - images := new(HostedRunnerCustomImages) - resp, err := s.client.Do(ctx, req, images) + var images *HostedRunnerCustomImages + resp, err := s.client.Do(ctx, req, &images) if err != nil { return nil, resp, err } @@ -262,8 +262,8 @@ func (s *EnterpriseService) GetHostedRunnerCustomImage(ctx context.Context, ente return nil, nil, err } - image := new(HostedRunnerCustomImage) - resp, err := s.client.Do(ctx, req, image) + var image *HostedRunnerCustomImage + resp, err := s.client.Do(ctx, req, &image) if err != nil { return nil, resp, err } @@ -298,8 +298,8 @@ func (s *EnterpriseService) ListHostedRunnerCustomImageVersions(ctx context.Cont return nil, nil, err } - versions := new(HostedRunnerCustomImageVersions) - resp, err := s.client.Do(ctx, req, versions) + var versions *HostedRunnerCustomImageVersions + resp, err := s.client.Do(ctx, req, &versions) if err != nil { return nil, resp, err } @@ -319,8 +319,8 @@ func (s *EnterpriseService) GetHostedRunnerCustomImageVersion(ctx context.Contex return nil, nil, err } - imageVersion := new(HostedRunnerCustomImageVersion) - resp, err := s.client.Do(ctx, req, imageVersion) + var imageVersion *HostedRunnerCustomImageVersion + resp, err := s.client.Do(ctx, req, &imageVersion) if err != nil { return nil, resp, err } diff --git a/github/github-accessors.go b/github/github-accessors.go index b529e5e4675..db10fdc439a 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -11854,6 +11854,102 @@ func (h *HostedRunner) GetStatus() string { return *h.Status } +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetLatestVersion returns the LatestVersion field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetLatestVersion() string { + if h == nil || h.LatestVersion == nil { + return "" + } + return *h.LatestVersion +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetPlatform returns the Platform field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetPlatform() string { + if h == nil || h.Platform == nil { + return "" + } + return *h.Platform +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetSource() string { + if h == nil || h.Source == nil { + return "" + } + return *h.Source +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetState() string { + if h == nil || h.State == nil { + return "" + } + return *h.State +} + +// GetTotalVersionsSize returns the TotalVersionsSize field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetTotalVersionsSize() int { + if h == nil || h.TotalVersionsSize == nil { + return 0 + } + return *h.TotalVersionsSize +} + +// GetVersionsCount returns the VersionsCount field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImage) GetVersionsCount() int { + if h == nil || h.VersionsCount == nil { + return 0 + } + return *h.VersionsCount +} + +// GetCreatedOn returns the CreatedOn field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImageVersion) GetCreatedOn() Timestamp { + if h == nil || h.CreatedOn == nil { + return Timestamp{} + } + return *h.CreatedOn +} + +// GetSizeGB returns the SizeGB field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImageVersion) GetSizeGB() int { + if h == nil || h.SizeGB == nil { + return 0 + } + return *h.SizeGB +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImageVersion) GetState() string { + if h == nil || h.State == nil { + return "" + } + return *h.State +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImageVersion) GetVersion() string { + if h == nil || h.Version == nil { + return "" + } + return *h.Version +} + // GetVersion returns the Version field if it's non-nil, zero value otherwise. func (h *HostedRunnerImage) GetVersion() string { if h == nil || h.Version == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 84aa1a4190e..c45efc40e7a 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -15416,6 +15416,138 @@ func TestHostedRunner_GetStatus(tt *testing.T) { h.GetStatus() } +func TestHostedRunnerCustomImage_GetID(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + h := &HostedRunnerCustomImage{ID: &zeroValue} + h.GetID() + h = &HostedRunnerCustomImage{} + h.GetID() + h = nil + h.GetID() +} + +func TestHostedRunnerCustomImage_GetLatestVersion(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImage{LatestVersion: &zeroValue} + h.GetLatestVersion() + h = &HostedRunnerCustomImage{} + h.GetLatestVersion() + h = nil + h.GetLatestVersion() +} + +func TestHostedRunnerCustomImage_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImage{Name: &zeroValue} + h.GetName() + h = &HostedRunnerCustomImage{} + h.GetName() + h = nil + h.GetName() +} + +func TestHostedRunnerCustomImage_GetPlatform(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImage{Platform: &zeroValue} + h.GetPlatform() + h = &HostedRunnerCustomImage{} + h.GetPlatform() + h = nil + h.GetPlatform() +} + +func TestHostedRunnerCustomImage_GetSource(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImage{Source: &zeroValue} + h.GetSource() + h = &HostedRunnerCustomImage{} + h.GetSource() + h = nil + h.GetSource() +} + +func TestHostedRunnerCustomImage_GetState(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImage{State: &zeroValue} + h.GetState() + h = &HostedRunnerCustomImage{} + h.GetState() + h = nil + h.GetState() +} + +func TestHostedRunnerCustomImage_GetTotalVersionsSize(tt *testing.T) { + tt.Parallel() + var zeroValue int + h := &HostedRunnerCustomImage{TotalVersionsSize: &zeroValue} + h.GetTotalVersionsSize() + h = &HostedRunnerCustomImage{} + h.GetTotalVersionsSize() + h = nil + h.GetTotalVersionsSize() +} + +func TestHostedRunnerCustomImage_GetVersionsCount(tt *testing.T) { + tt.Parallel() + var zeroValue int + h := &HostedRunnerCustomImage{VersionsCount: &zeroValue} + h.GetVersionsCount() + h = &HostedRunnerCustomImage{} + h.GetVersionsCount() + h = nil + h.GetVersionsCount() +} + +func TestHostedRunnerCustomImageVersion_GetCreatedOn(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + h := &HostedRunnerCustomImageVersion{CreatedOn: &zeroValue} + h.GetCreatedOn() + h = &HostedRunnerCustomImageVersion{} + h.GetCreatedOn() + h = nil + h.GetCreatedOn() +} + +func TestHostedRunnerCustomImageVersion_GetSizeGB(tt *testing.T) { + tt.Parallel() + var zeroValue int + h := &HostedRunnerCustomImageVersion{SizeGB: &zeroValue} + h.GetSizeGB() + h = &HostedRunnerCustomImageVersion{} + h.GetSizeGB() + h = nil + h.GetSizeGB() +} + +func TestHostedRunnerCustomImageVersion_GetState(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImageVersion{State: &zeroValue} + h.GetState() + h = &HostedRunnerCustomImageVersion{} + h.GetState() + h = nil + h.GetState() +} + +func TestHostedRunnerCustomImageVersion_GetVersion(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImageVersion{Version: &zeroValue} + h.GetVersion() + h = &HostedRunnerCustomImageVersion{} + h.GetVersion() + h = nil + h.GetVersion() +} + func TestHostedRunnerImage_GetVersion(tt *testing.T) { tt.Parallel() var zeroValue string From e8a20cb2e559e4f54cf99c5e4a63cd53d8392590 Mon Sep 17 00:00:00 2001 From: Austen Stone Date: Tue, 17 Mar 2026 11:06:57 -0400 Subject: [PATCH 4/4] Fix images JSON tag and add state_details field per review --- github/actions_hosted_runners.go | 13 +++---- github/actions_hosted_runners_test.go | 34 +++++++++++-------- .../enterprise_actions_hosted_runners_test.go | 34 +++++++++++-------- github/github-accessors.go | 8 +++++ github/github-accessors_test.go | 11 ++++++ 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/github/actions_hosted_runners.go b/github/actions_hosted_runners.go index 8588cc45b89..d0eb8f34400 100644 --- a/github/actions_hosted_runners.go +++ b/github/actions_hosted_runners.go @@ -174,16 +174,17 @@ type HostedRunnerCustomImage struct { // HostedRunnerCustomImages represents a collection of custom images for GitHub-hosted runners. type HostedRunnerCustomImages struct { - TotalCount int `json:"total_count"` - ImageVersions []*HostedRunnerCustomImage `json:"image_versions"` + TotalCount int `json:"total_count"` + Images []*HostedRunnerCustomImage `json:"images"` } // HostedRunnerCustomImageVersion represents a version of a custom image for GitHub-hosted runners. type HostedRunnerCustomImageVersion struct { - Version *string `json:"version,omitempty"` - SizeGB *int `json:"size_gb,omitempty"` - State *string `json:"state,omitempty"` - CreatedOn *Timestamp `json:"created_on,omitempty"` + Version *string `json:"version,omitempty"` + SizeGB *int `json:"size_gb,omitempty"` + State *string `json:"state,omitempty"` + StateDetails *string `json:"state_details,omitempty"` + CreatedOn *Timestamp `json:"created_on,omitempty"` } // HostedRunnerCustomImageVersions represents a collection of versions of a custom image. diff --git a/github/actions_hosted_runners_test.go b/github/actions_hosted_runners_test.go index ada4155db9a..d553fa5639a 100644 --- a/github/actions_hosted_runners_test.go +++ b/github/actions_hosted_runners_test.go @@ -867,7 +867,7 @@ func TestActionsService_ListHostedRunnerCustomImages(t *testing.T) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "total_count": 2, - "image_versions": [ + "images": [ { "id": 1, "platform": "linux-x64", @@ -900,7 +900,7 @@ func TestActionsService_ListHostedRunnerCustomImages(t *testing.T) { want := &HostedRunnerCustomImages{ TotalCount: 2, - ImageVersions: []*HostedRunnerCustomImage{ + Images: []*HostedRunnerCustomImage{ { ID: Ptr(int64(1)), Platform: Ptr("linux-x64"), @@ -1035,12 +1035,14 @@ func TestActionsService_ListHostedRunnerCustomImageVersions(t *testing.T) { "version": "1.1.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-09T23:39:01Z" }, { "version": "1.0.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-08T20:39:01Z" } ] @@ -1057,16 +1059,18 @@ func TestActionsService_ListHostedRunnerCustomImageVersions(t *testing.T) { TotalCount: 2, ImageVersions: []*HostedRunnerCustomImageVersion{ { - Version: Ptr("1.1.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, }, { - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, }, }, } @@ -1100,6 +1104,7 @@ func TestActionsService_GetHostedRunnerCustomImageVersion(t *testing.T) { "version": "1.0.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-08T20:39:01Z" }`) }) @@ -1111,10 +1116,11 @@ func TestActionsService_GetHostedRunnerCustomImageVersion(t *testing.T) { } want := &HostedRunnerCustomImageVersion{ - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, } if !cmp.Equal(version, want) { diff --git a/github/enterprise_actions_hosted_runners_test.go b/github/enterprise_actions_hosted_runners_test.go index 02b74f0293d..cd25bea0295 100644 --- a/github/enterprise_actions_hosted_runners_test.go +++ b/github/enterprise_actions_hosted_runners_test.go @@ -866,7 +866,7 @@ func TestEnterpriseService_ListHostedRunnerCustomImages(t *testing.T) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "total_count": 2, - "image_versions": [ + "images": [ { "id": 1, "platform": "linux-x64", @@ -899,7 +899,7 @@ func TestEnterpriseService_ListHostedRunnerCustomImages(t *testing.T) { want := &HostedRunnerCustomImages{ TotalCount: 2, - ImageVersions: []*HostedRunnerCustomImage{ + Images: []*HostedRunnerCustomImage{ { ID: Ptr(int64(1)), Platform: Ptr("linux-x64"), @@ -1034,12 +1034,14 @@ func TestEnterpriseService_ListHostedRunnerCustomImageVersions(t *testing.T) { "version": "1.1.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-09T23:39:01Z" }, { "version": "1.0.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-08T20:39:01Z" } ] @@ -1056,16 +1058,18 @@ func TestEnterpriseService_ListHostedRunnerCustomImageVersions(t *testing.T) { TotalCount: 2, ImageVersions: []*HostedRunnerCustomImageVersion{ { - Version: Ptr("1.1.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, + Version: Ptr("1.1.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 9, 23, 39, 1, 0, time.UTC)}, }, { - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, }, }, } @@ -1099,6 +1103,7 @@ func TestEnterpriseService_GetHostedRunnerCustomImageVersion(t *testing.T) { "version": "1.0.0", "size_gb": 75, "state": "Ready", + "state_details": "None", "created_on": "2024-11-08T20:39:01Z" }`) }) @@ -1110,10 +1115,11 @@ func TestEnterpriseService_GetHostedRunnerCustomImageVersion(t *testing.T) { } want := &HostedRunnerCustomImageVersion{ - Version: Ptr("1.0.0"), - SizeGB: Ptr(75), - State: Ptr("Ready"), - CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, + Version: Ptr("1.0.0"), + SizeGB: Ptr(75), + State: Ptr("Ready"), + StateDetails: Ptr("None"), + CreatedOn: &Timestamp{time.Date(2024, 11, 8, 20, 39, 1, 0, time.UTC)}, } if !cmp.Equal(version, want) { diff --git a/github/github-accessors.go b/github/github-accessors.go index db10fdc439a..c6ef2d73706 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -11942,6 +11942,14 @@ func (h *HostedRunnerCustomImageVersion) GetState() string { return *h.State } +// GetStateDetails returns the StateDetails field if it's non-nil, zero value otherwise. +func (h *HostedRunnerCustomImageVersion) GetStateDetails() string { + if h == nil || h.StateDetails == nil { + return "" + } + return *h.StateDetails +} + // GetVersion returns the Version field if it's non-nil, zero value otherwise. func (h *HostedRunnerCustomImageVersion) GetVersion() string { if h == nil || h.Version == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index c45efc40e7a..0efa179a2a0 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -15537,6 +15537,17 @@ func TestHostedRunnerCustomImageVersion_GetState(tt *testing.T) { h.GetState() } +func TestHostedRunnerCustomImageVersion_GetStateDetails(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerCustomImageVersion{StateDetails: &zeroValue} + h.GetStateDetails() + h = &HostedRunnerCustomImageVersion{} + h.GetStateDetails() + h = nil + h.GetStateDetails() +} + func TestHostedRunnerCustomImageVersion_GetVersion(tt *testing.T) { tt.Parallel() var zeroValue string