Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.11.0"
".": "0.11.1"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 46
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e98d46c55826cdf541a9ee0df04ce92806ac6d4d92957ae79f897270b7d85b23.yml
openapi_spec_hash: 8a1af54fc0a4417165b8a52e6354b685
config_hash: 043ddc54629c6d8b889123770cb4769f
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml
openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e
config_hash: ed56f95781ec9b2e73c97e1a66606071
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## 0.11.1 (2025-09-06)

Full Changelog: [v0.11.0...v0.11.1](https://github.com/onkernel/kernel-go-sdk/compare/v0.11.0...v0.11.1)

### Features

* **api:** add pagination to the deployments endpoint ([9130f8c](https://github.com/onkernel/kernel-go-sdk/commit/9130f8c40783560bc02d5b494c60549dbe092dcd))
* **api:** pagination properties added to response (has_more, next_offset) ([65c5342](https://github.com/onkernel/kernel-go-sdk/commit/65c53429690169c3ca5068b94991af6eba3832ff))
* **api:** update API spec with pagination headers ([ad37eb2](https://github.com/onkernel/kernel-go-sdk/commit/ad37eb2bdc92a4145e5dba9d8ef8b4ad26c9b64a))


### Bug Fixes

* **client:** correctly convert header pagination value to int ([d42bd8a](https://github.com/onkernel/kernel-go-sdk/commit/d42bd8a79dc3f64ea6aa8c3f4239b8cfa8545d82))
* **internal:** unmarshal correctly when there are multiple discriminators ([649203d](https://github.com/onkernel/kernel-go-sdk/commit/649203d6621f6850ac4cb414b04b78c9693d1923))

## 0.11.0 (2025-09-04)

Full Changelog: [v0.10.0...v0.11.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.10.0...v0.11.0)
Expand Down
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/onkernel/kernel-go-sdk@v0.11.0'
go get -u 'github.com/onkernel/kernel-go-sdk@v0.11.1'
```

<!-- x-release-please-end -->
Expand Down Expand Up @@ -289,9 +289,40 @@ This library provides some conveniences for working with paginated list endpoint

You can use `.ListAutoPaging()` methods to iterate through items across all pages:

```go
iter := client.Deployments.ListAutoPaging(context.TODO(), kernel.DeploymentListParams{
AppName: kernel.String("YOUR_APP"),
Limit: kernel.Int(2),
})
// Automatically fetches more pages as needed.
for iter.Next() {
deploymentListResponse := iter.Current()
fmt.Printf("%+v\n", deploymentListResponse)
}
if err := iter.Err(); err != nil {
panic(err.Error())
}
```

Or you can use simple `.List()` methods to fetch a single page and receive a standard response object
with additional helper methods like `.GetNextPage()`, e.g.:

```go
page, err := client.Deployments.List(context.TODO(), kernel.DeploymentListParams{
AppName: kernel.String("YOUR_APP"),
Limit: kernel.Int(2),
})
for page != nil {
for _, deployment := range page.Items {
fmt.Printf("%+v\n", deployment)
}
page, err = page.GetNextPage()
}
if err != nil {
panic(err.Error())
}
```

### Errors

When the API returns a non-success status code, we return an error with type
Expand Down
2 changes: 1 addition & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Methods:

- <code title="post /deployments">client.Deployments.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentNewParams">DeploymentNewParams</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentNewResponse">DeploymentNewResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /deployments/{id}">client.Deployments.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentGetResponse">DeploymentGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /deployments">client.Deployments.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentListParams">DeploymentListParams</a>) ([]<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentListResponse">DeploymentListResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /deployments">client.Deployments.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentListParams">DeploymentListParams</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk/packages/pagination#OffsetPagination">OffsetPagination</a>[<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentListResponse">DeploymentListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /deployments/{id}/events">client.Deployments.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentService.Follow">Follow</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentFollowParams">DeploymentFollowParams</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#DeploymentFollowResponseUnion">DeploymentFollowResponseUnion</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Apps
Expand Down
26 changes: 23 additions & 3 deletions deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/onkernel/kernel-go-sdk/internal/apiquery"
"github.com/onkernel/kernel-go-sdk/internal/requestconfig"
"github.com/onkernel/kernel-go-sdk/option"
"github.com/onkernel/kernel-go-sdk/packages/pagination"
"github.com/onkernel/kernel-go-sdk/packages/param"
"github.com/onkernel/kernel-go-sdk/packages/respjson"
"github.com/onkernel/kernel-go-sdk/packages/ssestream"
Expand Down Expand Up @@ -66,11 +67,26 @@ func (r *DeploymentService) Get(ctx context.Context, id string, opts ...option.R
}

// List deployments. Optionally filter by application name.
func (r *DeploymentService) List(ctx context.Context, query DeploymentListParams, opts ...option.RequestOption) (res *[]DeploymentListResponse, err error) {
func (r *DeploymentService) List(ctx context.Context, query DeploymentListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[DeploymentListResponse], err error) {
var raw *http.Response
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
path := "deployments"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
return
cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
if err != nil {
return nil, err
}
err = cfg.Execute()
if err != nil {
return nil, err
}
res.SetPageConfig(cfg, raw)
return res, nil
}

// List deployments. Optionally filter by application name.
func (r *DeploymentService) ListAutoPaging(ctx context.Context, query DeploymentListParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[DeploymentListResponse] {
return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...))
}

// Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and
Expand Down Expand Up @@ -477,6 +493,10 @@ const (
type DeploymentListParams struct {
// Filter results by application name.
AppName param.Opt[string] `query:"app_name,omitzero" json:"-"`
// Limit the number of deployments to return.
Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
// Offset the number of deployments to return.
Offset param.Opt[int64] `query:"offset,omitzero" json:"-"`
paramObj
}

Expand Down
2 changes: 2 additions & 0 deletions deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func TestDeploymentListWithOptionalParams(t *testing.T) {
)
_, err := client.Deployments.List(context.TODO(), kernel.DeploymentListParams{
AppName: kernel.String("app_name"),
Limit: kernel.Int(1),
Offset: kernel.Int(0),
})
if err != nil {
var apierr *kernel.Error
Expand Down
88 changes: 88 additions & 0 deletions internal/apijson/decodeparam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,36 @@ func init() {
})
}

type FooVariant struct {
Type string `json:"type,required"`
Value string `json:"value,required"`
}

type BarVariant struct {
Type string `json:"type,required"`
Enable bool `json:"enable,required"`
}

type MultiDiscriminatorUnion struct {
OfFoo *FooVariant `json:",inline"`
OfBar *BarVariant `json:",inline"`

paramUnion
}

func init() {
apijson.RegisterDiscriminatedUnion[MultiDiscriminatorUnion]("type", map[string]reflect.Type{
"foo": reflect.TypeOf(FooVariant{}),
"foo_v2": reflect.TypeOf(FooVariant{}),
"bar": reflect.TypeOf(BarVariant{}),
"bar_legacy": reflect.TypeOf(BarVariant{}),
})
}

func (m *MultiDiscriminatorUnion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, m)
}

func (d *DiscriminatedUnion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, d)
}
Expand Down Expand Up @@ -408,3 +438,61 @@ func TestDiscriminatedUnion(t *testing.T) {
})
}
}

func TestMultiDiscriminatorUnion(t *testing.T) {
tests := map[string]struct {
raw string
target MultiDiscriminatorUnion
shouldFail bool
}{
"foo_variant": {
raw: `{"type":"foo","value":"test"}`,
target: MultiDiscriminatorUnion{OfFoo: &FooVariant{
Type: "foo",
Value: "test",
}},
},
"foo_v2_variant": {
raw: `{"type":"foo_v2","value":"test_v2"}`,
target: MultiDiscriminatorUnion{OfFoo: &FooVariant{
Type: "foo_v2",
Value: "test_v2",
}},
},
"bar_variant": {
raw: `{"type":"bar","enable":true}`,
target: MultiDiscriminatorUnion{OfBar: &BarVariant{
Type: "bar",
Enable: true,
}},
},
"bar_legacy_variant": {
raw: `{"type":"bar_legacy","enable":false}`,
target: MultiDiscriminatorUnion{OfBar: &BarVariant{
Type: "bar_legacy",
Enable: false,
}},
},
"invalid_type": {
raw: `{"type":"unknown","value":"test"}`,
target: MultiDiscriminatorUnion{},
shouldFail: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
var dst MultiDiscriminatorUnion
err := json.Unmarshal([]byte(test.raw), &dst)
if err != nil && !test.shouldFail {
t.Fatalf("failed unmarshal with err: %v", err)
}
if err == nil && test.shouldFail {
t.Fatalf("expected unmarshal to fail but it succeeded")
}
if !reflect.DeepEqual(dst, test.target) {
t.Fatalf("failed equality, got %#v but expected %#v", dst, test.target)
}
})
}
}
48 changes: 27 additions & 21 deletions internal/apijson/union.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,10 @@ func RegisterDiscriminatedUnion[T any](key string, mappings map[string]reflect.T

func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {
type variantDecoder struct {
decoder decoderFunc
field reflect.StructField
discriminatorValue any
decoder decoderFunc
field reflect.StructField
}

variants := []variantDecoder{}
decoders := []variantDecoder{}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)

Expand All @@ -53,18 +51,26 @@ func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {
}

decoder := d.typeDecoder(field.Type)
variants = append(variants, variantDecoder{
decoders = append(decoders, variantDecoder{
decoder: decoder,
field: field,
})
}

type discriminatedDecoder struct {
variantDecoder
discriminator any
}
discriminatedDecoders := []discriminatedDecoder{}
unionEntry, discriminated := unionRegistry[t]
for _, unionVariant := range unionEntry.variants {
for i := 0; i < len(variants); i++ {
variant := &variants[i]
if variant.field.Type.Elem() == unionVariant.Type {
variant.discriminatorValue = unionVariant.DiscriminatorValue
for _, variant := range unionEntry.variants {
// For each union variant, find a matching decoder and save it
for _, decoder := range decoders {
if decoder.field.Type.Elem() == variant.Type {
discriminatedDecoders = append(discriminatedDecoders, discriminatedDecoder{
decoder,
variant.DiscriminatorValue,
})
break
}
}
Expand All @@ -73,10 +79,10 @@ func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {
return func(n gjson.Result, v reflect.Value, state *decoderState) error {
if discriminated && n.Type == gjson.JSON && len(unionEntry.discriminatorKey) != 0 {
discriminator := n.Get(unionEntry.discriminatorKey).Value()
for _, variant := range variants {
if discriminator == variant.discriminatorValue {
inner := v.FieldByIndex(variant.field.Index)
return variant.decoder(n, inner, state)
for _, decoder := range discriminatedDecoders {
if discriminator == decoder.discriminator {
inner := v.FieldByIndex(decoder.field.Index)
return decoder.decoder(n, inner, state)
}
}
return errors.New("apijson: was not able to find discriminated union variant")
Expand All @@ -85,15 +91,15 @@ func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {
// Set bestExactness to worse than loose
bestExactness := loose - 1
bestVariant := -1
for i, variant := range variants {
for i, decoder := range decoders {
// Pointers are used to discern JSON object variants from value variants
if n.Type != gjson.JSON && variant.field.Type.Kind() == reflect.Ptr {
if n.Type != gjson.JSON && decoder.field.Type.Kind() == reflect.Ptr {
continue
}

sub := decoderState{strict: state.strict, exactness: exact}
inner := v.FieldByIndex(variant.field.Index)
err := variant.decoder(n, inner, &sub)
inner := v.FieldByIndex(decoder.field.Index)
err := decoder.decoder(n, inner, &sub)
if err != nil {
continue
}
Expand All @@ -116,11 +122,11 @@ func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {
return errors.New("apijson: was not able to coerce type as union strictly")
}

for i := 0; i < len(variants); i++ {
for i := 0; i < len(decoders); i++ {
if i == bestVariant {
continue
}
v.FieldByIndex(variants[i].field.Index).SetZero()
v.FieldByIndex(decoders[i].field.Index).SetZero()
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package internal

const PackageVersion = "0.11.0" // x-release-please-version
const PackageVersion = "0.11.1" // x-release-please-version
Loading