Skip to content

Commit 744c0d4

Browse files
maskarbclaude
andauthored
fix(sdk): sync generator templates with hand-edited SDK output (#884)
## Summary - Update Go SDK generator templates and OpenAPI spec so that running `make generate-sdk` produces output identical to the current hand-edited SDK code - Prevents regeneration from silently dropping features ## Changes ### `generator/templates/go/http_client.go.tmpl` - Add `crypto/tls` import - Add `insecureSkipVerify` field to `Client` struct - Add `WithInsecureSkipVerify()` client option (needed for OpenShift/self-signed certs) - Compile `bearerTokenPattern` regex at package level (was `MustCompile` per call) ### `ambient-api-server/openapi/openapi.sessions.yaml` - Add `DELETE /api/ambient/v1/sessions/{id}` endpoint so the generator emits `Sessions().Delete()` ### `generator/templates/go/types.go.tmpl` - Fix extra blank lines between builder methods by trimming whitespace in `{{range}}` blocks ## Verification After these changes, running the generator produces output that differs from the committed SDK only in the timestamp and spec hash: ``` $ cd generator && go run . -spec ... -go-out ../go-sdk && cd ../go-sdk && go fmt ./... $ git diff --stat go-sdk/ client/client.go | 4 ++-- # timestamp + hash only client/session_api.go | 12 +++--- # Delete moved position + timestamp types/user.go | 4 ++-- # timestamp + hash only ... ``` ## Test plan - [x] `go run . -spec ...` succeeds, reports `Session delete=true` - [x] Generated `client.go` retains `WithInsecureSkipVerify`, `insecureSkipVerify`, compiled regex - [x] Generated `session_api.go` includes `Delete()` method - [x] Generated type files have no extra blank lines after `gofmt` - [x] Only diff from committed code is timestamp/hash and `Delete` method position 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ac84355 commit 744c0d4

40 files changed

Lines changed: 246 additions & 101 deletions
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: SDK Drift Check
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
paths:
7+
- 'components/ambient-sdk/generator/**'
8+
- 'components/ambient-sdk/go-sdk/**'
9+
- 'components/ambient-sdk/python-sdk/**'
10+
- 'components/ambient-sdk/ts-sdk/**'
11+
- 'components/ambient-api-server/openapi/**'
12+
- '.github/workflows/sdk-drift-check.yml'
13+
14+
push:
15+
branches: [main]
16+
paths:
17+
- 'components/ambient-sdk/generator/**'
18+
- 'components/ambient-sdk/go-sdk/**'
19+
- 'components/ambient-sdk/python-sdk/**'
20+
- 'components/ambient-sdk/ts-sdk/**'
21+
- 'components/ambient-api-server/openapi/**'
22+
- '.github/workflows/sdk-drift-check.yml'
23+
24+
workflow_dispatch:
25+
26+
concurrency:
27+
group: sdk-drift-${{ github.event.pull_request.number || github.ref }}
28+
cancel-in-progress: true
29+
30+
jobs:
31+
check-drift:
32+
name: SDK Generator Drift
33+
runs-on: ubuntu-latest
34+
steps:
35+
- name: Checkout code
36+
uses: actions/checkout@v6
37+
38+
- name: Set up Go
39+
uses: actions/setup-go@v5
40+
with:
41+
go-version-file: components/ambient-sdk/generator/go.mod
42+
cache-dependency-path: components/ambient-sdk/generator/go.sum
43+
44+
- name: Regenerate SDK from OpenAPI spec
45+
working-directory: components/ambient-sdk/generator
46+
run: |
47+
go run . \
48+
-spec ../../ambient-api-server/openapi/openapi.yaml \
49+
-go-out ../go-sdk \
50+
-python-out ../python-sdk/ambient_platform \
51+
-ts-out ../ts-sdk
52+
53+
- name: Run gofmt on generated Go code
54+
working-directory: components/ambient-sdk/go-sdk
55+
run: go fmt ./...
56+
57+
- name: Fix trailing newlines (match pre-commit end-of-file-fixer)
58+
run: |
59+
find components/ambient-sdk/go-sdk components/ambient-sdk/python-sdk components/ambient-sdk/ts-sdk \
60+
-type f \( -name '*.go' -o -name '*.py' -o -name '*.ts' \) \
61+
-exec sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' {} +
62+
63+
- name: Check for drift
64+
run: |
65+
# Ignore timestamp and hash lines (they change every run)
66+
# Patterns cover both // (Go/TS) and # (Python) comment styles
67+
DRIFT=$(git diff \
68+
--ignore-matching-lines='Spec SHA256:' \
69+
--ignore-matching-lines='Generated:' \
70+
-- components/ambient-sdk/go-sdk/ \
71+
components/ambient-sdk/python-sdk/ \
72+
components/ambient-sdk/ts-sdk/)
73+
74+
if [ -n "$DRIFT" ]; then
75+
echo "❌ SDK drift detected — regenerated code differs from committed code."
76+
echo ""
77+
echo "This means either:"
78+
echo " 1. A generator template was updated but the SDK was not regenerated"
79+
echo " 2. The OpenAPI spec changed but the SDK was not regenerated"
80+
echo " 3. Generated files were hand-edited (update the templates instead)"
81+
echo ""
82+
echo "Fix: cd components/ambient-sdk && make generate-sdk"
83+
echo ""
84+
echo "Diff:"
85+
echo "$DRIFT"
86+
exit 1
87+
fi
88+
89+
echo "✅ No SDK drift detected"

components/ambient-api-server/openapi/openapi.sessions.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,37 @@ paths:
177177
application/json:
178178
schema:
179179
$ref: 'openapi.yaml#/components/schemas/Error'
180+
delete:
181+
summary: Delete a session by id
182+
security:
183+
- Bearer: []
184+
responses:
185+
'204':
186+
description: Session deleted successfully
187+
'401':
188+
description: Auth token is invalid
189+
content:
190+
application/json:
191+
schema:
192+
$ref: 'openapi.yaml#/components/schemas/Error'
193+
'403':
194+
description: Unauthorized to perform operation
195+
content:
196+
application/json:
197+
schema:
198+
$ref: 'openapi.yaml#/components/schemas/Error'
199+
'404':
200+
description: No session with specified id exists
201+
content:
202+
application/json:
203+
schema:
204+
$ref: 'openapi.yaml#/components/schemas/Error'
205+
'500':
206+
description: Unexpected error deleting session
207+
content:
208+
application/json:
209+
schema:
210+
$ref: 'openapi.yaml#/components/schemas/Error'
180211
parameters:
181212
- $ref: '#/components/parameters/id'
182213
/api/ambient/v1/sessions/{id}/status:

components/ambient-sdk/generator/main.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,15 @@ func loadTemplate(path string) (*template.Template, error) {
341341
}
342342

343343
func executeTemplate(tmpl *template.Template, outPath string, data interface{}) error {
344-
f, err := os.Create(outPath)
345-
if err != nil {
344+
var buf strings.Builder
345+
if err := tmpl.Execute(&buf, data); err != nil {
346346
return err
347347
}
348-
defer func() { _ = f.Close() }()
349348

350-
return tmpl.Execute(f, data)
349+
// Ensure file ends with exactly one newline (match pre-commit end-of-file-fixer)
350+
content := strings.TrimRight(buf.String(), "\n") + "\n"
351+
352+
return os.WriteFile(outPath, []byte(content), 0644)
351353
}
352354

353355
func computeSpecHash(specPath string) (string, error) {

components/ambient-sdk/generator/templates/go/http_client.go.tmpl

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package client
88
import (
99
"bytes"
1010
"context"
11+
"crypto/tls"
1112
"encoding/json"
1213
"fmt"
1314
"io"
@@ -23,12 +24,13 @@ import (
2324
)
2425

2526
type Client struct {
26-
httpClient *http.Client
27-
baseURL string
28-
token string
29-
project string
30-
logger *slog.Logger
31-
userAgent string
27+
httpClient *http.Client
28+
baseURL string
29+
token string
30+
project string
31+
logger *slog.Logger
32+
userAgent string
33+
insecureSkipVerify bool
3234
}
3335

3436
type ClientOption func(*Client)
@@ -39,6 +41,23 @@ func WithTimeout(timeout time.Duration) ClientOption {
3941
}
4042
}
4143

44+
func WithInsecureSkipVerify() ClientOption {
45+
return func(c *Client) {
46+
c.insecureSkipVerify = true
47+
t, ok := c.httpClient.Transport.(*http.Transport)
48+
if !ok || t == nil {
49+
t = http.DefaultTransport.(*http.Transport).Clone()
50+
} else {
51+
t = t.Clone()
52+
}
53+
if t.TLSClientConfig == nil {
54+
t.TLSClientConfig = &tls.Config{MinVersion: tls.VersionTLS12}
55+
}
56+
t.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec
57+
c.httpClient.Transport = t
58+
}
59+
}
60+
4261
func WithLogger(logger *slog.Logger) ClientOption {
4362
return func(c *Client) {
4463
c.logger = logger
@@ -226,7 +245,8 @@ func validateURL(rawURL string) error {
226245
return nil
227246
}
228247

248+
var bearerTokenPattern = regexp.MustCompile(`([Bb]earer\s+)[a-zA-Z0-9\-_~.+/=]+`)
249+
229250
func sanitizeLogURL(rawURL string) string {
230-
tokenPattern := regexp.MustCompile(`([Bb]earer\s+)[a-zA-Z0-9\-_~.+/=]+`)
231-
return tokenPattern.ReplaceAllString(rawURL, "${1}[REDACTED]")
251+
return bearerTokenPattern.ReplaceAllString(rawURL, "${1}[REDACTED]")
232252
}

components/ambient-sdk/generator/templates/go/types.go.tmpl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ func (b *{{$.Resource.Name}}Builder) {{.GoName}}(v {{.GoType}}) *{{$.Resource.Na
4444
b.resource.{{.GoName}} = v
4545
return b
4646
}
47-
{{end}}{{end}}
48-
47+
{{end}}{{- end}}
4948
func (b *{{.Resource.Name}}Builder) Build() (*{{.Resource.Name}}, error) {
5049
{{- range .Resource.Fields}}
5150
{{- if .Required}}
@@ -78,7 +77,6 @@ func (b *{{$.Resource.Name}}PatchBuilder) {{.GoName}}(v {{.GoType}}) *{{$.Resour
7877
return b
7978
}
8079
{{end}}
81-
8280
func (b *{{.Resource.Name}}PatchBuilder) Build() map[string]any {
8381
return b.patch
8482
}
@@ -97,7 +95,6 @@ func (b *{{$.Resource.Name}}StatusPatchBuilder) {{.GoName}}(v {{.GoType}}) *{{$.
9795
return b
9896
}
9997
{{end}}
100-
10198
func (b *{{.Resource.Name}}StatusPatchBuilder) Build() map[string]any {
10299
return b.patch
103100
}

components/ambient-sdk/go-sdk/client/client.go

Lines changed: 12 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ambient-sdk/go-sdk/client/iterator.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ambient-sdk/go-sdk/client/project_api.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ambient-sdk/go-sdk/client/project_settings_api.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ambient-sdk/go-sdk/client/session_api.go

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)