From 4aa8c8308db669841a397749b71a731cd5c35e05 Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 28 May 2026 01:33:56 +0000 Subject: [PATCH 1/7] ci: add automated SDK definition sync workflow Adds a GitHub Action that: - Runs daily at 08:00 UTC (also manual/repository_dispatch) - Downloads latest OpenAPI specs from sandbox and controlplane repos - Regenerates TypeScript SDK clients via @hey-api/openapi-ts - Creates a PR if definitions changed, no-op otherwise Tracks: ENG-2667 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 .github/workflows/update-sdk-definitions.yaml diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml new file mode 100644 index 00000000..78f40e7c --- /dev/null +++ b/.github/workflows/update-sdk-definitions.yaml @@ -0,0 +1,108 @@ +name: Update SDK definitions + +on: + schedule: + - cron: "0 8 * * *" # daily at 08:00 UTC + workflow_dispatch: + repository_dispatch: + types: [update-sdk-definitions] + +permissions: + contents: write + pull-requests: write + +jobs: + update-definitions: + name: Regenerate SDK clients from upstream OpenAPI specs + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: main + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Install dependencies + run: bun install + + - name: Regenerate sandbox SDK client + env: + GH_TOKEN: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + run: | + echo "Downloading sandbox definition from blaxel-ai/sandbox" + curl -sf -H "Authorization: token ${GH_TOKEN}" \ + -H "Accept: application/vnd.github.v3.raw" \ + -o ./definition.yml \ + "https://api.github.com/repos/blaxel-ai/sandbox/contents/sandbox-api/docs/openapi.yml?ref=main" + + rm -rf @blaxel/core/src/sandbox/client/types.gen.ts @blaxel/core/src/sandbox/client/sdk.gen.ts + npx @hey-api/openapi-ts@0.66.0 -i ./definition.yml -o ./tmp/ -c @hey-api/client-fetch + cp -r ./tmp/* @blaxel/core/src/sandbox/client + + sed -i 's/from '\''\.\/sdk\.gen'\''/from '\''\.\/sdk\.gen\.js'\''/g' @blaxel/core/src/sandbox/client/index.ts + sed -i 's/from '\''\.\/types\.gen'\''/from '\''\.\/types\.gen\.js'\''/g' @blaxel/core/src/sandbox/client/index.ts + rm -rf ./tmp definition.yml + + - name: Regenerate controlplane SDK client + env: + GH_TOKEN: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + run: | + echo "Downloading controlplane definition from blaxel-ai/controlplane" + curl -sf -H "Authorization: token ${GH_TOKEN}" \ + -H "Accept: application/vnd.github.v3.raw" \ + -o ./definition.yml \ + "https://api.github.com/repos/blaxel-ai/controlplane/contents/api/api/definitions/controlplane.yml?ref=main" + + rm -rf @blaxel/core/src/client/types.gen.ts @blaxel/core/src/client/sdk.gen.ts + npx @hey-api/openapi-ts@0.66.0 -i ./definition.yml -o ./tmp/ -c @hey-api/client-fetch + cp -r ./tmp/* @blaxel/core/src/client + + sed -i 's/from '\''\.\/sdk\.gen'\''/from '\''\.\/sdk\.gen\.js'\''/g' @blaxel/core/src/client/index.ts + sed -i 's/from '\''\.\/types\.gen'\''/from '\''\.\/types\.gen\.js'\''/g' @blaxel/core/src/client/index.ts + sed -i 's/from '\''\.\/types\.gen'\''/from '\''\.\/types\.gen\.js'\''/g' @blaxel/core/src/client/sdk.gen.ts + perl -i -0777 -pe 's/(\{\s*scheme: .bearer.,\s*type: .http.\s*\}),\s*\{\s*scheme: .bearer.,\s*type: .http.\s*\}/$1/g' @blaxel/core/src/client/sdk.gen.ts + sed -i 's/\([A-Za-z_][A-Za-z0-9_]*\)Readable/\1/g' @blaxel/core/src/client/types.gen.ts + sed -i 's/TimeFieldsWritable/TimeFields/g' @blaxel/core/src/client/types.gen.ts + sed -i 's/OwnerFieldsWritable/OwnerFields/g' @blaxel/core/src/client/types.gen.ts + sed -i 's/export type Function =/export type _Function =/g' @blaxel/core/src/client/types.gen.ts + sed -i 's/: Function;/: _Function;/g' @blaxel/core/src/client/types.gen.ts + sed -i 's//<_Function>/g' @blaxel/core/src/client/types.gen.ts + echo '' >> @blaxel/core/src/client/types.gen.ts + echo 'export type DriveStateWritable = DriveState;' >> @blaxel/core/src/client/types.gen.ts + rm -rf ./tmp definition.yml + + - name: Check for changes + id: diff + run: | + if git diff --quiet; then + echo "changed=false" >> "$GITHUB_OUTPUT" + echo "No definition changes detected" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "Definition changes detected:" + git diff --stat + fi + + - name: Create pull request + if: steps.diff.outputs.changed == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + branch: automated/update-sdk-definitions + commit-message: "chore: update SDK definitions from upstream OpenAPI specs" + title: "chore: update SDK definitions from upstream OpenAPI specs" + body: | + Automated PR to sync the generated SDK clients with the latest OpenAPI specs from: + - [`blaxel-ai/sandbox`](https://github.com/blaxel-ai/sandbox) (sandbox client) + - [`blaxel-ai/controlplane`](https://github.com/blaxel-ai/controlplane) (controlplane client) + + Generated by the **Update SDK definitions** workflow. + labels: automated + delete-branch: true From 8326df9b6a7ba54342df73c0e397a4fdce6ee9c1 Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 28 May 2026 01:35:57 +0000 Subject: [PATCH 2/7] ci: use GITHUB_TOKEN for PR creation instead of cross-repo PAT Limits GH_CONTROLPLANE_TOKEN exposure to only the curl steps that need cross-repo read access. GITHUB_TOKEN already has the contents:write and pull-requests:write permissions needed for PR creation on this repo. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index 78f40e7c..da9a97bb 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -94,7 +94,7 @@ jobs: if: steps.diff.outputs.changed == 'true' uses: peter-evans/create-pull-request@v7 with: - token: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} branch: automated/update-sdk-definitions commit-message: "chore: update SDK definitions from upstream OpenAPI specs" title: "chore: update SDK definitions from upstream OpenAPI specs" From 59cf132c9a75be1d6f574caec6b4131cdaa51527 Mon Sep 17 00:00:00 2001 From: Mathis Joffre Date: Wed, 27 May 2026 18:37:07 -0700 Subject: [PATCH 3/7] Update .github/workflows/update-sdk-definitions.yaml Co-authored-by: mendral-app[bot] <233154221+mendral-app[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index da9a97bb..f6d91d7a 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -17,7 +17,8 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main From 07845715733abb9782d2c7536befd1c603bd048b Mon Sep 17 00:00:00 2001 From: Mathis Joffre Date: Wed, 27 May 2026 18:37:29 -0700 Subject: [PATCH 4/7] Apply suggestions from code review Co-authored-by: mendral-app[bot] <233154221+mendral-app[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index f6d91d7a..769d3457 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -23,12 +23,14 @@ jobs: ref: main - name: Setup Bun - uses: oven-sh/setup-bun@v2 + - name: Setup Bun + uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642195f2b846f73898f2e17 # v4.4.0 with: node-version: "22" + node-version: "22" - name: Install dependencies run: bun install @@ -93,7 +95,9 @@ jobs: - name: Create pull request if: steps.diff.outputs.changed == 'true' - uses: peter-evans/create-pull-request@v7 + - name: Create pull request + if: steps.diff.outputs.changed == 'true' + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: token: ${{ secrets.GITHUB_TOKEN }} branch: automated/update-sdk-definitions From 43c8ab6cf8ab46d5094262d82b55c86757d81876 Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 28 May 2026 01:41:27 +0000 Subject: [PATCH 5/7] ci: fix duplicate YAML lines and use git status --porcelain - Remove duplicate step name and property lines introduced by manual edits - Switch from git diff --quiet to git status --porcelain to also detect untracked files from cp -r Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index 769d3457..aa14a002 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -16,13 +16,11 @@ jobs: name: Regenerate SDK clients from upstream OpenAPI specs runs-on: ubuntu-latest steps: - - name: Checkout - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main - - name: Setup Bun - name: Setup Bun uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2 @@ -30,7 +28,6 @@ jobs: uses: actions/setup-node@49933ea5288caeca8642195f2b846f73898f2e17 # v4.4.0 with: node-version: "22" - node-version: "22" - name: Install dependencies run: bun install @@ -84,17 +81,15 @@ jobs: - name: Check for changes id: diff run: | - if git diff --quiet; then + if [ -z "$(git status --porcelain)" ]; then echo "changed=false" >> "$GITHUB_OUTPUT" echo "No definition changes detected" else echo "changed=true" >> "$GITHUB_OUTPUT" echo "Definition changes detected:" - git diff --stat + git status --short fi - - name: Create pull request - if: steps.diff.outputs.changed == 'true' - name: Create pull request if: steps.diff.outputs.changed == 'true' uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 From 4925f72fc4e2102b55d1a68115b52984a57c4f16 Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 28 May 2026 01:43:27 +0000 Subject: [PATCH 6/7] ci: use GITHUB_TOKEN for cross-repo reads (same org) No separate PAT needed since repos are in the same GitHub org. GITHUB_TOKEN has sufficient read access to blaxel-ai/sandbox and blaxel-ai/controlplane. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index aa14a002..30f04f99 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -34,7 +34,7 @@ jobs: - name: Regenerate sandbox SDK client env: - GH_TOKEN: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Downloading sandbox definition from blaxel-ai/sandbox" curl -sf -H "Authorization: token ${GH_TOKEN}" \ @@ -52,7 +52,7 @@ jobs: - name: Regenerate controlplane SDK client env: - GH_TOKEN: ${{ secrets.GH_CONTROLPLANE_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Downloading controlplane definition from blaxel-ai/controlplane" curl -sf -H "Authorization: token ${GH_TOKEN}" \ From 0b9dd4f203b6e8b88939e50136e296d5b667b955 Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 28 May 2026 01:48:51 +0000 Subject: [PATCH 7/7] ci: use public endpoints for spec downloads - Sandbox: raw.githubusercontent.com (public repo) - Controlplane: api.blaxel.ai/v0/openapi/controlplane.yml (public API) No auth tokens needed for either download. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/update-sdk-definitions.yaml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/update-sdk-definitions.yaml b/.github/workflows/update-sdk-definitions.yaml index 30f04f99..7bcdb22d 100644 --- a/.github/workflows/update-sdk-definitions.yaml +++ b/.github/workflows/update-sdk-definitions.yaml @@ -33,14 +33,10 @@ jobs: run: bun install - name: Regenerate sandbox SDK client - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Downloading sandbox definition from blaxel-ai/sandbox" - curl -sf -H "Authorization: token ${GH_TOKEN}" \ - -H "Accept: application/vnd.github.v3.raw" \ - -o ./definition.yml \ - "https://api.github.com/repos/blaxel-ai/sandbox/contents/sandbox-api/docs/openapi.yml?ref=main" + curl -sf -o ./definition.yml \ + "https://raw.githubusercontent.com/blaxel-ai/sandbox/refs/heads/main/sandbox-api/docs/openapi.yml" rm -rf @blaxel/core/src/sandbox/client/types.gen.ts @blaxel/core/src/sandbox/client/sdk.gen.ts npx @hey-api/openapi-ts@0.66.0 -i ./definition.yml -o ./tmp/ -c @hey-api/client-fetch @@ -51,14 +47,10 @@ jobs: rm -rf ./tmp definition.yml - name: Regenerate controlplane SDK client - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Downloading controlplane definition from blaxel-ai/controlplane" - curl -sf -H "Authorization: token ${GH_TOKEN}" \ - -H "Accept: application/vnd.github.v3.raw" \ - -o ./definition.yml \ - "https://api.github.com/repos/blaxel-ai/controlplane/contents/api/api/definitions/controlplane.yml?ref=main" + curl -sf -o ./definition.yml \ + "https://api.blaxel.ai/v0/openapi/controlplane.yml" rm -rf @blaxel/core/src/client/types.gen.ts @blaxel/core/src/client/sdk.gen.ts npx @hey-api/openapi-ts@0.66.0 -i ./definition.yml -o ./tmp/ -c @hey-api/client-fetch