diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..eac1bad83 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,5 @@ +{ + "extensions": [ + "golang.go" + ] +} \ No newline at end of file diff --git a/internal/codespaces/api/api.go b/internal/codespaces/api/api.go index afed04404..ec3a1ff66 100644 --- a/internal/codespaces/api/api.go +++ b/internal/codespaces/api/api.go @@ -579,6 +579,8 @@ type CreateCodespaceParams struct { Branch string Machine string Location string + VSCSTarget string + VSCSTargetURL string PermissionsOptOut bool } @@ -625,6 +627,8 @@ type startCreateRequest struct { Ref string `json:"ref"` Location string `json:"location"` Machine string `json:"machine"` + VSCSTarget string `json:"vscs_target,omitempty"` + VSCSTargetURL string `json:"vscs_target_url,omitempty"` PermissionsOptOut bool `json:"devcontainer_permissions_opt_out"` } @@ -654,8 +658,11 @@ func (a *API) startCreate(ctx context.Context, params *CreateCodespaceParams) (* Ref: params.Branch, Location: params.Location, Machine: params.Machine, + VSCSTarget: params.VSCSTarget, + VSCSTargetURL: params.VSCSTargetURL, PermissionsOptOut: params.PermissionsOptOut, }) + if err != nil { return nil, fmt.Errorf("error marshaling request: %w", err) } diff --git a/pkg/cmd/codespace/create.go b/pkg/cmd/codespace/create.go index b145a6a7d..26156a886 100644 --- a/pkg/cmd/codespace/create.go +++ b/pkg/cmd/codespace/create.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "time" "github.com/AlecAivazis/survey/v2" @@ -47,7 +48,13 @@ func newCreateCmd(app *App) *cobra.Command { // Create creates a new Codespace func (a *App) Create(ctx context.Context, opts createOptions) error { - locationCh := getLocation(ctx, a.apiClient) + + // Overrides for Codespace developers to target test environments + vscsLocation := os.Getenv("VSCS_LOCATION") + vscsTarget := os.Getenv("VSCS_TARGET") + vscsTargetUrl := os.Getenv("VSCS_TARGET_URL") + + locationCh := getLocation(ctx, vscsLocation, a.apiClient) userInputs := struct { Repository string @@ -117,6 +124,8 @@ func (a *App) Create(ctx context.Context, opts createOptions) error { Branch: branch, Machine: machine, Location: locationResult.Location, + VSCSTarget: vscsTarget, + VSCSTargetURL: vscsTargetUrl, IdleTimeoutMinutes: int(opts.idleTimeout.Minutes()), PermissionsOptOut: opts.permissionsOptOut, } @@ -282,9 +291,18 @@ type locationResult struct { Err error } -// getLocation fetches the closest Codespace datacenter region/location to the user. -func getLocation(ctx context.Context, apiClient apiClient) <-chan locationResult { +// getLocation fetches the closest Codespace datacenter +// region/location to the user, unless the 'vscsLocationOverride' override is set +func getLocation(ctx context.Context, vscsLocationOverride string, apiClient apiClient) <-chan locationResult { ch := make(chan locationResult, 1) + + // Developer override is set, return the override + if vscsLocationOverride != "" { + ch <- locationResult{vscsLocationOverride, nil} + return ch + } + + // Dynamically fetch the region location go func() { location, err := apiClient.GetCodespaceRegionLocation(ctx) ch <- locationResult{location, err}