publish #173
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: publish | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version to release (e.g. 0.2.0 or 0.2.0-rc.1). Leave empty for preview publish on the dispatched branch." | |
| required: false | |
| type: string | |
| latest: | |
| description: "Tag as @latest (release only)" | |
| required: true | |
| type: boolean | |
| default: true | |
| concurrency: | |
| group: publish-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| R2_BUCKET: rivet-releases | |
| R2_ENDPOINT: https://2a94c6a0ced8d35ea63cddc86c2681e7.r2.cloudflarestorage.com | |
| SIDECAR_PLATFORMS: "linux-x64-gnu linux-arm64-gnu darwin-x64 darwin-arm64" | |
| RUST_TOOLCHAIN: "1.91.1" | |
| LINUX_GNU_LLVM_VERSION: "22" | |
| LINUX_GNU_SYSROOT_TAG: "sysroot-20250207" | |
| jobs: | |
| context: | |
| name: Context | |
| runs-on: ubuntu-latest | |
| outputs: | |
| trigger: ${{ steps.ctx.outputs.trigger }} | |
| version: ${{ steps.ctx.outputs.version }} | |
| npm_tag: ${{ steps.ctx.outputs.npm_tag }} | |
| sha: ${{ steps.ctx.outputs.sha }} | |
| latest: ${{ steps.ctx.outputs.latest }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - run: pnpm install --frozen-lockfile --filter=publish | |
| - id: ctx | |
| name: Resolve publish context | |
| run: pnpm --filter=publish exec tsx src/ci/bin.ts context-output | |
| wasm-commands: | |
| name: WASM Commands | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - uses: dtolnay/rust-toolchain@nightly | |
| with: | |
| targets: wasm32-wasip1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: toolchain -> toolchain/target | |
| cache-workspace-crates: true | |
| key: wasm-commands-${{ hashFiles('toolchain/Cargo.lock') }} | |
| - run: pnpm install --frozen-lockfile --filter '@rivet-dev/agentos-runtime-core...' | |
| - run: make -C toolchain commands | |
| - run: node packages/runtime-core/scripts/copy-wasm-commands.mjs --require | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: wasm-commands | |
| path: packages/runtime-core/commands | |
| if-no-files-found: error | |
| codex-wasm: | |
| name: Codex WASI | |
| runs-on: [self-hosted, agentos-builder] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: nightly-2026-03-01 | |
| components: rust-src | |
| targets: wasm32-wasip1 | |
| - name: Install toolchain build prerequisites | |
| run: | | |
| if ! command -v cmake >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --yes cmake | |
| fi | |
| - run: make -C toolchain codex | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: codex-wasm | |
| path: software/codex/wasm | |
| if-no-files-found: error | |
| build-sidecar: | |
| needs: [context] | |
| name: "Build linux native artifacts (${{ matrix.platform }})" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux-x64-gnu | |
| runner: [self-hosted, agentos-builder] | |
| target: x86_64-unknown-linux-gnu | |
| - platform: linux-arm64-gnu | |
| runner: [self-hosted, agentos-builder-arm64] | |
| target: aarch64-unknown-linux-gnu | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| with: | |
| name: agentos-${{ matrix.platform }} | |
| keep-state: ${{ contains(matrix.runner, 'self-hosted') }} | |
| - name: Resolve build profile | |
| id: mode | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ needs.context.outputs.trigger }}" = "release" ]; then | |
| echo "profile=release" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "profile=debug" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Build linux artifacts | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: docker/build/linux-gnu.Dockerfile | |
| build-args: | | |
| TARGET=${{ matrix.target }} | |
| BUILD_PROFILE=${{ steps.mode.outputs.profile }} | |
| CACHE_PLATFORM=${{ matrix.platform }} | |
| RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} | |
| LINUX_GNU_LLVM_VERSION=${{ env.LINUX_GNU_LLVM_VERSION }} | |
| LINUX_GNU_SYSROOT_TAG=${{ env.LINUX_GNU_SYSROOT_TAG }} | |
| tags: agentos-linux-${{ matrix.platform }} | |
| load: true | |
| - name: Extract linux artifacts | |
| id: extract | |
| run: | | |
| set -euo pipefail | |
| sidecar_out="target/sidecar-artifacts/${{ matrix.platform }}" | |
| mkdir -p "$sidecar_out" | |
| cid=$(docker create agentos-linux-${{ matrix.platform }}) | |
| docker cp "$cid:/artifacts/agentos-sidecar" "$sidecar_out/agentos-sidecar" | |
| docker cp "$cid:/artifacts/agentos-native-sidecar" "$sidecar_out/agentos-native-sidecar" | |
| docker rm "$cid" | |
| test -f "$sidecar_out/agentos-sidecar" | |
| test -f "$sidecar_out/agentos-native-sidecar" | |
| echo "sidecar_dir=$sidecar_out" >> "$GITHUB_OUTPUT" | |
| - name: Check glibc floor | |
| run: | | |
| scripts/ci/check-linux-glibc-floor.sh \ | |
| "${{ steps.extract.outputs.sidecar_dir }}/agentos-sidecar" \ | |
| "${{ steps.extract.outputs.sidecar_dir }}/agentos-native-sidecar" | |
| - name: Smoke-run binaries in old Linux containers | |
| run: | | |
| scripts/ci/smoke-linux-artifacts.sh binary \ | |
| "${{ steps.extract.outputs.sidecar_dir }}/agentos-sidecar" \ | |
| "${{ steps.extract.outputs.sidecar_dir }}/agentos-native-sidecar" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: sidecar-${{ matrix.platform }} | |
| path: ${{ steps.extract.outputs.sidecar_dir }} | |
| if-no-files-found: error | |
| build-sidecar-darwin: | |
| needs: [context] | |
| name: "Build darwin binaries (${{ matrix.platform }})" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: darwin-x64 | |
| runner: [self-hosted, agentos-builder] | |
| target: x86_64-apple-darwin | |
| clang: x86_64-apple-darwin20.4 | |
| - platform: darwin-arm64 | |
| runner: [self-hosted, agentos-builder] | |
| target: aarch64-apple-darwin | |
| clang: aarch64-apple-darwin20.4 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| with: | |
| name: agentos-${{ matrix.platform }} | |
| keep-state: true | |
| - name: Log in to ghcr.io | |
| run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | |
| - name: Compute build profile | |
| id: mode | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ needs.context.outputs.trigger }}" = "release" ]; then | |
| echo "profile=release" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "profile=debug" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Cross-compile via osxcross | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: docker/build/darwin.Dockerfile | |
| build-args: | | |
| TARGET=${{ matrix.target }} | |
| CLANG=${{ matrix.clang }} | |
| BUILD_PROFILE=${{ steps.mode.outputs.profile }} | |
| CACHE_PLATFORM=${{ matrix.platform }} | |
| RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} | |
| tags: agentos-darwin-${{ matrix.platform }} | |
| load: true | |
| - name: Extract darwin artifacts | |
| run: | | |
| set -euo pipefail | |
| sidecar_out="target/sidecar-artifacts/${{ matrix.platform }}" | |
| mkdir -p "$sidecar_out" | |
| cid=$(docker create agentos-darwin-${{ matrix.platform }}) | |
| docker cp "$cid:/artifacts/agentos-sidecar" "$sidecar_out/agentos-sidecar" | |
| docker cp "$cid:/artifacts/agentos-native-sidecar" "$sidecar_out/agentos-native-sidecar" | |
| docker rm "$cid" | |
| test -f "$sidecar_out/agentos-sidecar" | |
| test -f "$sidecar_out/agentos-native-sidecar" | |
| case "${{ matrix.platform }}" in | |
| darwin-x64) expected_arch="x86_64" ;; | |
| darwin-arm64) expected_arch="arm64" ;; | |
| *) echo "unknown darwin platform: ${{ matrix.platform }}" >&2; exit 2 ;; | |
| esac | |
| file "$sidecar_out/agentos-sidecar" | grep -F "$expected_arch" | |
| file "$sidecar_out/agentos-native-sidecar" | grep -F "$expected_arch" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: sidecar-${{ matrix.platform }} | |
| path: target/sidecar-artifacts/${{ matrix.platform }} | |
| if-no-files-found: error | |
| publish-npm: | |
| needs: [context, wasm-commands, codex-wasm, build-sidecar, build-sidecar-darwin] | |
| name: Publish npm | |
| if: ${{ !cancelled() && needs.wasm-commands.result == 'success' && needs.codex-wasm.result == 'success' && needs.build-sidecar.result == 'success' && needs.build-sidecar-darwin.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| registry-url: https://registry.npmjs.org | |
| - run: pnpm install --frozen-lockfile | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: wasm-commands | |
| path: packages/runtime-core/commands | |
| - name: Restore canonical WASM command staging | |
| run: | | |
| set -euo pipefail | |
| commands_dir="toolchain/target/wasm32-wasip1/release/commands" | |
| mkdir -p "$commands_dir" | |
| cp -a packages/runtime-core/commands/. "$commands_dir/" | |
| test -s "$commands_dir/sh" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: codex-wasm | |
| path: software/codex/wasm | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: sidecar-* | |
| path: artifacts | |
| - name: Place sidecar binaries into platform packages | |
| run: | | |
| set -euo pipefail | |
| for p in $SIDECAR_PLATFORMS; do | |
| agent_bin="artifacts/sidecar-${p}/agentos-sidecar" | |
| runtime_bin="artifacts/sidecar-${p}/agentos-native-sidecar" | |
| agent_dest="packages/sidecar-binary/npm/${p}" | |
| runtime_dest="packages/runtime-sidecar/npm/${p}" | |
| test -f "$agent_bin" | |
| test -f "$runtime_bin" | |
| test -d "$agent_dest" | |
| test -d "$runtime_dest" | |
| cp "$agent_bin" "${agent_dest}/agentos-sidecar" | |
| chmod +x "${agent_dest}/agentos-sidecar" | |
| cp "$runtime_bin" "${runtime_dest}/agentos-native-sidecar" | |
| chmod +x "${runtime_dest}/agentos-native-sidecar" | |
| done | |
| - name: Bump package versions for build | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts bump-versions \ | |
| --version ${{ needs.context.outputs.version }} \ | |
| --version-only | |
| - run: node packages/runtime-core/scripts/copy-wasm-commands.mjs --require | |
| - name: Build TypeScript packages | |
| env: | |
| AGENTOS_SKIP_NATIVE_META_BUILD: "1" | |
| run: | | |
| # Browser support is retained in-tree but intentionally disabled until | |
| # it has a reactor/security design independent of the native sidecar. | |
| npx turbo build \ | |
| --filter='!@rivet-dev/agentos-browser' \ | |
| --filter='!@rivet-dev/agentos-runtime-browser' \ | |
| --filter='!@rivet-dev/agentos-playground' \ | |
| --filter='!./examples/*' \ | |
| --filter='!./examples/quickstart/*' | |
| - name: Finalize package versions for publish | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts bump-versions \ | |
| --version ${{ needs.context.outputs.version }} | |
| - name: Publish npm packages | |
| env: | |
| NODE_AUTH_TOKEN: "" | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts publish-npm \ | |
| --tag ${{ needs.context.outputs.npm_tag }} \ | |
| --parallel 16 \ | |
| --retries 3 \ | |
| ${{ needs.context.outputs.trigger == 'release' && '--release-mode' || '' }} | |
| release-assets: | |
| needs: [context, build-sidecar, build-sidecar-darwin] | |
| name: Release assets | |
| if: ${{ !cancelled() && needs.build-sidecar.result == 'success' && needs.build-sidecar-darwin.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - run: pnpm install --frozen-lockfile --filter=publish | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: sidecar-* | |
| path: artifacts | |
| - name: Stage release assets | |
| env: | |
| VERSION: ${{ needs.context.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| declare -A PLATFORM_TARGET=( | |
| [linux-x64-gnu]=x86_64-unknown-linux-gnu | |
| [linux-arm64-gnu]=aarch64-unknown-linux-gnu | |
| [darwin-x64]=x86_64-apple-darwin | |
| [darwin-arm64]=aarch64-apple-darwin | |
| ) | |
| mkdir -p release-assets | |
| for p in $SIDECAR_PLATFORMS; do | |
| target="${PLATFORM_TARGET[$p]}" | |
| cp "artifacts/sidecar-${p}/agentos-sidecar" "release-assets/agentos-sidecar-${target}" | |
| cp "artifacts/sidecar-${p}/agentos-native-sidecar" "release-assets/agentos-native-sidecar-${target}" | |
| done | |
| chmod +x release-assets/agentos-sidecar-* release-assets/agentos-native-sidecar-* | |
| if [ -d crates/execution/assets/pyodide ]; then | |
| mkdir -p release-assets/pyodide | |
| cp -R crates/execution/assets/pyodide/. release-assets/pyodide/ | |
| fi | |
| - name: Create GitHub release and upload assets | |
| if: ${{ needs.context.outputs.trigger == 'release' }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| VERSION: ${{ needs.context.outputs.version }} | |
| NPM_TAG: ${{ needs.context.outputs.npm_tag }} | |
| run: | | |
| set -euo pipefail | |
| if ! gh release view "v${VERSION}" >/dev/null 2>&1; then | |
| PRERELEASE="" | |
| if [ "${NPM_TAG}" = "rc" ]; then PRERELEASE="--prerelease"; fi | |
| gh release create "v${VERSION}" --title "v${VERSION}" --generate-notes $PRERELEASE | |
| fi | |
| # Upload FILES only — a bare `release-assets/*` glob matches the | |
| # pyodide directory itself and `gh release upload` cannot upload dirs. | |
| find release-assets -maxdepth 1 -type f -print0 | xargs -0 gh release upload "v${VERSION}" --clobber | |
| if [ -d release-assets/pyodide ]; then | |
| find release-assets/pyodide -maxdepth 1 -type f -print0 | xargs -0 gh release upload "v${VERSION}" --clobber | |
| fi | |
| - name: Upload release assets to R2 | |
| if: ${{ needs.context.outputs.trigger == 'release' }} | |
| env: | |
| R2_RELEASES_ACCESS_KEY_ID: ${{ secrets.R2_RELEASES_ACCESS_KEY_ID }} | |
| R2_RELEASES_SECRET_ACCESS_KEY: ${{ secrets.R2_RELEASES_SECRET_ACCESS_KEY }} | |
| VERSION: ${{ needs.context.outputs.version }} | |
| SHA: ${{ needs.context.outputs.sha }} | |
| LATEST: ${{ needs.context.outputs.latest }} | |
| run: | | |
| set -uo pipefail | |
| if [ -z "${R2_RELEASES_ACCESS_KEY_ID:-}" ] || [ -z "${R2_RELEASES_SECRET_ACCESS_KEY:-}" ]; then | |
| echo "R2 credentials not configured; skipping R2 upload." | |
| exit 0 | |
| fi | |
| set -e | |
| pnpm --filter=publish exec tsx src/ci/bin.ts upload-r2 \ | |
| --source "$GITHUB_WORKSPACE/release-assets" --sha "$SHA" | |
| pnpm --filter=publish exec tsx src/ci/bin.ts copy-r2 \ | |
| --sha "$SHA" --version "$VERSION" --latest "$LATEST" | |
| publish-crates: | |
| needs: [context, build-sidecar, release-assets] | |
| name: Publish crates.io | |
| if: ${{ !cancelled() && needs.build-sidecar.result == 'success' && (needs.release-assets.result == 'success' || needs.release-assets.result == 'skipped') }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: . -> target | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/.rusty_v8 | |
| key: ${{ runner.os }}-x86_64-unknown-linux-gnu-rusty-v8-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-x86_64-unknown-linux-gnu-rusty-v8- | |
| - run: pnpm install --frozen-lockfile | |
| - name: Bump Cargo versions | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts bump-versions \ | |
| --version ${{ needs.context.outputs.version }} \ | |
| --version-only | |
| - name: Stage vendored V8 bridge bundles and base filesystem | |
| run: | | |
| set -euo pipefail | |
| # crates/{execution,v8-runtime}/assets/generated is gitignored; the | |
| # published crates fall back to the vendored bundle (build-support | |
| # copy_vendored_bundle) and panic if it is absent. Stage it here. | |
| for crate in execution v8-runtime; do | |
| out="crates/${crate}/assets/generated" | |
| mkdir -p "$out" | |
| node packages/build-tools/scripts/build-v8-bridge.mjs --out-dir "$out" | |
| done | |
| git add -f crates/execution/assets/generated crates/v8-runtime/assets/generated | |
| # The single committed base filesystem lives in the vfs crate; the | |
| # kernel and native-sidecar crates vendor a copy for isolated publish | |
| # builds (their build.rs falls back to assets/base-filesystem.json). | |
| mkdir -p crates/kernel/assets crates/native-sidecar/assets | |
| cp crates/vfs/assets/base-filesystem.json crates/kernel/assets/base-filesystem.json | |
| cp crates/vfs/assets/base-filesystem.json crates/native-sidecar/assets/base-filesystem.json | |
| - name: Dry-run crate publish | |
| if: ${{ needs.context.outputs.trigger != 'release' }} | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts publish-crates \ | |
| --version ${{ needs.context.outputs.version }} \ | |
| --dry-run \ | |
| --allow-dirty | |
| - name: Publish crates | |
| if: ${{ needs.context.outputs.trigger == 'release' }} | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| run: | | |
| pnpm --filter=publish exec tsx src/ci/bin.ts publish-crates \ | |
| --version ${{ needs.context.outputs.version }} \ | |
| --allow-dirty |