diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3d26904..8f3e0a4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.14.2" + ".": "0.15.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 6bb4af8..b4dc606 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c765f1c4ce1c4dd4ceb371f56bf047aa79af36031ba43cbd68fa16a5fdb9bb3.yml -openapi_spec_hash: e9086f69281360f4e0895c9274a59531 -config_hash: deadfc4d2b0a947673bcf559b5db6e1b +configured_endpoints: 64 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e21f0324774a1762bc2bba0da3a8a6b0d0e74720d7a1c83dec813f9e027fcf58.yml +openapi_spec_hash: f1b636abfd6cb8e7c2ba7ffb8e53b9ba +config_hash: 09a2df23048cb16689c9a390d9e5bc47 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9f937..0155032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.15.0 (2025-10-17) + +Full Changelog: [v0.14.2...v0.15.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.14.2...v0.15.0) + +### Features + +* click mouse, move mouse, screenshot ([b1dcded](https://github.com/onkernel/kernel-go-sdk/commit/b1dcdedf9662f112048d27622a787b2bacb5ac84)) +* Phani/deploy with GitHub url ([5e04228](https://github.com/onkernel/kernel-go-sdk/commit/5e04228a5fdd20381b24b230c64e65761a444300)) + ## 0.14.2 (2025-10-16) Full Changelog: [v0.14.1...v0.14.2](https://github.com/onkernel/kernel-go-sdk/compare/v0.14.1...v0.14.2) diff --git a/README.md b/README.md index 6d5b4dd..ba522c0 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/onkernel/kernel-go-sdk@v0.14.2' +go get -u 'github.com/onkernel/kernel-go-sdk@v0.15.0' ``` @@ -391,20 +391,17 @@ which can be used to wrap any `io.Reader` with the appropriate file name and con // A file from the file system file, err := os.Open("/path/to/file") kernel.DeploymentNewParams{ - EntrypointRelPath: "src/app.py", - File: file, + File: file, } // A file from a string kernel.DeploymentNewParams{ - EntrypointRelPath: "src/app.py", - File: strings.NewReader("my file contents"), + File: strings.NewReader("my file contents"), } // With a custom filename and contentType kernel.DeploymentNewParams{ - EntrypointRelPath: "src/app.py", - File: kernel.File(strings.NewReader(`{"hello": "foo"}`), "file.go", "application/json"), + File: kernel.File(strings.NewReader(`{"hello": "foo"}`), "file.go", "application/json"), } ``` diff --git a/api.md b/api.md index 9c71da3..906226c 100644 --- a/api.md +++ b/api.md @@ -152,6 +152,18 @@ Methods: - client.Browsers.Logs.Stream(ctx context.Context, id string, query kernel.BrowserLogStreamParams) (shared.LogEvent, error) +## Computer + +Methods: + +- client.Browsers.Computer.CaptureScreenshot(ctx context.Context, id string, body kernel.BrowserComputerCaptureScreenshotParams) (http.Response, error) +- client.Browsers.Computer.ClickMouse(ctx context.Context, id string, body kernel.BrowserComputerClickMouseParams) error +- client.Browsers.Computer.DragMouse(ctx context.Context, id string, body kernel.BrowserComputerDragMouseParams) error +- client.Browsers.Computer.MoveMouse(ctx context.Context, id string, body kernel.BrowserComputerMoveMouseParams) error +- client.Browsers.Computer.PressKey(ctx context.Context, id string, body kernel.BrowserComputerPressKeyParams) error +- client.Browsers.Computer.Scroll(ctx context.Context, id string, body kernel.BrowserComputerScrollParams) error +- client.Browsers.Computer.TypeText(ctx context.Context, id string, body kernel.BrowserComputerTypeTextParams) error + # Profiles Methods: diff --git a/browser.go b/browser.go index b5b4222..6e067e8 100644 --- a/browser.go +++ b/browser.go @@ -31,11 +31,12 @@ import ( // automatically. You should not instantiate this service directly, and instead use // the [NewBrowserService] method instead. type BrowserService struct { - Options []option.RequestOption - Replays BrowserReplayService - Fs BrowserFService - Process BrowserProcessService - Logs BrowserLogService + Options []option.RequestOption + Replays BrowserReplayService + Fs BrowserFService + Process BrowserProcessService + Logs BrowserLogService + Computer BrowserComputerService } // NewBrowserService generates a new service that applies the given options to each @@ -48,6 +49,7 @@ func NewBrowserService(opts ...option.RequestOption) (r BrowserService) { r.Fs = NewBrowserFService(opts...) r.Process = NewBrowserProcessService(opts...) r.Logs = NewBrowserLogService(opts...) + r.Computer = NewBrowserComputerService(opts...) return } diff --git a/browsercomputer.go b/browsercomputer.go new file mode 100644 index 0000000..4158a7c --- /dev/null +++ b/browsercomputer.go @@ -0,0 +1,323 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "context" + "errors" + "fmt" + "net/http" + "slices" + + "github.com/onkernel/kernel-go-sdk/internal/apijson" + "github.com/onkernel/kernel-go-sdk/internal/requestconfig" + "github.com/onkernel/kernel-go-sdk/option" + "github.com/onkernel/kernel-go-sdk/packages/param" +) + +// BrowserComputerService contains methods and other services that help with +// interacting with the kernel API. +// +// Note, unlike clients, this service does not read variables from the environment +// automatically. You should not instantiate this service directly, and instead use +// the [NewBrowserComputerService] method instead. +type BrowserComputerService struct { + Options []option.RequestOption +} + +// NewBrowserComputerService generates a new service that applies the given options +// to each request. These options are applied after the parent client's options (if +// there is one), and before any request-specific options. +func NewBrowserComputerService(opts ...option.RequestOption) (r BrowserComputerService) { + r = BrowserComputerService{} + r.Options = opts + return +} + +// Capture a screenshot of the browser instance +func (r *BrowserComputerService) CaptureScreenshot(ctx context.Context, id string, body BrowserComputerCaptureScreenshotParams, opts ...option.RequestOption) (res *http.Response, err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "image/png")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/screenshot", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Simulate a mouse click action on the browser instance +func (r *BrowserComputerService) ClickMouse(ctx context.Context, id string, body BrowserComputerClickMouseParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/click_mouse", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +// Drag the mouse along a path +func (r *BrowserComputerService) DragMouse(ctx context.Context, id string, body BrowserComputerDragMouseParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/drag_mouse", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +// Move the mouse cursor to the specified coordinates on the browser instance +func (r *BrowserComputerService) MoveMouse(ctx context.Context, id string, body BrowserComputerMoveMouseParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/move_mouse", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +// Press one or more keys on the host computer +func (r *BrowserComputerService) PressKey(ctx context.Context, id string, body BrowserComputerPressKeyParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/press_key", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +// Scroll the mouse wheel at a position on the host computer +func (r *BrowserComputerService) Scroll(ctx context.Context, id string, body BrowserComputerScrollParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/scroll", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +// Type text on the browser instance +func (r *BrowserComputerService) TypeText(ctx context.Context, id string, body BrowserComputerTypeTextParams, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/type", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + +type BrowserComputerCaptureScreenshotParams struct { + Region BrowserComputerCaptureScreenshotParamsRegion `json:"region,omitzero"` + paramObj +} + +func (r BrowserComputerCaptureScreenshotParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerCaptureScreenshotParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerCaptureScreenshotParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The properties Height, Width, X, Y are required. +type BrowserComputerCaptureScreenshotParamsRegion struct { + // Height of the region in pixels + Height int64 `json:"height,required"` + // Width of the region in pixels + Width int64 `json:"width,required"` + // X coordinate of the region's top-left corner + X int64 `json:"x,required"` + // Y coordinate of the region's top-left corner + Y int64 `json:"y,required"` + paramObj +} + +func (r BrowserComputerCaptureScreenshotParamsRegion) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerCaptureScreenshotParamsRegion + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerCaptureScreenshotParamsRegion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BrowserComputerClickMouseParams struct { + // X coordinate of the click position + X int64 `json:"x,required"` + // Y coordinate of the click position + Y int64 `json:"y,required"` + // Number of times to repeat the click + NumClicks param.Opt[int64] `json:"num_clicks,omitzero"` + // Mouse button to interact with + // + // Any of "left", "right", "middle", "back", "forward". + Button BrowserComputerClickMouseParamsButton `json:"button,omitzero"` + // Type of click action + // + // Any of "down", "up", "click". + ClickType BrowserComputerClickMouseParamsClickType `json:"click_type,omitzero"` + // Modifier keys to hold during the click + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerClickMouseParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerClickMouseParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerClickMouseParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Mouse button to interact with +type BrowserComputerClickMouseParamsButton string + +const ( + BrowserComputerClickMouseParamsButtonLeft BrowserComputerClickMouseParamsButton = "left" + BrowserComputerClickMouseParamsButtonRight BrowserComputerClickMouseParamsButton = "right" + BrowserComputerClickMouseParamsButtonMiddle BrowserComputerClickMouseParamsButton = "middle" + BrowserComputerClickMouseParamsButtonBack BrowserComputerClickMouseParamsButton = "back" + BrowserComputerClickMouseParamsButtonForward BrowserComputerClickMouseParamsButton = "forward" +) + +// Type of click action +type BrowserComputerClickMouseParamsClickType string + +const ( + BrowserComputerClickMouseParamsClickTypeDown BrowserComputerClickMouseParamsClickType = "down" + BrowserComputerClickMouseParamsClickTypeUp BrowserComputerClickMouseParamsClickType = "up" + BrowserComputerClickMouseParamsClickTypeClick BrowserComputerClickMouseParamsClickType = "click" +) + +type BrowserComputerDragMouseParams struct { + // Ordered list of [x, y] coordinate pairs to move through while dragging. Must + // contain at least 2 points. + Path [][]int64 `json:"path,omitzero,required"` + // Delay in milliseconds between button down and starting to move along the path. + Delay param.Opt[int64] `json:"delay,omitzero"` + // Delay in milliseconds between relative steps while dragging (not the initial + // delay). + StepDelayMs param.Opt[int64] `json:"step_delay_ms,omitzero"` + // Number of relative move steps per segment in the path. Minimum 1. + StepsPerSegment param.Opt[int64] `json:"steps_per_segment,omitzero"` + // Mouse button to drag with + // + // Any of "left", "middle", "right". + Button BrowserComputerDragMouseParamsButton `json:"button,omitzero"` + // Modifier keys to hold during the drag + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerDragMouseParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerDragMouseParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerDragMouseParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Mouse button to drag with +type BrowserComputerDragMouseParamsButton string + +const ( + BrowserComputerDragMouseParamsButtonLeft BrowserComputerDragMouseParamsButton = "left" + BrowserComputerDragMouseParamsButtonMiddle BrowserComputerDragMouseParamsButton = "middle" + BrowserComputerDragMouseParamsButtonRight BrowserComputerDragMouseParamsButton = "right" +) + +type BrowserComputerMoveMouseParams struct { + // X coordinate to move the cursor to + X int64 `json:"x,required"` + // Y coordinate to move the cursor to + Y int64 `json:"y,required"` + // Modifier keys to hold during the move + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerMoveMouseParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerMoveMouseParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerMoveMouseParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BrowserComputerPressKeyParams struct { + // List of key symbols to press. Each item should be a key symbol supported by + // xdotool (see X11 keysym definitions). Examples include "Return", "Shift", + // "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g. + // "Ctrl+t" or "Ctrl+Shift+Tab". + Keys []string `json:"keys,omitzero,required"` + // Duration to hold the keys down in milliseconds. If omitted or 0, keys are + // tapped. + Duration param.Opt[int64] `json:"duration,omitzero"` + // Optional modifier keys to hold during the key press sequence. + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerPressKeyParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerPressKeyParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerPressKeyParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BrowserComputerScrollParams struct { + // X coordinate at which to perform the scroll + X int64 `json:"x,required"` + // Y coordinate at which to perform the scroll + Y int64 `json:"y,required"` + // Horizontal scroll amount. Positive scrolls right, negative scrolls left. + DeltaX param.Opt[int64] `json:"delta_x,omitzero"` + // Vertical scroll amount. Positive scrolls down, negative scrolls up. + DeltaY param.Opt[int64] `json:"delta_y,omitzero"` + // Modifier keys to hold during the scroll + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerScrollParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerScrollParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerScrollParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BrowserComputerTypeTextParams struct { + // Text to type on the browser instance + Text string `json:"text,required"` + // Delay in milliseconds between keystrokes + Delay param.Opt[int64] `json:"delay,omitzero"` + paramObj +} + +func (r BrowserComputerTypeTextParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerTypeTextParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerTypeTextParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} diff --git a/browsercomputer_test.go b/browsercomputer_test.go new file mode 100644 index 0000000..0391cd9 --- /dev/null +++ b/browsercomputer_test.go @@ -0,0 +1,256 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel_test + +import ( + "bytes" + "context" + "errors" + "io" + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/onkernel/kernel-go-sdk" + "github.com/onkernel/kernel-go-sdk/internal/testutil" + "github.com/onkernel/kernel-go-sdk/option" +) + +func TestBrowserComputerCaptureScreenshotWithOptionalParams(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte("abc")) + })) + defer server.Close() + baseURL := server.URL + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + resp, err := client.Browsers.Computer.CaptureScreenshot( + context.TODO(), + "id", + kernel.BrowserComputerCaptureScreenshotParams{ + Region: kernel.BrowserComputerCaptureScreenshotParamsRegion{ + Height: 0, + Width: 0, + X: 0, + Y: 0, + }, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } + defer resp.Body.Close() + + b, err := io.ReadAll(resp.Body) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } + if !bytes.Equal(b, []byte("abc")) { + t.Fatalf("return value not %s: %s", "abc", b) + } +} + +func TestBrowserComputerClickMouseWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.ClickMouse( + context.TODO(), + "id", + kernel.BrowserComputerClickMouseParams{ + X: 0, + Y: 0, + Button: kernel.BrowserComputerClickMouseParamsButtonLeft, + ClickType: kernel.BrowserComputerClickMouseParamsClickTypeDown, + HoldKeys: []string{"string"}, + NumClicks: kernel.Int(0), + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBrowserComputerDragMouseWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.DragMouse( + context.TODO(), + "id", + kernel.BrowserComputerDragMouseParams{ + Path: [][]int64{{0, 0}, {0, 0}}, + Button: kernel.BrowserComputerDragMouseParamsButtonLeft, + Delay: kernel.Int(0), + HoldKeys: []string{"string"}, + StepDelayMs: kernel.Int(0), + StepsPerSegment: kernel.Int(1), + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBrowserComputerMoveMouseWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.MoveMouse( + context.TODO(), + "id", + kernel.BrowserComputerMoveMouseParams{ + X: 0, + Y: 0, + HoldKeys: []string{"string"}, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBrowserComputerPressKeyWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.PressKey( + context.TODO(), + "id", + kernel.BrowserComputerPressKeyParams{ + Keys: []string{"string"}, + Duration: kernel.Int(0), + HoldKeys: []string{"string"}, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBrowserComputerScrollWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.Scroll( + context.TODO(), + "id", + kernel.BrowserComputerScrollParams{ + X: 0, + Y: 0, + DeltaX: kernel.Int(0), + DeltaY: kernel.Int(0), + HoldKeys: []string{"string"}, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBrowserComputerTypeTextWithOptionalParams(t *testing.T) { + t.Skip("Prism tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.Browsers.Computer.TypeText( + context.TODO(), + "id", + kernel.BrowserComputerTypeTextParams{ + Text: "text", + Delay: kernel.Int(0), + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} diff --git a/deployment.go b/deployment.go index c6d4779..7feea55 100644 --- a/deployment.go +++ b/deployment.go @@ -449,9 +449,7 @@ func (r *DeploymentFollowResponseAppVersionSummaryEvent) UnmarshalJSON(data []by type DeploymentNewParams struct { // Relative path to the entrypoint of the application - EntrypointRelPath string `json:"entrypoint_rel_path,required"` - // ZIP file containing the application source directory - File io.Reader `json:"file,omitzero,required" format:"binary"` + EntrypointRelPath param.Opt[string] `json:"entrypoint_rel_path,omitzero"` // Allow overwriting an existing app version Force param.Opt[bool] `json:"force,omitzero"` // Version of the application. Can be any string. @@ -459,10 +457,14 @@ type DeploymentNewParams struct { // Map of environment variables to set for the deployed application. Each key-value // pair represents an environment variable. EnvVars map[string]string `json:"env_vars,omitzero"` + // ZIP file containing the application source directory + File io.Reader `json:"file,omitzero" format:"binary"` // Region for deployment. Currently we only support "aws.us-east-1a" // // Any of "aws.us-east-1a". Region DeploymentNewParamsRegion `json:"region,omitzero"` + // Source from which to fetch application code. + Source DeploymentNewParamsSource `json:"source,omitzero"` paramObj } @@ -491,6 +493,68 @@ const ( DeploymentNewParamsRegionAwsUsEast1a DeploymentNewParamsRegion = "aws.us-east-1a" ) +// Source from which to fetch application code. +// +// The properties Entrypoint, Ref, Type, URL are required. +type DeploymentNewParamsSource struct { + // Relative path to the application entrypoint within the selected path. + Entrypoint string `json:"entrypoint,required"` + // Git ref (branch, tag, or commit SHA) to fetch. + Ref string `json:"ref,required"` + // Source type identifier. + // + // Any of "github". + Type string `json:"type,omitzero,required"` + // Base repository URL (without blob/tree suffixes). + URL string `json:"url,required"` + // Path within the repo to deploy (omit to use repo root). + Path param.Opt[string] `json:"path,omitzero"` + // Authentication for private repositories. + Auth DeploymentNewParamsSourceAuth `json:"auth,omitzero"` + paramObj +} + +func (r DeploymentNewParamsSource) MarshalJSON() (data []byte, err error) { + type shadow DeploymentNewParamsSource + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *DeploymentNewParamsSource) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[DeploymentNewParamsSource]( + "type", "github", + ) +} + +// Authentication for private repositories. +// +// The properties Token, Method are required. +type DeploymentNewParamsSourceAuth struct { + // GitHub PAT or installation access token + Token string `json:"token,required" format:"password"` + // Auth method + // + // Any of "github_token". + Method string `json:"method,omitzero,required"` + paramObj +} + +func (r DeploymentNewParamsSourceAuth) MarshalJSON() (data []byte, err error) { + type shadow DeploymentNewParamsSourceAuth + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *DeploymentNewParamsSourceAuth) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[DeploymentNewParamsSourceAuth]( + "method", "github_token", + ) +} + type DeploymentListParams struct { // Filter results by application name. AppName param.Opt[string] `query:"app_name,omitzero" json:"-"` diff --git a/deployment_test.go b/deployment_test.go index 81715eb..5472dfb 100644 --- a/deployment_test.go +++ b/deployment_test.go @@ -29,13 +29,24 @@ func TestDeploymentNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Deployments.New(context.TODO(), kernel.DeploymentNewParams{ - EntrypointRelPath: "src/app.py", - File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + EntrypointRelPath: kernel.String("src/app.py"), EnvVars: map[string]string{ - "foo": "string", + "FOO": "bar", + }, + File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Force: kernel.Bool(false), + Region: kernel.DeploymentNewParamsRegionAwsUsEast1a, + Source: kernel.DeploymentNewParamsSource{ + Entrypoint: "src/index.ts", + Ref: "main", + Type: "github", + URL: "https://github.com/org/repo", + Auth: kernel.DeploymentNewParamsSourceAuth{ + Token: "ghs_***", + Method: "github_token", + }, + Path: kernel.String("apps/api"), }, - Force: kernel.Bool(false), - Region: kernel.DeploymentNewParamsRegionAwsUsEast1a, Version: kernel.String("1.0.0"), }) if err != nil { diff --git a/internal/version.go b/internal/version.go index c843cf5..1f338c3 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.14.2" // x-release-please-version +const PackageVersion = "0.15.0" // x-release-please-version