Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ jobs:
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-
turbo-${{ runner.os }}-

- name: Install ripgrep (Windows)
# Fork: the file-search index is built by a background ripgrep walk
# whose errors are swallowed (core/src/filesystem/search.ts forks it
# with orDie). On GitHub-hosted Windows runners the first-use
# download+extract of rg.exe is slow/fragile, which left the index
# permanently empty and failed httpapi-file's search-endpoints test on
# every run. Pre-installing ripgrep makes binary.ts's which("rg.exe")
# short-circuit the download entirely.
if: runner.os == 'Windows'
run: choco install ripgrep --no-progress -y

- name: Run unit tests
# Fork: upstream runs on Blacksmith runners; GitHub-hosted windows-latest
# needs well over 20 minutes for the spawn-heavy opencode suite.
Expand All @@ -78,6 +89,10 @@ jobs:

- name: Run HttpApi exerciser gates
if: runner.os == 'Linux'
# Fork: the three exerciser modes finish in a few minutes; without a
# step timeout a wedged run (seen once in effect mode) holds the job
# until the 6-hour GitHub ceiling.
timeout-minutes: 30
working-directory: packages/opencode
run: bun run test:httpapi

Expand Down
4 changes: 2 additions & 2 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ upstream maintainers — see README → Syncing with upstream for why and how.
| `.github/TEAM_MEMBERS` | Deleted | Upstream's team roster. The five workflows that read it (pr-standards, pr-management, triage, duplicate-issues, compliance-close) fetch it from a `dev` branch this fork doesn't have, so they are already inert here. | Keep deleted. |
| `packages/script/src/index.ts` | Guard the `.github/TEAM_MEMBERS` read: fall back to an empty team list when the file is absent instead of throwing at module load | This module is imported by the publish path (`publish.ts`); the deleted `TEAM_MEMBERS` (row above) made `bun run release` crash with ENOENT. `Script.team` has no consumers in the fork. | Keep our `exists()` guard; take upstream's surrounding changes. |
| `.github/workflows/` — 22 upstream workflows deleted (beta, close-issues, close-prs, compliance-close, containers, deploy, docs-locale-sync, docs-update, duplicate-issues, generate, nix-hashes, notify-discord, opencode, pr-management, pr-standards, publish, publish-github-action, publish-vscode, release-github-action, review, stats, triage) | Deleted | All inert or upstream-only here: gated on `anomalyco/opencode`, publish/deploy to upstream infra, need upstream secrets (`OPENCODE_APP_SECRET`, `OPENCODE_API_KEY`, marketplace/Discord/PostHog tokens), trigger only on a `dev` branch the fork lacks, or read the deleted `TEAM_MEMBERS`. | Keep deleted; delete new upstream workflows too unless they're generic self-contained CI. |
| `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest`; test.yml unit-test step `timeout-minutes` 20 → 45 | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. GitHub-hosted `windows-latest` needs well over 20 minutes for the spawn-heavy opencode suite. | Keep our branches + runners + timeout; take upstream's other changes. |
| `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest`; test.yml unit-test step `timeout-minutes` 20 → 45; test.yml exerciser step gains `timeout-minutes: 30`; test.yml Windows unit job pre-installs ripgrep via choco | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. GitHub-hosted `windows-latest` needs well over 20 minutes for the spawn-heavy opencode suite. A wedged exerciser run otherwise holds the job for GitHub's 6-hour ceiling. The file-search index is built by a background ripgrep walk with swallowed errors; Windows's first-use rg.exe download left it permanently empty, failing httpapi-file's search test every run. | Keep our branches + runners + timeouts; take upstream's other changes. |
| `packages/core/test/ripgrep.test.ts` | `120_000` timeout on both `it.live` tests | First use downloads + extracts the ripgrep binary; GitHub-hosted Windows runners blow bun's 5s default. | Keep our timeouts; take upstream's test changes. |
| `packages/opencode/test/cli/run/run-process.test.ts`, `packages/opencode/test/cli/acp/lifecycle.test.ts`, `packages/opencode/test/server/httpapi-file.test.ts`, `packages/opencode/test/server/httpapi-sdk.test.ts` | Slow-runner headroom: unknown-model test `timeoutMs`/bound 15s → 30s (test timeout 60s); ACP stdin-EOF exit timeout 5s → 30s; file-search-index polls 5s → 30s | Loaded GitHub-hosted runners spawn processes and build the lazy file index slower than upstream's Blacksmith runners; 5–15s budgets flake. Hang regressions are still caught (a hang exceeds the bound; polls return as soon as ready). | Keep our numbers; take upstream's test changes. |
| `packages/opencode/test/cli/run/run-process.test.ts`, `packages/opencode/test/cli/acp/lifecycle.test.ts`, `packages/opencode/test/server/httpapi-file.test.ts`, `packages/opencode/test/server/httpapi-sdk.test.ts` | Slow-runner headroom: unknown-model test `timeoutMs`/bound 15s → 30s (test timeout 60s); ACP stdin-EOF exit timeout 5s → 30s; file-search-index poll 5s → 120s with a 150s test timeout (the search-endpoints test pays ripgrep's first-use download on Windows runners, like ripgrep.test.ts) | Loaded GitHub-hosted runners spawn processes, fetch ripgrep, and build the lazy file index slower than upstream's Blacksmith runners; 5–30s budgets flake or fail outright. Hang regressions are still caught (a hang exceeds the bound; polls return as soon as ready). | Keep our numbers; take upstream's test changes. |
| `packages/opencode/test/tool/external-directory.test.ts`, `packages/opencode/test/tool/read.test.ts` | Windows path-variant tests keep the drive letter in the `alt` form (drop the `.replace(/^[A-Za-z]:/, "")` step) | A drive-less path is drive-relative: it resolves against the CWD's drive (D: on GitHub-hosted Windows) while the temp dir lives on C:, so the file genuinely isn't there. Slash + case variants still exercise normalization. | Keep our `alt` construction; take upstream's test changes. |
| `packages/opencode/test/server/httpapi-exercise/environment.ts` | Exercise config/data dirs `config/opencode`,`data/opencode` → `…/codev-code`; seeds `config.json` with `{"share":"manual"}` | Follows the `global.ts` app-dir rename (row above); the fork's `share: "disabled"` default (config.ts row) would 500 the share/unshare scenarios, so the isolated environment opts back in (network stays stubbed by `OPENCODE_DISABLE_SHARE`). | Keep our dir names + seeded config; take upstream's surrounding changes. |
| `sdks/vscode/package.json`, `sdks/vscode/README.md` | `description` "opencode for VS Code" → "CoDev Code for VS Code"; README title → "CoDev Code VS Code Extension" | Manifest branding. `name`, `displayName`, command IDs/titles and README body (which names actual UI elements) stay upstream — the fork doesn't publish this extension; revisit before shipping it. | Keep our description + title; take upstream's other fields/body. |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Releases publish the unscoped — therefore **public** — [`codev-code`](https:

```sh
npm login # once per machine
bun release # from the repo root: builds all platforms (~15-20 min), then publishes
bun release # builds all platforms, then publishes
```

Variants:
Expand Down
60 changes: 33 additions & 27 deletions packages/opencode/test/server/httpapi-file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,35 +52,41 @@ describe("file HttpApi", () => {
expect(await status.json()).toEqual([])
})

test("serves search endpoints", async () => {
await using tmp = await tmpdir({ git: true })
await Bun.write(path.join(tmp.path, "hello.txt"), "needle")
test(
"serves search endpoints",
async () => {
await using tmp = await tmpdir({ git: true })
await Bun.write(path.join(tmp.path, "hello.txt"), "needle")

const [text, symbols] = await Promise.all([
request(FilePaths.findText, tmp.path, { pattern: "needle" }),
request(FilePaths.findSymbol, tmp.path, { query: "hello" }),
])
const files = await Effect.runPromise(
pollWithTimeout(
Effect.promise(async () => {
const response = await request(FilePaths.findFile, tmp.path, { query: "hello", type: "file" })
const body = await response.json()
return body.includes("hello.txt") ? { response, body } : undefined
}),
"file search index was not ready",
// Lazy indexing on loaded GitHub-hosted Windows runners can exceed
// the 5s default; the poll returns as soon as the index is ready.
"30 seconds",
),
)
const [text, symbols] = await Promise.all([
request(FilePaths.findText, tmp.path, { pattern: "needle" }),
request(FilePaths.findSymbol, tmp.path, { query: "hello" }),
])
const files = await Effect.runPromise(
pollWithTimeout(
Effect.promise(async () => {
const response = await request(FilePaths.findFile, tmp.path, { query: "hello", type: "file" })
const body = await response.json()
return body.includes("hello.txt") ? { response, body } : undefined
}),
"file search index was not ready",
// Lazy indexing needs ripgrep, whose first use downloads + extracts
// the binary — on GitHub-hosted Windows runners that alone can blow
// a 30s budget (see ripgrep.test.ts). The poll returns as soon as
// the index is ready.
"120 seconds",
),
)

expect(text.status).toBe(200)
expect(await text.json()).toContainEqual(expect.objectContaining({ line_number: 1 }))
expect(text.status).toBe(200)
expect(await text.json()).toContainEqual(expect.objectContaining({ line_number: 1 }))

expect(files.response.status).toBe(200)
expect(files.body).toContain("hello.txt")
expect(files.response.status).toBe(200)
expect(files.body).toContain("hello.txt")

expect(symbols.status).toBe(200)
expect(await symbols.json()).toEqual([])
})
expect(symbols.status).toBe(200)
expect(await symbols.json()).toEqual([])
},
150_000,
)
})
Loading