# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 name: Publish TypeScript package on: push: tags: - 'v*' - '!v*-alpha*' concurrency: group: publish-typescript queue: max cancel-in-progress: false defaults: run: shell: bash jobs: publish-typescript: name: Publish (npmjs.com) runs-on: ubuntu-24.04 timeout-minutes: 25 permissions: # actions/checkout needs read access to the tagged repository contents. contents: read # npm trusted publishing exchanges this job's GitHub OIDC token for a # short-lived registry credential; no long-lived npm token is provided. id-token: write environment: npmjs steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - name: Verify release tag id: source env: RELEASE_REF: ${{ github.ref }} run: | set -euo pipefail if [[ "$RELEASE_REF" != refs/tags/* ]]; then echo "Release ref must be a tag: ${RELEASE_REF}" >&2 exit 1 fi release_tag="${RELEASE_REF#refs/tags/}" tag_commit="$(git rev-parse --verify "refs/tags/${release_tag}^{commit}")" head_commit="$(git rev-parse HEAD)" if [[ "$tag_commit" != "$head_commit" ]]; then echo "Release tag ${release_tag} points to ${tag_commit}, not checked-out commit ${head_commit}" >&2 exit 1 fi echo "tag=${release_tag}" >> "$GITHUB_OUTPUT" - name: Set up Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '24' package-manager-cache: false - name: Set up Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: 1.4.2 - name: Install just uses: taiki-e/install-action@c070f87102a1c75b3183910f391c1cb887fe13c8 # v2.77.6 with: tool: just@1.50.0 - name: Validate trusted publishing toolchain run: | set -euo pipefail node --version npm_version="$(npm --version)" echo "$npm_version" NPM_VERSION="$npm_version" node <<'NODE' const actual = process.env.NPM_VERSION.split('.').map(Number); const minimum = [11, 5, 1]; const comparison = actual.findIndex( (part, index) => part !== minimum[index], ); if ( actual.length !== minimum.length || actual.some(Number.isNaN) || (comparison !== -1 && actual[comparison] < minimum[comparison]) ) { throw new Error('npm 11.5.1 or newer is required for trusted publishing'); } NODE - name: Resolve package release id: release env: RELEASE_TAG: ${{ steps.source.outputs.tag }} run: | set -euo pipefail case "$RELEASE_TAG" in v*) version_tag="$RELEASE_TAG" ;; *) echo "Unsupported TypeScript release tag: $RELEASE_TAG" >&2 exit 1 ;; esac version="$(python3 scripts/ci/normalize_release_tag.py "$version_tag")" if [[ "$version" == *+* ]]; then echo "npm publication does not support build metadata: $version" >&2 exit 1 fi case "$version" in *-beta*|*-rc*) dist_tag="next" ;; *-*) echo "Unsupported npm prerelease: $version" >&2 exit 1 ;; *) dist_tag="latest" ;; esac python3 scripts/ci/set_typescript_project_version.py "$version" { echo "version=$version" echo "dist_tag=$dist_tag" } >> "$GITHUB_OUTPUT" - name: Check npm package bootstrap run: python3 scripts/ci/check_npm_bootstrap.py - name: Test packages run: | just test-typescript just test-typescript-adapters - name: Publish packages env: NPM_CONFIG_REGISTRY: https://registry.npmjs.org RELEASE_VERSION: ${{ steps.release.outputs.version }} RELEASE_DIST_TAG: ${{ steps.release.outputs.dist_tag }} run: | set -euo pipefail # Keep publication aligned with the explicit versioning/build coverage. for package_directory in \ adapter-contract/typescript \ adapters/typescript/common \ adapters/typescript/cline \ adapters/typescript/droid \ adapters/typescript/pi \ adapters/typescript/opencode \ adapters/typescript/qwen \ adapters/typescript/kilo \ adapters/typescript/kiro \ adapters/typescript/strands; do python3 scripts/ci/publish_typescript_package.py \ --action publish \ --package-directory "$package_directory" \ --version "$RELEASE_VERSION" \ --dist-tag "$RELEASE_DIST_TAG" done