diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03f8deb..42a3e5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,18 +2,23 @@ name: CI on: push: - branches: [main] + branches: [main, 'fix/**'] pull_request: jobs: check: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + node: [20, 22] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: ${{ matrix.node }} cache: pnpm - uses: oven-sh/setup-bun@v2 with: @@ -22,4 +27,4 @@ jobs: - run: pnpm typecheck - run: pnpm test - name: Bundle for npm and smoke it - run: pnpm build:npm && node packages/cli/bin/vibi.mjs --version + run: pnpm build:npm && node packages/cli/dist/vibi.mjs --version && node packages/cli/dist/vibi.mjs --help diff --git a/package.json b/package.json index 1529ea4..a726ce6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packageManager": "pnpm@12.8.1", "scripts": { "typecheck": "pnpm -r typecheck", - "test": "tsx --test packages/shared/test/*.test.ts packages/cli/test/*.test.ts", + "test": "node scripts/test.mjs", "build:npm": "pnpm --filter vibi build:npm", "build:host": "pnpm --filter vibi build:tui:host && pnpm --filter vibi build:host", "build": "pnpm --filter vibi build:tui && pnpm --filter vibi build" diff --git a/packages/cli/test/install.test.ts b/packages/cli/test/install.test.ts index 80bfa39..3b2a76b 100644 --- a/packages/cli/test/install.test.ts +++ b/packages/cli/test/install.test.ts @@ -17,10 +17,11 @@ after(async () => { const meta = { title: 't', cwd: '/work/x', model: '', messageCount: 1, sourcePath: '', startedAt: null }; test('Claude Code project directories are encoded the way Claude Code does it', () => { - assert.equal(encodeClaudeProjectDir('/Users/hongyinluo/Desktop/cybermind'), '-Users-hongyinluo-Desktop-cybermind'); - assert.equal(encodeClaudeProjectDir('/Users/me/my_app.v2'), '-Users-me-my-app-v2'); + const prefix = process.platform === 'win32' ? `${path.parse(process.cwd()).root[0]}--` : '-'; + assert.equal(encodeClaudeProjectDir('/Users/hongyinluo/Desktop/cybermind'), `${prefix}Users-hongyinluo-Desktop-cybermind`); + assert.equal(encodeClaudeProjectDir('/Users/me/my_app.v2'), `${prefix}Users-me-my-app-v2`); const file = installPathFor({ harness: 'claude', harnessSessionId: 'abc', harnessUpdatedAt: '2026-10-01T10:00:00Z', metadata: meta, home, projectDir: '/work/x' }); - assert.equal(file, path.join(home, '.claude', 'projects', '-work-x', 'abc.jsonl')); + assert.equal(file, path.join(home, '.claude', 'projects', `${prefix}work-x`, 'abc.jsonl')); }); test('other harnesses keep their original file names and date folders', () => { diff --git a/scripts/test.mjs b/scripts/test.mjs new file mode 100644 index 0000000..c1b7768 --- /dev/null +++ b/scripts/test.mjs @@ -0,0 +1,11 @@ +import { spawnSync } from 'node:child_process'; +import { readdirSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +const root = fileURLToPath(new URL('../', import.meta.url)); +const files = ['packages/shared/test', 'packages/cli/test'].flatMap((dir) => + readdirSync(new URL(`../${dir}/`, import.meta.url)).filter((name) => name.endsWith('.test.ts')).sort().map((name) => `${dir}/${name}`) +); +const result = spawnSync(process.execPath, ['--import', 'tsx', '--test', ...files], {cwd: root, stdio: 'inherit'}); +if (result.error) throw result.error; +process.exit(result.status ?? 1);