name: Blacksmith Build Artifacts Testbox on: workflow_dispatch: inputs: testbox_id: type: string description: "Testbox session ID" required: true pull_request: paths: - ".github/workflows/**" permissions: contents: read env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: build-artifacts: permissions: contents: read name: "build-artifacts" runs-on: blacksmith-8vcpu-ubuntu-2404 timeout-minutes: 35 steps: - name: Begin Testbox uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67 with: testbox_id: ${{ inputs.testbox_id }} - name: Checkout shell: bash env: CHECKOUT_REPO: ${{ github.repository }} CHECKOUT_SHA: ${{ github.sha }} CHECKOUT_TOKEN: ${{ github.token }} run: | set -euo pipefail workdir="$GITHUB_WORKSPACE" auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')" reset_checkout_dir() { mkdir -p "$workdir" find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} + } checkout_attempt() { local attempt="$1" reset_checkout_dir git init "$workdir" >/dev/null git config --global --add safe.directory "$workdir" git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}" git -C "$workdir" config gc.auto 0 timeout --signal=TERM 30s git -C "$workdir" \ -c protocol.version=2 \ -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${auth_header}" \ fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \ "+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1 git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1 test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1 echo "checkout attempt ${attempt}/5 succeeded" } for attempt in 1 2 3 4 5; do if checkout_attempt "$attempt"; then exit 0 fi echo "checkout attempt ${attempt}/5 failed" sleep $((attempt * 5)) done echo "checkout failed after 5 attempts" >&2 exit 1 - name: Setup Node environment uses: ./.github/actions/setup-node-env with: install-bun: "false" - name: Resolve release dist cache seeds id: dist-cache-seeds shell: bash run: | set -euo pipefail cache_prefix="${RUNNER_OS}-dist-build-" declare -A seen=() resolve_tag_sha() { local tag="$1" local direct="" local peeled="" while read -r sha ref; do if [[ "$ref" == "refs/tags/${tag}^{}" ]]; then peeled="$sha" elif [[ "$ref" == "refs/tags/${tag}" ]]; then direct="$sha" fi done < <(git ls-remote --tags origin "refs/tags/${tag}" "refs/tags/${tag}^{}") printf '%s\n' "${peeled:-$direct}" } { echo "restore-keys</dev/null || true)" if [[ -z "$version" ]]; then echo "Could not resolve npm dist-tag ${dist_tag}; skipping cache seed." >&2 continue fi sha="$(resolve_tag_sha "v${version}")" if [[ -z "$sha" ]]; then echo "Could not resolve git tag v${version}; skipping cache seed." >&2 continue fi key="${cache_prefix}${sha}" if [[ -z "${seen[$key]+x}" ]]; then echo "$key" seen[$key]=1 fi done echo "${cache_prefix}" echo "EOF" } >> "$GITHUB_OUTPUT" - name: Restore dist build cache id: dist-cache uses: actions/cache/restore@v5 with: path: | .artifacts/build-all-cache/ dist/ dist-runtime/ key: ${{ runner.os }}-dist-build-${{ github.sha }} restore-keys: ${{ steps.dist-cache-seeds.outputs.restore-keys }} - name: Build dist on cache miss if: steps.dist-cache.outputs.cache-hit != 'true' run: pnpm build:ci-artifacts - name: Build Control UI on cache miss if: steps.dist-cache.outputs.cache-hit != 'true' run: pnpm ui:build - name: Verify build artifacts shell: bash run: | set -euo pipefail test -d dist test -d dist-runtime if [[ ! -f dist/index.js && ! -f dist/index.mjs ]]; then echo "Missing dist/index.js or dist/index.mjs" >&2 exit 1 fi test -f dist/build-info.json test -f dist/control-ui/index.html - name: Save dist build cache if: steps.dist-cache.outputs.cache-hit != 'true' uses: actions/cache/save@v5 with: path: | .artifacts/build-all-cache/ dist/ dist-runtime/ key: ${{ runner.os }}-dist-build-${{ github.sha }} - name: Prepare Testbox shell shell: bash run: | set -euo pipefail git fetch --no-tags --depth=50 origin "+refs/heads/main:refs/remotes/origin/main" node_bin="$(dirname "$(node -p 'process.execPath')")" pnpm_bin="$(command -v pnpm)" sudo ln -sf "$node_bin/node" /usr/local/bin/node sudo ln -sf "$node_bin/npm" /usr/local/bin/npm sudo ln -sf "$node_bin/npx" /usr/local/bin/npx sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack sudo ln -sf "$pnpm_bin" /usr/local/bin/pnpm - name: Hydrate Testbox provider env helper shell: bash env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }} ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }} CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }} DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }} FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }} GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }} MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }} OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }} TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }} XAI_API_KEY: ${{ secrets.XAI_API_KEY }} ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }} Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }} run: bash scripts/ci-hydrate-testbox-env.sh - name: Run Testbox uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc if: always() env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"