diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4c36f41106..d438aaf92e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,14 +3,15 @@ name: test on: push: branches: - - dev + - local/amicode pull_request: workflow_dispatch: concurrency: - # Keep every run on dev so cancelled checks do not pollute the default branch - # commit history. PRs and other branches still share a group and cancel stale runs. - group: ${{ case(github.ref == 'refs/heads/dev', format('{0}-{1}', github.workflow, github.run_id), format('{0}-{1}', github.workflow, github.event.pull_request.number || github.ref)) }} + # Keep every run on the default branch so cancelled checks do not pollute the + # default branch commit history. PRs and other branches still share a group and + # cancel stale runs. + group: ${{ case(github.ref == 'refs/heads/local/amicode', format('{0}-{1}', github.workflow, github.run_id), format('{0}-{1}', github.workflow, github.event.pull_request.number || github.ref)) }} cancel-in-progress: true permissions: @@ -28,9 +29,9 @@ jobs: matrix: settings: - name: linux - host: blacksmith-4vcpu-ubuntu-2404 + host: ubuntu-latest - name: windows - host: blacksmith-4vcpu-windows-2025 + host: windows-latest runs-on: ${{ matrix.settings.host }} defaults: run: @@ -64,7 +65,7 @@ jobs: turbo-${{ runner.os }}- - name: Run unit tests - timeout-minutes: 20 + timeout-minutes: 45 run: bun turbo test --output-logs=errors-only --log-order=grouped --log-prefix=task env: OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }} @@ -81,9 +82,9 @@ jobs: matrix: settings: - name: linux - host: blacksmith-4vcpu-ubuntu-2404 + host: ubuntu-latest - name: windows - host: blacksmith-4vcpu-windows-2025 + host: windows-latest runs-on: ${{ matrix.settings.host }} env: PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.playwright-browsers @@ -99,7 +100,8 @@ jobs: - name: Setup Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: "24" + # Playwright 1.59 hangs while extracting Chromium with Node 24.16. + node-version: "24.15" - name: Setup Bun uses: ./.github/actions/setup-bun diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index fc9a52797c..605b6c4f70 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -2,14 +2,13 @@ name: typecheck on: push: - branches: [dev] + branches: [local/amicode] pull_request: - branches: [dev] workflow_dispatch: jobs: typecheck: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 diff --git a/packages/app/e2e/smoke/session-timeline.spec.ts b/packages/app/e2e/smoke/session-timeline.spec.ts index 5d7425ea5b..e4add848a4 100644 --- a/packages/app/e2e/smoke/session-timeline.spec.ts +++ b/packages/app/e2e/smoke/session-timeline.spec.ts @@ -412,13 +412,12 @@ function expectCompleteScroll( async function selectHomeProject(page: Page, projectName: string) { await page.goto("/") - const row = page - .locator('[data-component="home-project-row"]') - .filter({ hasText: new RegExp(projectName, "i") }) - .first() - await expectAppVisible(row) - await row.click() - await expect(row).toHaveAttribute("data-selected", "", { timeout: APP_READY_TIMEOUT }) + // amicode home: a single seeded project is auto-focused and its row is + // deliberately NOT rendered (HomeProjectList shows rows only when there is + // an actual choice, i.e. >1 projects). The home-cards strip is the stable + // "home ready" signal; the focused project's sessions render alongside it. + await expectAppVisible(page.locator('[data-component="amicode-home-cards"]')) + await expect(page.getByText(new RegExp(projectName, "i")).first()).toBeVisible({ timeout: APP_READY_TIMEOUT }) await expect(page).toHaveURL(/\/$/) } diff --git a/packages/app/e2e/utils/waits.ts b/packages/app/e2e/utils/waits.ts index 8a47815674..aaabf19c81 100644 --- a/packages/app/e2e/utils/waits.ts +++ b/packages/app/e2e/utils/waits.ts @@ -1,6 +1,6 @@ import { expect, type Locator, type Page } from "@playwright/test" -export const APP_READY_TIMEOUT = 30_000 +export const APP_READY_TIMEOUT = 45_000 export async function expectAppVisible(locator: Locator) { await expect(locator).toBeVisible({ timeout: APP_READY_TIMEOUT }) diff --git a/packages/app/playwright.config.ts b/packages/app/playwright.config.ts index d9648a88ba..9b25311a8c 100644 --- a/packages/app/playwright.config.ts +++ b/packages/app/playwright.config.ts @@ -6,7 +6,7 @@ const serverHost = process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1" const serverPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096" const command = `bun run dev -- --host 0.0.0.0 --port ${port}` const reuse = !process.env.CI -const workers = Number(process.env.PLAYWRIGHT_WORKERS ?? (process.env.CI ? 5 : 0)) || undefined +const workers = Number(process.env.PLAYWRIGHT_WORKERS ?? (process.env.CI ? 2 : 0)) || undefined export default defineConfig({ testDir: "./e2e", outputDir: "./e2e/test-results", diff --git a/packages/opencode/test/cli/run/run-process.test.ts b/packages/opencode/test/cli/run/run-process.test.ts index 00d2e64b37..db2d0da69d 100644 --- a/packages/opencode/test/cli/run/run-process.test.ts +++ b/packages/opencode/test/cli/run/run-process.test.ts @@ -33,10 +33,10 @@ describe("opencode run (non-interactive subprocess)", () => { Effect.gen(function* () { const result = yield* opencode.run("say hi", { model: "test/nonexistent-model", - timeoutMs: 15_000, + timeoutMs: 18_000, }) expect(result.exitCode).not.toBe(0) - expect(result.durationMs).toBeLessThan(15_000) + expect(result.durationMs).toBeLessThan(18_000) }), 30_000, ) diff --git a/packages/server/src/handlers/event.ts b/packages/server/src/handlers/event.ts index 65ec78a7cb..fdc68fbb24 100644 --- a/packages/server/src/handlers/event.ts +++ b/packages/server/src/handlers/event.ts @@ -21,14 +21,15 @@ export const EventHandler = HttpApiBuilder.group(Api, "server.event", (handlers) return handlers.handleRaw("event.subscribe", () => Effect.gen(function* () { const location = yield* Location.Service + const info = new Location.Info({ + directory: location.directory, + workspaceID: location.workspaceID, + project: location.project, + }) const connected = { id: EventV2.ID.create(), type: "server.connected", - location: new Location.Info({ - directory: location.directory, - workspaceID: location.workspaceID, - project: location.project, - }), + location: info, data: {}, } return HttpServerResponse.stream( @@ -42,6 +43,11 @@ export const EventHandler = HttpApiBuilder.group(Api, "server.event", (handlers) event.location?.directory === location.directory && event.location.workspaceID === location.workspaceID, ), + // Events carry a raw Location.Ref ({directory, workspaceID?}); + // the wire contract is a RESOLVED Location.Info. The filter + // pins every event to this connection's location, so the + // resolved info is the same for all of them. + Stream.map((event) => ({ ...event, location: info })), ), ), Stream.map(eventData),