Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 29 additions & 0 deletions .github/workflows/branch-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,32 @@ jobs:

- name: Lint
run: mise run markdown:lint

sdk-typescript:
name: TypeScript SDK
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
container:
image: ghcr.io/nvidia/openshell/ci:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install tools
run: mise install --locked

- name: Check TypeScript SDK
run: mise run sdk:ts:ci

# Exercise the full release publish path (version stamp, dist-tag,
# prepublishOnly, tarball) without uploading. Uses the off-tag dev
# version, which validates the prerelease dist-tag branch too.
- name: Verify publishable artifact (dry-run)
env:
OPENSHELL_NPM_PUBLISH_ARGS: --dry-run
run: |
OPENSHELL_NPM_VERSION="$(uv run python tasks/scripts/release.py get-version --npm)" \
mise run sdk:ts:publish
40 changes: 40 additions & 0 deletions .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
outputs:
python_version: ${{ steps.v.outputs.python }}
cargo_version: ${{ steps.v.outputs.cargo }}
npm_version: ${{ steps.v.outputs.npm }}
deb_version: ${{ steps.v.outputs.deb }}
rpm_version: ${{ steps.v.outputs.rpm_version }}
rpm_release: ${{ steps.v.outputs.rpm_release }}
Expand All @@ -65,6 +66,7 @@ jobs:
set -euo pipefail
echo "python=$(uv run python tasks/scripts/release.py get-version --python)" >> "$GITHUB_OUTPUT"
echo "cargo=$(uv run python tasks/scripts/release.py get-version --cargo)" >> "$GITHUB_OUTPUT"
echo "npm=$(uv run python tasks/scripts/release.py get-version --npm)" >> "$GITHUB_OUTPUT"
echo "deb=$(uv run python tasks/scripts/release.py get-version --deb)" >> "$GITHUB_OUTPUT"
echo "rpm_version=$(uv run python tasks/scripts/release.py get-version --rpm-version)" >> "$GITHUB_OUTPUT"
echo "rpm_release=$(uv run python tasks/scripts/release.py get-version --rpm-release)" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -1067,6 +1069,44 @@ jobs:
working-directory: ./fern
run: fern generate --docs

publish-sdk-typescript:
name: Publish TypeScript SDK
needs: [compute-versions, release]
runs-on: linux-amd64-cpu8
timeout-minutes: 15
permissions:
contents: read
packages: write
container:
image: ghcr.io/nvidia/openshell/ci:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs.tag || github.ref }}

- name: Mark workspace safe for git
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Install tools
run: mise install --locked

- name: Configure npm auth for GitHub Packages
working-directory: ./sdk/typescript
run: |
{
echo "@nvidia:registry=https://npm.pkg.github.com"
echo '//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}'
} > .npmrc

- name: Publish
env:
OPENSHELL_NPM_VERSION: ${{ needs.compute-versions.outputs.npm_version }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: mise run sdk:ts:publish

release-helm:
name: Release Helm Chart (OCI)
needs: [compute-versions, release, tag-ghcr-release]
Expand Down
3 changes: 3 additions & 0 deletions docs/_components/jsx.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

declare const React: unknown;
3 changes: 3 additions & 0 deletions fern/components/CustomFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

/**
* Custom footer for NVIDIA docs (Fern native header/footer).
* Markup and class names match the original custom-app footer 1:1 so that
Expand Down
9 changes: 9 additions & 0 deletions scripts/update_license_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
".yaml": "#",
".yml": "#",
".rego": "#",
".ts": "//",
".tsx": "//",
".mts": "//",
".cts": "//",
}

# Directories to skip entirely (relative to repo root).
Expand All @@ -55,6 +59,7 @@
".git",
".cache",
"python/openshell/_proto",
"sdk/typescript/src/gen",
}

# Individual filenames to skip.
Expand Down Expand Up @@ -103,6 +108,10 @@ def is_excluded(rel: Path) -> bool:
"""Return True if a path should be skipped."""
rel_str = str(rel)

# Vendored dependencies never carry our headers, at any depth.
if "node_modules" in rel.parts:
return True

# Exact filename exclusions.
if rel.name in EXCLUDE_FILES:
return True
Expand Down
5 changes: 5 additions & 0 deletions sdk/typescript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
src/gen/
dist/
*.tsbuildinfo
.npmrc
50 changes: 50 additions & 0 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# @nvidia/openshell-sdk

TypeScript client for the OpenShell gateway — thin, idiomatic bindings generated from the OpenShell protobufs.

Distributed via GitHub Packages during pre-GA. Public npm (`@openshell/sdk`) follows at GA; the public API is unchanged across the move, so only the install specifier changes.

## Install

Published to GitHub Packages, so add a project `.npmrc`:

```shell
@nvidia:registry=https://npm.pkg.github.com
```

Authenticate with a GitHub token that has `read:packages`, then:

```shell
npm install @nvidia/openshell-sdk
```

## Usage

```ts
import { OpenShellClient } from '@nvidia/openshell-sdk'

const client = await OpenShellClient.connect({
gateway: 'https://gateway.example.com',
oidcToken: process.env.OPENSHELL_TOKEN,
})

const sandbox = await client.createSandbox({
image: 'ghcr.io/nvidia/openshell-community/sandboxes/python:latest',
})
await client.waitReady(sandbox.name, 120)

const result = await client.exec(sandbox.name, ['/bin/sh', '-c', 'echo hello'])
console.log(result.stdout.toString())

await client.deleteSandbox(sandbox.name)
```

## Development

The version field is a `0.0.0` placeholder; CI stamps the real version from the git release tag at publish time, matching the Rust and Python packages.

```shell
mise run sdk:ts:proto # generate stubs from proto/ (protoc + protoc-gen-es)
mise run sdk:ts:typecheck # tsc --noEmit
mise run sdk:ts:build # emit dist/
```
29 changes: 29 additions & 0 deletions sdk/typescript/gen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Generate idiomatic TypeScript from the OpenShell protos using the pinned
# `protoc` toolchain (mise) + the connect-es plugin (@bufbuild/protoc-gen-es).
# No `buf` required. Well-known types (Struct, Timestamp, ...) resolve via
# protoc's bundled include path and render through @bufbuild/protobuf/wkt, so
# we do not generate them ourselves.
set -euo pipefail

HERE="$(cd "$(dirname "$0")" && pwd)"
PROTO_DIR="$HERE/../../proto"
OUT="$HERE/src/gen"
PLUGIN="$HERE/node_modules/.bin/protoc-gen-es"

rm -rf "$OUT"
mkdir -p "$OUT"

# Only the files the client-facing surface needs (transitive imports included).
protoc \
-I "$PROTO_DIR" \
--plugin=protoc-gen-es="$PLUGIN" \
--es_out="$OUT" \
--es_opt=target=ts,import_extension=js \
datamodel.proto sandbox.proto openshell.proto

echo "generated into $OUT:"
ls -1 "$OUT"
Loading
Loading