name: Publish to npm on: workflow_call: workflow_dispatch: concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: contents: write pull-requests: write id-token: write # Required for npm trusted publishing (OIDC) jobs: build-cli: uses: ./.github/workflows/build-cli.yml # Build npm packages (no environment needed) build: name: Build npm packages runs-on: ubuntu-latest needs: [build-cli] steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '24.10.0' registry-url: 'https://registry.npmjs.org' always-auth: true - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10.30.3 - name: Download freshly-built goose CLI binaries uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: /tmp/cli-artifacts - name: Place binaries into goose-binary packages run: | set -euo pipefail echo "Available CLI artifacts:" find /tmp/cli-artifacts -maxdepth 2 -type d | sort # Map: npm platform name -> upstream artifact directory name (target triple) declare -A PLATFORM_MAP=( [darwin-arm64]=aarch64-apple-darwin [darwin-x64]=x86_64-apple-darwin [linux-arm64]=aarch64-unknown-linux-gnu [linux-x64]=x86_64-unknown-linux-gnu [win32-x64]=x86_64-pc-windows-msvc ) for platform in "${!PLATFORM_MAP[@]}"; do target="${PLATFORM_MAP[$platform]}" artifact_dir="/tmp/cli-artifacts/goose-${target}" pkg_dir="ui/goose-binary/goose-binary-${platform}/bin" mkdir -p "${pkg_dir}" if [[ "${platform}" == "win32-x64" ]]; then archive="${artifact_dir}/goose-${target}.zip" if [[ ! -f "${archive}" ]]; then echo "::error::Missing Windows CLI artifact: ${archive}" exit 1 fi rm -rf /tmp/goose-extract unzip -o "${archive}" -d /tmp/goose-extract cp /tmp/goose-extract/goose-package/goose.exe "${pkg_dir}/goose.exe" else archive="${artifact_dir}/goose-${target}.tar.bz2" if [[ ! -f "${archive}" ]]; then echo "::error::Missing CLI artifact: ${archive}" exit 1 fi rm -rf /tmp/goose-extract mkdir -p /tmp/goose-extract tar -xjf "${archive}" -C /tmp/goose-extract cp /tmp/goose-extract/goose "${pkg_dir}/goose" chmod +x "${pkg_dir}/goose" fi echo " ✅ ${platform} (${target})" done - name: List downloaded binaries (debug) run: find ui/goose-binary -name 'goose*' -type f | sort - name: Install dependencies run: | cd ui pnpm install --frozen-lockfile - name: Build packages run: | cd ui/sdk pnpm run build:ts cd ../text pnpm run build - name: Compatibility check (TUI client ↔ goose binary) env: GOOSE_BINARY: ${{ github.workspace }}/ui/goose-binary/goose-binary-linux-x64/bin/goose run: | cd ui/sdk pnpm run check:compat - name: Upload built packages uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: npm-packages path: ui/ if-no-files-found: error retention-days: 7 - name: Build summary run: | { echo "## 📦 Build Summary" echo "" echo "### Source" echo "Commit: \`${GITHUB_SHA}\`" echo "" echo "### Goose CLI Binaries" echo "✅ Built from this commit for all platforms:" for dir in ui/goose-binary/goose-binary-*/; do platform=$(basename "$dir" | sed 's/goose-binary-//') echo " - $platform" done echo "" echo "### npm Packages" cd ui for pkg in sdk text goose-binary/*/; do if [ -f "$pkg/package.json" ]; then name=$(jq -r '.name' "$pkg/package.json") version=$(jq -r '.version' "$pkg/package.json") echo "- $name@$version" fi done } >> "$GITHUB_STEP_SUMMARY" publish: name: Publish to npm runs-on: ubuntu-latest needs: [build] environment: npm-production-publishing steps: - name: Download built packages uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: npm-packages path: ui/ - name: Restore executable bits on goose binaries run: find ui/goose-binary -name 'goose' -type f -exec chmod +x {} + - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '24.10.0' registry-url: 'https://registry.npmjs.org' always-auth: true - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10.30.3 - name: Publish to npm run: | cd ui # Publish each package individually so one failure doesn't abort the rest. # Skips packages whose version is already published (409/403). failed=0 for pkg in sdk goose-binary/*/ text; do if [ -f "$pkg/package.json" ]; then name=$(jq -r '.name' "$pkg/package.json") version=$(jq -r '.version' "$pkg/package.json") echo "Publishing $name@$version..." if (cd "$pkg" && pnpm publish --access public --no-git-checks --provenance); then echo " ✅ $name@$version published" else # Check if it failed because the version already exists if npm view "$name@$version" version > /dev/null 2>&1; then echo " ⏭️ $name@$version already published, skipping" else echo " ❌ $name@$version failed to publish" failed=1 fi fi fi done if [ "$failed" -eq 1 ]; then echo "::error::One or more packages failed to publish" exit 1 fi - name: Publish summary if: always() run: | cd ui { echo "## 🚀 Published Packages" echo "" for pkg in sdk text goose-binary/*/; do if [ -f "$pkg/package.json" ]; then name=$(jq -r '.name' "$pkg/package.json") version=$(jq -r '.version' "$pkg/package.json") echo "- $name@$version" fi done } >> "$GITHUB_STEP_SUMMARY"