Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
89 changes: 89 additions & 0 deletions github/codespaces_machines.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2025 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"
)

// Machine represent a description of the machine powering a codespace.
type Machine struct {
Name string `json:"name"`
DisplayName string `json:"display_name"`
OperatingSystem string `json:"operating_system"`
StorageInBytes int64 `json:"storage_in_bytes"`
MemoryInBytes int64 `json:"memory_in_bytes"`
CPUs int64 `json:"cpus"`
// PrebuildAvailability represents whether a prebuild is currently available when creating a codespace for this machine and repository.
// Value will be "null" if prebuilds are not supported or prebuild availability could not be determined.
// Value will be "none" if no prebuild is available.
// Latest values "ready" and "in_progress" indicate the prebuild availability status.
PrebuildAvailability string `json:"prebuild_availability"`
}

// CodespaceMachines represent a list of machines.
type CodespaceMachines struct {
TotalCount int64 `json:"total_count"`
Machines []*Machine `json:"machines"`
}

// ListMachinesOptions represent options for ListMachinesTypesForRepository.
type ListMachinesOptions struct {
// Ref represent the branch or commit to check for prebuild availability and devcontainer restrictions.
Ref *string `json:"ref,omitempty"`
// Location represent the location to check for available machines. Assigned by IP if not provided.
Location *string `json:"location,omitempty"`
// ClientIP represent the IP for location auto-detection when proxying a request
ClientIP *string `json:"client_ip,omitempty"`
}

// ListMachinesTypesForRepository lists the machine types available for a given repository based on its configuration.
//
// GitHub API docs: https://docs.github.com/rest/codespaces/machines#list-available-machine-types-for-a-repository
//
//meta:operation GET /repos/{owner}/{repo}/codespaces/machines
func (s *CodespacesService) ListMachinesTypesForRepository(ctx context.Context, owner, repo string, opts *ListMachinesOptions) (*CodespaceMachines, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/codespaces/machines", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var machines *CodespaceMachines
resp, err := s.client.Do(ctx, req, &machines)
if err != nil {
return nil, resp, err
}

return machines, resp, nil
}

// ListMachinesTypesForCodespace lists the machine types a codespace can transition to use.
//
// GitHub API docs: https://docs.github.com/rest/codespaces/machines#list-machine-types-for-a-codespace
//
//meta:operation GET /user/codespaces/{codespace_name}/machines
func (s *CodespacesService) ListMachinesTypesForCodespace(ctx context.Context, codespaceName string) (*CodespaceMachines, *Response, error) {
u := fmt.Sprintf("user/codespaces/%v/machines", codespaceName)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var machines *CodespaceMachines
resp, err := s.client.Do(ctx, req, &machines)
if err != nil {
return nil, resp, err
}

return machines, resp, nil
}
141 changes: 141 additions & 0 deletions github/codespaces_machines_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright 2025 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 (
"fmt"
"net/http"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestCodespacesService_ListMachinesTypesForRepository(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/repos/owner/repo/codespaces/machines", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")

fmt.Fprint(w, `{
"total_count": 1,
"machines": [
{
"name": "standardLinux",
"display_name": "4 cores, 8 GB RAM, 64 GB storage",
"operating_system": "linux",
"storage_in_bytes": 68719476736,
"memory_in_bytes": 17179869184,
"cpus": 4,
"prebuild_availability": "ready"
}
]
}`)
})

ctx := t.Context()
opt := &ListMachinesOptions{
Ref: Ptr("main"),
Location: Ptr("WestUs2"),
ClientIP: Ptr("1.2.3.4"),
}

got, _, err := client.Codespaces.ListMachinesTypesForRepository(
ctx,
"owner",
"repo",
opt,
)
if err != nil {
t.Fatalf("Codespaces.ListMachinesTypesForRepository returned error: %v", err)
}

want := &CodespaceMachines{
TotalCount: 1,
Machines: []*Machine{
{
Name: "standardLinux",
DisplayName: "4 cores, 8 GB RAM, 64 GB storage",
OperatingSystem: "linux",
StorageInBytes: 68719476736,
MemoryInBytes: 17179869184,
CPUs: 4,
PrebuildAvailability: "ready",
},
},
}

if !cmp.Equal(got, want) {
t.Errorf("Codespaces.ListMachinesTypesForRepository returned %+v, want %+v", got, want)
}

const methodName = "ListMachinesTypesForRepository"
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Codespaces.ListMachinesTypesForRepository(ctx, "/n", "/n", opt)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestCodespacesService_ListMachinesTypesForCodespace(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/user/codespaces/codespace_1/machines", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")

fmt.Fprint(w, `{
"total_count": 1,
"machines": [
{
"name": "standardLinux",
"display_name": "4 cores, 8 GB RAM, 64 GB storage",
"operating_system": "linux",
"storage_in_bytes": 68719476736,
"memory_in_bytes": 17179869184,
"cpus": 4,
"prebuild_availability": "ready"
}
]
}`)
})

ctx := t.Context()
got, _, err := client.Codespaces.ListMachinesTypesForCodespace(ctx, "codespace_1")
if err != nil {
t.Fatalf("Codespaces.ListMachinesTypesForCodespace returned error: %v", err)
}

want := &CodespaceMachines{
TotalCount: 1,
Machines: []*Machine{
{
Name: "standardLinux",
DisplayName: "4 cores, 8 GB RAM, 64 GB storage",
OperatingSystem: "linux",
StorageInBytes: 68719476736,
MemoryInBytes: 17179869184,
CPUs: 4,
PrebuildAvailability: "ready",
},
},
}

if !cmp.Equal(got, want) {
t.Errorf("Codespaces.ListMachinesTypesForCodespace returned %+v, want %+v", got, want)
}

const methodName = "ListMachinesTypesForCodespace"
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Codespaces.ListMachinesTypesForCodespace(ctx, "/n")
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}
24 changes: 24 additions & 0 deletions github/github-accessors.go

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

33 changes: 33 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