Skip to content

Commit 2c83bd6

Browse files
feat: Add support for remaining Codespaces APIs (#3886)
1 parent ecab7f1 commit 2c83bd6

File tree

4 files changed

+1373
-5
lines changed

4 files changed

+1373
-5
lines changed

github/codespaces.go

Lines changed: 330 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,101 @@ type CreateCodespaceOptions struct {
167167
DisplayName *string `json:"display_name,omitempty"`
168168
// RetentionPeriodMinutes represents the duration in minutes after codespace has gone idle in which it will be deleted.
169169
// Must be integer minutes between 0 and 43200 (30 days).
170-
RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"`
170+
RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"`
171+
Location *string `json:"location,omitempty"`
172+
}
173+
174+
// DevContainer represents a devcontainer configuration in a repository.
175+
type DevContainer struct {
176+
Path string `json:"path"`
177+
Name *string `json:"name,omitempty"`
178+
DisplayName *string `json:"display_name,omitempty"`
179+
}
180+
181+
// DevContainerConfigurations represents a list of devcontainer configurations in a repository.
182+
type DevContainerConfigurations struct {
183+
Devcontainers []*DevContainer `json:"devcontainers"`
184+
TotalCount int64 `json:"total_count"`
185+
}
186+
187+
// CodespaceDefaults represents default settings for a Codespace.
188+
type CodespaceDefaults struct {
189+
Location string `json:"location"`
190+
DevcontainerPath *string `json:"devcontainer_path,omitempty"`
191+
}
192+
193+
// CodespaceDefaultAttributes represents the default attributes for codespaces created by the user with the repository.
194+
type CodespaceDefaultAttributes struct {
195+
BillableOwner *User `json:"billable_owner"`
196+
Defaults *CodespaceDefaults `json:"defaults"`
197+
}
198+
199+
// CodespaceGetDefaultAttributesOptions represents options for getting default attributes for a codespace.
200+
type CodespaceGetDefaultAttributesOptions struct {
201+
// Ref represents the branch or commit to check for a default devcontainer path. If not specified, the default branch will be checked.
202+
Ref *string `url:"ref,omitempty"`
203+
// ClientIP represents an alternative IP for default location auto-detection, such as when proxying a request.
204+
ClientIP *string `url:"client_ip,omitempty"`
205+
}
206+
207+
// CodespacePullRequestOptions represents options for a CodespacePullRequest.
208+
type CodespacePullRequestOptions struct {
209+
// PullRequestNumber represents the pull request number.
210+
PullRequestNumber int64 `json:"pull_request_number"`
211+
// RepositoryID represents the repository ID for this codespace.
212+
RepositoryID int64 `json:"repository_id"`
213+
}
214+
215+
// CodespaceCreateForUserOptions represents options for creating a codespace for the authenticated user.
216+
type CodespaceCreateForUserOptions struct {
217+
PullRequest *CodespacePullRequestOptions `json:"pull_request"`
218+
// RepositoryID represents the repository ID for this codespace.
219+
RepositoryID int64 `json:"repository_id"`
220+
Ref *string `json:"ref,omitempty"`
221+
Geo *string `json:"geo,omitempty"`
222+
ClientIP *string `json:"client_ip,omitempty"`
223+
RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"`
224+
Location *string `json:"location,omitempty"`
225+
Machine *string `json:"machine,omitempty"`
226+
DevcontainerPath *string `json:"devcontainer_path,omitempty"`
227+
MultiRepoPermissionsOptOut *bool `json:"multi_repo_permissions_opt_out,omitempty"`
228+
WorkingDirectory *string `json:"working_directory,omitempty"`
229+
IdleTimeoutMinutes *int `json:"idle_timeout_minutes,omitempty"`
230+
DisplayName *string `json:"display_name,omitempty"`
231+
}
232+
233+
// UpdateCodespaceOptions represents options for updating a codespace.
234+
type UpdateCodespaceOptions struct {
235+
// Machine represents a valid machine to transition this codespace to.
236+
Machine *string `json:"machine,omitempty"`
237+
// RecentFolders represents the recently opened folders inside the codespace.
238+
// It is currently used by the clients to determine the folder path to load the codespace in.
239+
RecentFolders []string `json:"recent_folders,omitempty"`
240+
}
241+
242+
// CodespaceExport represents an export of a codespace.
243+
type CodespaceExport struct {
244+
// Can be one of: `succeeded`, `failed`, `in_progress`.
245+
State *string `json:"state,omitempty"`
246+
CompletedAt *Timestamp `json:"completed_at,omitempty"`
247+
Branch *string `json:"branch,omitempty"`
248+
SHA *string `json:"sha,omitempty"`
249+
ID *string `json:"id,omitempty"`
250+
ExportURL *string `json:"export_url,omitempty"`
251+
HTMLURL *string `json:"html_url,omitempty"`
252+
}
253+
254+
// PublishCodespaceOptions represents options for creating a repository from an unpublished codespace.
255+
type PublishCodespaceOptions struct {
256+
// Name represents the name of the new repository.
257+
Name *string `json:"name,omitempty"`
258+
// Private represents whether the new repository is private. Defaults to false.
259+
Private *bool `json:"private,omitempty"`
260+
}
261+
262+
// CodespacePermissions represents a response indicating whether the permissions defined by a devcontainer have been accepted.
263+
type CodespacePermissions struct {
264+
Accepted bool `json:"accepted"`
171265
}
172266

173267
// CreateInRepo creates a codespace in a repository.
@@ -181,7 +275,6 @@ type CreateCodespaceOptions struct {
181275
//meta:operation POST /repos/{owner}/{repo}/codespaces
182276
func (s *CodespacesService) CreateInRepo(ctx context.Context, owner, repo string, request *CreateCodespaceOptions) (*Codespace, *Response, error) {
183277
u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo)
184-
185278
req, err := s.client.NewRequest("POST", u, request)
186279
if err != nil {
187280
return nil, nil, err
@@ -206,7 +299,6 @@ func (s *CodespacesService) CreateInRepo(ctx context.Context, owner, repo string
206299
//meta:operation POST /user/codespaces/{codespace_name}/start
207300
func (s *CodespacesService) Start(ctx context.Context, codespaceName string) (*Codespace, *Response, error) {
208301
u := fmt.Sprintf("user/codespaces/%v/start", codespaceName)
209-
210302
req, err := s.client.NewRequest("POST", u, nil)
211303
if err != nil {
212304
return nil, nil, err
@@ -231,7 +323,6 @@ func (s *CodespacesService) Start(ctx context.Context, codespaceName string) (*C
231323
//meta:operation POST /user/codespaces/{codespace_name}/stop
232324
func (s *CodespacesService) Stop(ctx context.Context, codespaceName string) (*Codespace, *Response, error) {
233325
u := fmt.Sprintf("user/codespaces/%v/stop", codespaceName)
234-
235326
req, err := s.client.NewRequest("POST", u, nil)
236327
if err != nil {
237328
return nil, nil, err
@@ -256,11 +347,245 @@ func (s *CodespacesService) Stop(ctx context.Context, codespaceName string) (*Co
256347
//meta:operation DELETE /user/codespaces/{codespace_name}
257348
func (s *CodespacesService) Delete(ctx context.Context, codespaceName string) (*Response, error) {
258349
u := fmt.Sprintf("user/codespaces/%v", codespaceName)
259-
260350
req, err := s.client.NewRequest("DELETE", u, nil)
261351
if err != nil {
262352
return nil, err
263353
}
264354

265355
return s.client.Do(ctx, req, nil)
266356
}
357+
358+
// ListDevContainerConfigurations lists devcontainer configurations in a repository for the authenticated user.
359+
//
360+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#list-devcontainer-configurations-in-a-repository-for-the-authenticated-user
361+
//
362+
//meta:operation GET /repos/{owner}/{repo}/codespaces/devcontainers
363+
func (s *CodespacesService) ListDevContainerConfigurations(ctx context.Context, owner, repo string, opts *ListOptions) (*DevContainerConfigurations, *Response, error) {
364+
u := fmt.Sprintf("repos/%v/%v/codespaces/devcontainers", owner, repo)
365+
u, err := addOptions(u, opts)
366+
if err != nil {
367+
return nil, nil, err
368+
}
369+
370+
req, err := s.client.NewRequest("GET", u, nil)
371+
if err != nil {
372+
return nil, nil, err
373+
}
374+
375+
var devcontainers *DevContainerConfigurations
376+
resp, err := s.client.Do(ctx, req, &devcontainers)
377+
if err != nil {
378+
return nil, resp, err
379+
}
380+
381+
return devcontainers, resp, nil
382+
}
383+
384+
// GetDefaultAttributes gets the default attributes for codespaces created by the user with the repository.
385+
//
386+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#get-default-attributes-for-a-codespace
387+
//
388+
//meta:operation GET /repos/{owner}/{repo}/codespaces/new
389+
func (s *CodespacesService) GetDefaultAttributes(ctx context.Context, owner, repo string, opts *CodespaceGetDefaultAttributesOptions) (*CodespaceDefaultAttributes, *Response, error) {
390+
u := fmt.Sprintf("repos/%v/%v/codespaces/new", owner, repo)
391+
u, err := addOptions(u, opts)
392+
if err != nil {
393+
return nil, nil, err
394+
}
395+
396+
req, err := s.client.NewRequest("GET", u, nil)
397+
if err != nil {
398+
return nil, nil, err
399+
}
400+
401+
var attributes *CodespaceDefaultAttributes
402+
resp, err := s.client.Do(ctx, req, &attributes)
403+
if err != nil {
404+
return nil, resp, err
405+
}
406+
407+
return attributes, resp, nil
408+
}
409+
410+
// CheckPermissions checks whether the permissions defined by a given devcontainer configuration have been accepted by the authenticated user.
411+
//
412+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#check-if-permissions-defined-by-a-devcontainer-have-been-accepted-by-the-authenticated-user
413+
//
414+
//meta:operation GET /repos/{owner}/{repo}/codespaces/permissions_check
415+
func (s *CodespacesService) CheckPermissions(ctx context.Context, owner, repo, ref, devcontainerPath string) (*CodespacePermissions, *Response, error) {
416+
u := fmt.Sprintf("repos/%v/%v/codespaces/permissions_check", owner, repo)
417+
u, err := addOptions(u, &struct {
418+
Ref string `url:"ref"`
419+
DevcontainerPath string `url:"devcontainer_path"`
420+
}{
421+
Ref: ref,
422+
DevcontainerPath: devcontainerPath,
423+
})
424+
if err != nil {
425+
return nil, nil, err
426+
}
427+
428+
req, err := s.client.NewRequest("GET", u, nil)
429+
if err != nil {
430+
return nil, nil, err
431+
}
432+
433+
var permissions *CodespacePermissions
434+
resp, err := s.client.Do(ctx, req, &permissions)
435+
if err != nil {
436+
return nil, resp, err
437+
}
438+
439+
return permissions, resp, nil
440+
}
441+
442+
// CreateFromPullRequest creates a codespace owned by the authenticated user for the specified pull request.
443+
//
444+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#create-a-codespace-from-a-pull-request
445+
//
446+
//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces
447+
func (s *CodespacesService) CreateFromPullRequest(ctx context.Context, owner, repo string, pullNumber int, request *CreateCodespaceOptions) (*Codespace, *Response, error) {
448+
u := fmt.Sprintf("repos/%v/%v/pulls/%v/codespaces", owner, repo, pullNumber)
449+
req, err := s.client.NewRequest("POST", u, request)
450+
if err != nil {
451+
return nil, nil, err
452+
}
453+
454+
var codespace *Codespace
455+
resp, err := s.client.Do(ctx, req, &codespace)
456+
if err != nil {
457+
return nil, resp, err
458+
}
459+
460+
return codespace, resp, nil
461+
}
462+
463+
// Create creates a new codespace, owned by the authenticated user.
464+
//
465+
// This method requires either RepositoryId OR a PullRequest but not both.
466+
//
467+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#create-a-codespace-for-the-authenticated-user
468+
//
469+
//meta:operation POST /user/codespaces
470+
func (s *CodespacesService) Create(ctx context.Context, opts *CodespaceCreateForUserOptions) (*Codespace, *Response, error) {
471+
u := "user/codespaces"
472+
req, err := s.client.NewRequest("POST", u, opts)
473+
if err != nil {
474+
return nil, nil, err
475+
}
476+
477+
var codespace *Codespace
478+
resp, err := s.client.Do(ctx, req, &codespace)
479+
if err != nil {
480+
return nil, resp, err
481+
}
482+
483+
return codespace, resp, nil
484+
}
485+
486+
// Get gets information about a user's codespace.
487+
//
488+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#get-a-codespace-for-the-authenticated-user
489+
//
490+
//meta:operation GET /user/codespaces/{codespace_name}
491+
func (s *CodespacesService) Get(ctx context.Context, codespaceName string) (*Codespace, *Response, error) {
492+
u := fmt.Sprintf("user/codespaces/%v", codespaceName)
493+
req, err := s.client.NewRequest("GET", u, nil)
494+
if err != nil {
495+
return nil, nil, err
496+
}
497+
498+
var codespace *Codespace
499+
resp, err := s.client.Do(ctx, req, &codespace)
500+
if err != nil {
501+
return nil, resp, err
502+
}
503+
504+
return codespace, resp, nil
505+
}
506+
507+
// Update updates a codespace owned by the authenticated user.
508+
//
509+
// Only the codespace's machine type and recent folders can be modified using this endpoint.
510+
//
511+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#update-a-codespace-for-the-authenticated-user
512+
//
513+
//meta:operation PATCH /user/codespaces/{codespace_name}
514+
func (s *CodespacesService) Update(ctx context.Context, codespaceName string, opts *UpdateCodespaceOptions) (*Codespace, *Response, error) {
515+
u := fmt.Sprintf("user/codespaces/%v", codespaceName)
516+
req, err := s.client.NewRequest("PATCH", u, opts)
517+
if err != nil {
518+
return nil, nil, err
519+
}
520+
521+
var codespace *Codespace
522+
resp, err := s.client.Do(ctx, req, &codespace)
523+
if err != nil {
524+
return nil, resp, err
525+
}
526+
527+
return codespace, resp, nil
528+
}
529+
530+
// ExportCodespace triggers an export of the specified codespace and returns a URL and ID where the status of the export can be monitored.
531+
//
532+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#export-a-codespace-for-the-authenticated-user
533+
//
534+
//meta:operation POST /user/codespaces/{codespace_name}/exports
535+
func (s *CodespacesService) ExportCodespace(ctx context.Context, codespaceName string) (*CodespaceExport, *Response, error) {
536+
u := fmt.Sprintf("user/codespaces/%v/exports", codespaceName)
537+
req, err := s.client.NewRequest("POST", u, nil)
538+
if err != nil {
539+
return nil, nil, err
540+
}
541+
542+
var codespace *CodespaceExport
543+
resp, err := s.client.Do(ctx, req, &codespace)
544+
if err != nil {
545+
return nil, resp, err
546+
}
547+
548+
return codespace, resp, nil
549+
}
550+
551+
// GetLatestCodespaceExport gets information about an export of a codespace.
552+
//
553+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#get-details-about-a-codespace-export
554+
//
555+
//meta:operation GET /user/codespaces/{codespace_name}/exports/{export_id}
556+
func (s *CodespacesService) GetLatestCodespaceExport(ctx context.Context, codespaceName string) (*CodespaceExport, *Response, error) {
557+
u := fmt.Sprintf("user/codespaces/%v/exports/latest", codespaceName)
558+
req, err := s.client.NewRequest("GET", u, nil)
559+
if err != nil {
560+
return nil, nil, err
561+
}
562+
563+
var codespace *CodespaceExport
564+
resp, err := s.client.Do(ctx, req, &codespace)
565+
if err != nil {
566+
return nil, resp, err
567+
}
568+
569+
return codespace, resp, nil
570+
}
571+
572+
// Publish publishes an unpublished codespace, creating a new repository and assigning it to the codespace.
573+
//
574+
// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#create-a-repository-from-an-unpublished-codespace
575+
//
576+
//meta:operation POST /user/codespaces/{codespace_name}/publish
577+
func (s *CodespacesService) Publish(ctx context.Context, codespaceName string, opts *PublishCodespaceOptions) (*Codespace, *Response, error) {
578+
u := fmt.Sprintf("user/codespaces/%v/publish", codespaceName)
579+
req, err := s.client.NewRequest("POST", u, opts)
580+
if err != nil {
581+
return nil, nil, err
582+
}
583+
584+
var codespace *Codespace
585+
resp, err := s.client.Do(ctx, req, &codespace)
586+
if err != nil {
587+
return nil, resp, err
588+
}
589+
590+
return codespace, resp, nil
591+
}

0 commit comments

Comments
 (0)