mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-08 01:07:06 +03:00
353 lines
14 KiB
YAML
353 lines
14 KiB
YAML
name: check-test
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- dev
|
|
- beta
|
|
pull_request:
|
|
types: [opened, synchronize, reopened, ready_for_review]
|
|
workflow_dispatch:
|
|
inputs:
|
|
quarantine:
|
|
description: Run only the quarantined browser tests (packages/app/e2e/QUARANTINE.md)
|
|
type: boolean
|
|
default: false
|
|
|
|
concurrency:
|
|
# A new push to a pull request cancels its stale run. Every push and manual run keeps its own group, so each
|
|
# dev and beta commit gets a verdict and a quarantine run never cancels a normal one.
|
|
group: ${{ case(github.event_name == 'pull_request', format('{0}-{1}', github.workflow, github.event.pull_request.number), format('{0}-{1}', github.workflow, github.run_id)) }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
checks: write
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
|
|
jobs:
|
|
affected:
|
|
name: affected packages
|
|
if: ${{ !github.event.pull_request.draft }}
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
outputs:
|
|
e2e: ${{ steps.packages.outputs.app }}
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
# Pull requests diff against the merge's first parent; pushes diff against the previous dev head.
|
|
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
with:
|
|
bun-version-file: package.json
|
|
|
|
- name: Find affected packages
|
|
id: packages
|
|
env:
|
|
TURBO_SCM_BASE: ${{ github.event_name == 'pull_request' && format('{0}^1', github.sha) || github.event.before }}
|
|
TURBO_SCM_HEAD: ${{ github.sha }}
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
echo "app=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
# packages/stories hosts the component tests, but no app package depends on it.
|
|
bun x turbo@2.10.2 ls --affected --filter=@opencode/app --filter=@opencode/stories --output=json > affected.json
|
|
bun -e 'const result = await Bun.file("affected.json").json(); console.log(`app=${result.packages.count > 0}`)' >> "$GITHUB_OUTPUT"
|
|
|
|
unit:
|
|
name: unit (${{ matrix.settings.name }})
|
|
if: ${{ !inputs.quarantine && !github.event.pull_request.draft }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
settings:
|
|
- name: linux
|
|
host: blacksmith-4vcpu-ubuntu-2404
|
|
- name: windows
|
|
host: blacksmith-4vcpu-windows-2025
|
|
runs-on: ${{ matrix.settings.host }}
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
# Pull requests diff against the merge's first parent; pushes diff against the previous dev head.
|
|
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "24"
|
|
|
|
- name: Setup Bun
|
|
uses: ./.github/actions/setup-bun
|
|
|
|
- name: Test Effect simplification rules
|
|
if: runner.os == 'Linux'
|
|
run: bun run test:effect-simplification-rules
|
|
|
|
- name: Check Effect simplifications
|
|
if: runner.os == 'Linux'
|
|
run: bun run lint:effect-simplifications
|
|
|
|
- name: Configure git identity
|
|
run: |
|
|
git config --global user.email "bot@opencode.ai"
|
|
git config --global user.name "opencode"
|
|
|
|
- name: Run unit tests
|
|
timeout-minutes: 20
|
|
run: |
|
|
# The runners have four vCPUs, and each Bun test process performs its own concurrent work.
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
GITHUB_ACTIONS=false bun turbo test --concurrency=3
|
|
exit 0
|
|
fi
|
|
GITHUB_ACTIONS=false bun turbo test --affected --concurrency=3
|
|
env:
|
|
OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }}
|
|
TURBO_SCM_BASE: ${{ github.event_name == 'pull_request' && format('{0}^1', github.sha) || github.event.before }}
|
|
TURBO_SCM_HEAD: ${{ github.sha }}
|
|
|
|
- name: Verify packed codemode package
|
|
if: runner.os == 'Linux'
|
|
working-directory: packages/codemode
|
|
run: bun run pack
|
|
|
|
- name: Verify packed workerd SDK
|
|
if: runner.os == 'Linux'
|
|
timeout-minutes: 15
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
bun turbo verify:package --filter=@opencode/sdk
|
|
exit 0
|
|
fi
|
|
bun turbo verify:package --affected --filter=@opencode/sdk
|
|
env:
|
|
TURBO_SCM_BASE: ${{ github.event_name == 'pull_request' && format('{0}^1', github.sha) || github.event.before }}
|
|
TURBO_SCM_HEAD: ${{ github.sha }}
|
|
|
|
- name: Check generated client
|
|
if: runner.os == 'Linux'
|
|
working-directory: packages/client
|
|
run: bun run check:generated
|
|
|
|
- name: Check generated OpenAPI document
|
|
if: runner.os == 'Linux'
|
|
working-directory: packages/protocol
|
|
run: bun run check:generated
|
|
|
|
build:
|
|
name: build (${{ matrix.settings.name }})
|
|
if: ${{ !inputs.quarantine && !github.event.pull_request.draft }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
settings:
|
|
- name: linux
|
|
host: blacksmith-4vcpu-ubuntu-2404
|
|
- name: windows
|
|
host: blacksmith-4vcpu-windows-2025
|
|
runs-on: ${{ matrix.settings.host }}
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
# Pull requests diff against the merge's first parent; pushes diff against the previous dev head.
|
|
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}
|
|
|
|
- name: Setup Bun
|
|
uses: ./.github/actions/setup-bun
|
|
|
|
- name: Verify compiled service lifecycle
|
|
timeout-minutes: 10
|
|
working-directory: packages/cli
|
|
env:
|
|
NODE_OPTIONS: ${{ runner.os == 'Windows' && '--max-old-space-size=4096' || '' }}
|
|
run: |
|
|
bun run script/build.ts --single --skip-install
|
|
bun run script/service-smoke.ts
|
|
|
|
# Unit tests import workspace sources and never build the libraries they use, so this checks those builds. The
|
|
# CLI and app closures hold every library a tested package depends on. The builds are tsc and Bun.build with no
|
|
# platform-specific steps, and the libraries publish from Linux, so Windows skips them.
|
|
- name: Build workspace libraries
|
|
if: ${{ !cancelled() && runner.os == 'Linux' }}
|
|
timeout-minutes: 10
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
bun turbo build --concurrency=3 --filter='@opencode/cli^...' --filter='@opencode/app^...'
|
|
exit 0
|
|
fi
|
|
bun turbo build --affected --concurrency=3 --filter='@opencode/cli^...' --filter='@opencode/app^...'
|
|
env:
|
|
TURBO_SCM_BASE: ${{ github.event_name == 'pull_request' && format('{0}^1', github.sha) || github.event.before }}
|
|
TURBO_SCM_HEAD: ${{ github.sha }}
|
|
|
|
- name: Setup Node build runtime
|
|
if: ${{ !cancelled() }}
|
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "26.4.0"
|
|
|
|
- name: Verify Node build
|
|
if: ${{ !cancelled() }}
|
|
timeout-minutes: 15
|
|
working-directory: packages/cli
|
|
env:
|
|
NODE_OPTIONS: ${{ runner.os == 'Windows' && '--max-old-space-size=4096' || '' }}
|
|
run: |
|
|
bun run script/build-node.ts --single --skip-install --outdir=dist/node
|
|
bun run script/service-smoke.ts --node
|
|
|
|
e2e-suite:
|
|
name: e2e (${{ matrix.settings.name }}, ${{ matrix.suite.id }}${{ matrix.quarantine && ', quarantine' || '' }})
|
|
needs: affected
|
|
if: needs.affected.outputs.e2e == 'true'
|
|
# Quarantined tests are known red; their legs report without failing the e2e checks.
|
|
continue-on-error: ${{ matrix.quarantine }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# Beta PRs gate on Linux; Windows runs on pushes and manual runs (nightly-beta.yml dispatches beta).
|
|
settings: ${{ fromJSON(github.base_ref == 'beta' && '[{"name":"linux","host":"blacksmith-4vcpu-ubuntu-2404"}]' || '[{"name":"linux","host":"blacksmith-4vcpu-ubuntu-2404"},{"name":"windows","host":"blacksmith-4vcpu-windows-2025"}]') }}
|
|
quarantine: ${{ fromJSON(inputs.quarantine && '[true]' || '[false]') }}
|
|
# Playwright splits whole spec files across shards by test count, not duration. Every app-N
|
|
# entry must use the same total, and the entries must cover 1..total. The service worker suite
|
|
# reuses shard 2's production build. Each component suite runs once per OS in its own leg, so the
|
|
# two suites' story servers and test time are not added up on one runner.
|
|
suite:
|
|
- id: app-1
|
|
shard: 1/2
|
|
- id: app-2
|
|
shard: 2/2
|
|
- id: session-ui-components
|
|
- id: app-components
|
|
runs-on: ${{ matrix.settings.host }}
|
|
env:
|
|
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.playwright-browsers
|
|
# Beta only (packages/app/e2e/QUARANTINE.md): gate legs skip quarantined tests, retry once and stop after 8
|
|
# failures; quarantine legs run only those tests, to the end. Other branches keep the config defaults.
|
|
PLAYWRIGHT_ARGS: ${{ matrix.quarantine && '--grep @quarantine --pass-with-no-tests --retries=1' || (github.base_ref == 'beta' || github.ref == 'refs/heads/beta') && '--grep-invert @quarantine --max-failures=8 --retries=1' || '' }}
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
# Playwright 1.59 hangs while extracting Chromium with Node 24.16.
|
|
node-version: "24.15"
|
|
|
|
- name: Setup Bun
|
|
uses: ./.github/actions/setup-bun
|
|
|
|
- name: Read Playwright version
|
|
id: playwright-version
|
|
run: |
|
|
version=$(node -e 'console.log(require("./package.json").workspaces.catalog["@playwright/test"])')
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Cache Playwright browsers
|
|
id: playwright-cache
|
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: ${{ github.workspace }}/.playwright-browsers
|
|
key: ${{ runner.os }}-${{ runner.arch }}-playwright-${{ steps.playwright-version.outputs.version }}-chromium
|
|
|
|
- name: Install Playwright system dependencies
|
|
if: runner.os == 'Linux'
|
|
working-directory: packages/app
|
|
run: bunx playwright install-deps chromium
|
|
|
|
- name: Install Playwright browsers
|
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
working-directory: packages/app
|
|
run: bunx playwright install chromium
|
|
|
|
- name: Run app e2e tests against production build
|
|
if: matrix.suite.shard
|
|
run: bun --cwd packages/app test:e2e:built --shard=${{ matrix.suite.shard }} ${{ env.PLAYWRIGHT_ARGS }}
|
|
env:
|
|
CI: true
|
|
timeout-minutes: ${{ (matrix.quarantine || github.base_ref == 'beta' || github.ref == 'refs/heads/beta') && 10 || 15 }}
|
|
|
|
- name: Verify service worker precaching and upgrades
|
|
if: matrix.suite.shard == '2/2' && !matrix.quarantine
|
|
working-directory: packages/app
|
|
run: bunx playwright test --config e2e/service-worker/playwright.config.ts
|
|
timeout-minutes: 5
|
|
|
|
- name: Run session UI component tests
|
|
if: matrix.suite.id == 'session-ui-components'
|
|
run: bun --cwd packages/session-ui test:components ${{ env.PLAYWRIGHT_ARGS }}
|
|
env:
|
|
CI: true
|
|
timeout-minutes: ${{ (matrix.quarantine || github.base_ref == 'beta' || github.ref == 'refs/heads/beta') && 10 || 15 }}
|
|
|
|
- name: Run app component tests
|
|
if: matrix.suite.id == 'app-components'
|
|
run: bun --cwd packages/app test:components ${{ env.PLAYWRIGHT_ARGS }}
|
|
env:
|
|
CI: true
|
|
timeout-minutes: ${{ (matrix.quarantine || github.base_ref == 'beta' || github.ref == 'refs/heads/beta') && 10 || 15 }}
|
|
|
|
- name: Upload Playwright artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: playwright-${{ matrix.settings.name }}-${{ matrix.suite.id }}${{ matrix.quarantine && '-quarantine' || '' }}-${{ github.run_attempt }}
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
path: |
|
|
packages/app/e2e/test-results
|
|
packages/app/e2e/playwright-report
|
|
packages/session-ui/component-tests/test-results
|
|
packages/session-ui/component-tests/playwright-report
|
|
packages/app/component-tests/test-results
|
|
packages/app/component-tests/playwright-report
|
|
|
|
# Branch rules require one e2e check per OS. These keep those names and pass only when every
|
|
# leg above passed, or when no leg was needed; a failing leg on either OS fails both checks.
|
|
e2e:
|
|
name: e2e (${{ matrix.os }})
|
|
needs: [affected, e2e-suite]
|
|
if: ${{ !cancelled() && !inputs.quarantine && !github.event.pull_request.draft }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [linux, windows]
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
steps:
|
|
- name: Check browser test results
|
|
env:
|
|
AFFECTED: ${{ needs.affected.result }}
|
|
SUITES: ${{ needs.e2e-suite.result }}
|
|
EXPECTED: ${{ needs.affected.outputs.e2e == 'true' && 'success' || 'skipped' }}
|
|
run: |
|
|
if [ "${{ matrix.os }}" = windows ] && [ "${{ github.base_ref }}" = beta ]; then
|
|
echo "Windows browser tests run on beta pushes and nightly, not on beta pull requests"
|
|
exit 0
|
|
fi
|
|
echo "affected packages: $AFFECTED, browser test legs: $SUITES (expected $EXPECTED)"
|
|
test "$AFFECTED" = success && test "$SUITES" = "$EXPECTED"
|