name: Release runtime artifacts on: push: tags: - v2.0.0 - v2.0.0-rc.* workflow_dispatch: permissions: contents: read concurrency: group: runtime-release-${{ github.ref }} cancel-in-progress: false jobs: build: name: Build ${{ matrix.target }} permissions: contents: read id-token: write attestations: write strategy: fail-fast: false matrix: include: - os: macos-15 target: darwin-arm64 capabilities: browser,browser-visible,design,pdf,diagram,ios - os: macos-15-intel target: darwin-x64 capabilities: browser,browser-visible,design,pdf,diagram,ios - os: ubuntu-24.04-arm target: linux-arm64 capabilities: browser,browser-visible,design,pdf,diagram - os: ubuntu-24.04 target: linux-x64 capabilities: browser,browser-visible,design,pdf,diagram - os: windows-11-arm target: windows-arm64 capabilities: browser,browser-visible,design,pdf,diagram - os: windows-2025 target: windows-x64 capabilities: browser,browser-visible,design,pdf,diagram runs-on: ${{ matrix.os }} timeout-minutes: 35 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: 1.3.14 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: 22.23.1 - name: Install frozen dependencies run: bun install --frozen-lockfile --ignore-scripts shell: bash - name: Build and stage the complete managed runtime env: GSTACK_HOME: ${{ runner.temp }}/gstack-release-home TARGET: ${{ matrix.target }} CAPABILITIES: ${{ matrix.capabilities }} run: | set -euo pipefail node runtime/install.js \ --source "$GITHUB_WORKSPACE" \ --home "$GSTACK_HOME" \ --version 2.0.0 \ --install-now \ --yes \ --capabilities "$CAPABILITIES" active_slot=$(node -e 'const fs=require("fs"),p=process.argv[1];const v=JSON.parse(fs.readFileSync(p,"utf8")).current;if(typeof v!=="string"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(v))process.exit(1);process.stdout.write(v)' "$GSTACK_HOME/versions/current.json") active="$GSTACK_HOME/versions/$active_slot" test -f "$active/.gstack-bundle.json" case "$TARGET" in windows-*) managed_bun_rel=".gstack-runtime-tools/bun.exe" ;; *) managed_bun_rel=".gstack-runtime-tools/bun" ;; esac managed_bun="$active/$managed_bun_rel" test -f "$managed_bun" test "$("$managed_bun" --version)" = "1.3.14" test -f "$active/runtime/licenses/BUN-LICENSE-1.3.14.md" test -f "$active/runtime/licenses/BUN-SOURCE.md" node -e 'const fs=require("fs"),c=require("crypto"),root=process.argv[1],rel=process.argv[2];const m=JSON.parse(fs.readFileSync(root+"/.gstack-bundle.json","utf8"));if(m.tools?.bun?.path!==rel||m.tools?.bun?.version!=="1.3.14")process.exit(1);const license=fs.readFileSync(root+"/runtime/licenses/BUN-LICENSE-1.3.14.md");if(c.createHash("sha256").update(license).digest("hex")!=="2cb858b2db8fc793bca2093489c5bc8eee615d002cc4924254904044c27a0afa")process.exit(1)' "$active" "$managed_bun_rel" test -d "$active/.gstack-runtime-browsers" ( cd "$active" PLAYWRIGHT_BROWSERS_PATH="$active/.gstack-runtime-browsers" \ node --input-type=module --eval \ 'const { chromium } = await import("./node_modules/playwright/index.mjs"); for (const options of [{ headless: true }, { headless: true, channel: "chromium" }]) { const browser = await chromium.launch(options); await browser.close(); }' ) node_command=$(node -p 'process.execPath') host_bun=$(command -v bun) host_bun_dir=$(cd "$(dirname "$host_bun")" && pwd -P) clean_path="" IFS=: read -r -a path_parts <<< "$PATH" for part in "${path_parts[@]}"; do physical=$(cd "$part" 2>/dev/null && pwd -P || printf '%s' "$part") if [ "$physical" != "$host_bun_dir" ]; then clean_path="${clean_path:+$clean_path:}$part" fi done if (PATH="$clean_path"; command -v bun >/dev/null 2>&1); then echo "Host-global Bun remained available after removing setup-bun from PATH" >&2 exit 1 fi test "$(PATH="$clean_path" GSTACK_NODE="$node_command" "$GSTACK_HOME/bin/bun" --version)" = "1.3.14" browser_cleanup() { PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \ "$GSTACK_HOME/bin/browse" stop >/dev/null 2>&1 || true } trap browser_cleanup EXIT smoke_url=$(node -e 'const fs=require("fs"),p=require("path").join(process.env.GITHUB_WORKSPACE,".gstack-runtime-smoke.html");fs.writeFileSync(p,"