Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
6 changes: 0 additions & 6 deletions .changeset/README.md

This file was deleted.

12 changes: 0 additions & 12 deletions .changeset/config.json

This file was deleted.

23 changes: 9 additions & 14 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ This directory contains the VS Code dev container configuration for OpenSpec dev

## What's Included

- **Node.js 20 LTS** (>=20.19.0) - TypeScript/JavaScript runtime
- **pnpm** - Fast, disk space efficient package manager
- **Bun** - Fast JavaScript runtime, bundler, and package manager
- **Git + GitHub CLI** - Version control tools
- **VS Code Extensions**:
- ESLint & Prettier for code quality
- Vitest Explorer for running tests
- GitLens for enhanced git integration
- Error Lens for inline error highlighting
- Code Spell Checker
Expand Down Expand Up @@ -37,7 +35,7 @@ This directory contains the VS Code dev container configuration for OpenSpec dev

3. **Wait for Setup**:
- The container will build (first time takes a few minutes)
- `pnpm install` runs automatically via `postCreateCommand`
- `bun install` runs automatically via `postCreateCommand`
- All extensions install automatically

### Daily Development
Expand All @@ -46,19 +44,16 @@ Once set up, the container preserves your development environment:

```bash
# Run development build
pnpm run dev
bun run dev

# Run CLI in development
pnpm run dev:cli
bun run dev:cli

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch
bun test

# Build the project
pnpm run build
bun run build
```

### SSH Keys
Expand All @@ -72,9 +67,9 @@ If you modify `.devcontainer/devcontainer.json`:

## Benefits

- No need to install Node.js or pnpm on your local machine
- No need to install Bun on your local machine
- Consistent development environment across team members
- Isolated from other Node.js projects on your machine
- Isolated from other projects on your machine
- All dependencies and tools containerized
- Easy onboarding for new developers

Expand All @@ -88,5 +83,5 @@ If you modify `.devcontainer/devcontainer.json`:
- Rebuild the container: "Dev Containers: Rebuild Container"

**Permission issues:**
- The container runs as the `node` user (non-root)
- The container runs as the `bun` user (non-root)
- Files created in the container are owned by this user
27 changes: 4 additions & 23 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"name": "OpenSpec Development",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm",
"image": "oven/bun:latest",

// Additional tools and features
"features": {
"ghcr.io/devcontainers/features/git:1": {
"version": "latest",
Expand All @@ -13,10 +12,8 @@
}
},

// Configure tool-specific properties
"customizations": {
"vscode": {
// Set default container specific settings
"settings": {
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
Expand All @@ -29,40 +26,24 @@
"terminal.integrated.defaultProfile.linux": "bash"
},

// Add extensions you want installed when the container is created
"extensions": [
// TypeScript/JavaScript essentials
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",

// Testing
"vitest.explorer",

// Git
"eamodio.gitlens",

// Utilities
"streetsidesoftware.code-spell-checker",
"usernamehw.errorlens",
"christian-kohler.path-intellisense"
]
}
},

// Use 'forwardPorts' to make a list of ports inside the container available locally
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created
"postCreateCommand": "corepack enable && corepack prepare pnpm@latest --activate && pnpm install",
"postCreateCommand": "bun install",

// Configure mounts to preserve SSH keys for git operations
"mounts": [
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/node/.ssh,readonly,type=bind,consistency=cached"
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/bun/.ssh,readonly,type=bind,consistency=cached"
],

// Set the default user to 'node' (non-root user)
"remoteUser": "node",
"remoteUser": "bun",

// Ensure git is properly configured
"initializeCommand": "echo 'Initializing dev container...'"
}
207 changes: 18 additions & 189 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ on:
branches: [main]
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read
Expand All @@ -15,211 +14,41 @@ concurrency:
cancel-in-progress: true

jobs:
test_pr:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.event_name == 'pull_request'

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build project
run: pnpm run build

- name: Run tests
run: pnpm test

- name: Upload test coverage
uses: actions/upload-artifact@v4
with:
name: coverage-report-pr
path: coverage/
retention-days: 7

test_matrix:
name: Test (${{ matrix.label }})
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 15
if: github.event_name != 'pull_request'
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
shell: bash
label: linux-bash
- os: macos-latest
shell: bash
label: macos-bash
- os: windows-latest
shell: pwsh
label: windows-pwsh

defaults:
run:
shell: ${{ matrix.shell }}

os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
- uses: oven-sh/setup-bun@v2
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'

- name: Print environment diagnostics
run: |
node -p "JSON.stringify({ platform: process.platform, arch: process.arch, shell: process.env.SHELL || process.env.ComSpec || '' })"
bun-version: latest
Comment on lines +28 to +30
Copy link

@coderabbitai coderabbitai bot Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

latest stable version of Bun runtime December 2025

💡 Result:

The latest stable Bun runtime is v1.3.5 — released December 17, 2025. [1][2]

Sources:
[1] Bun release notes: Bun v1.3.5.
[2] endoflife.date entry for Bun (shows latest 1.3.5, Dec 17, 2025).


Consider pinning Bun version for reproducible builds.

Using bun-version: latest may lead to unpredictable CI behavior when Bun releases updates. Consider pinning to a specific version for more reproducible builds:

Suggested fix
       - uses: oven-sh/setup-bun@v2
         with:
-          bun-version: latest
+          bun-version: "1.3.x"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: oven-sh/setup-bun@v2
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Print environment diagnostics
run: |
node -p "JSON.stringify({ platform: process.platform, arch: process.arch, shell: process.env.SHELL || process.env.ComSpec || '' })"
bun-version: latest
- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.x"
🤖 Prompt for AI Agents
.github/workflows/ci.yml around lines 28 to 30: the workflow pins Bun with
bun-version: latest which can cause non-reproducible CI when Bun updates; change
this to a specific, tested Bun version (e.g., a fixed semantic version or
commit) by replacing "latest" with the chosen version string and update any
related workflow docs or matrix entries so CI consistently uses that pinned
version.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YOLO my fren

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ClankerGuru, got it! I'll keep that in mind for future reviews. 🚀


✏️ Learnings added
Learnt from: ClankerGuru
Repo: ClankerGuru/OpenSpec PR: 1
File: .github/workflows/ci.yml:28-30
Timestamp: 2025-12-28T09:37:00.257Z
Learning: In the clanker-guru/openspec project CI workflows, the maintainers prefer using `bun-version: latest` rather than pinning to a specific Bun version, accepting the trade-off for staying current with the latest Bun releases.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ClankerGuru
Repo: ClankerGuru/OpenSpec PR: 1
File: package.json:29-31
Timestamp: 2025-12-28T09:27:28.326Z
Learning: The clanker-guru/openspec package is intentionally designed to run exclusively on the Bun runtime. The bin entry points to a TypeScript file (bin/openspec.ts) with a Bun shebang (#!/usr/bin/env bun), and this is by design, not a compatibility issue.

Learnt from: ClankerGuru
Repo: ClankerGuru/OpenSpec PR: 1
File: package.json:51-51
Timestamp: 2025-12-28T09:28:29.872Z
Learning: The clanker-guru/openspec package maintainers explicitly do not want npm compatibility or fallbacks. The package is intentionally Bun-exclusive, and npm-based workflows should not be suggested.


- name: Install dependencies
run: pnpm install --frozen-lockfile
- run: bun install --frozen-lockfile

- name: Build project
run: pnpm run build
- run: bun run build

- name: Run tests
run: pnpm test

- name: Upload test coverage
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: coverage-report-main
path: coverage/
retention-days: 7
- run: bun test

lint:
name: Lint & Type Check
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
- uses: oven-sh/setup-bun@v2
with:
node-version: '20'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build project
run: pnpm run build
bun-version: latest

- name: Type check
run: pnpm exec tsc --noEmit
- run: bun install --frozen-lockfile

- name: Lint
run: pnpm lint
- run: bun run build

- name: Check for build artifacts
run: |
if [ ! -d "dist" ]; then
echo "Error: dist directory not found after build"
exit 1
fi
if [ ! -f "dist/cli/index.js" ]; then
echo "Error: CLI entry point not found"
exit 1
fi
- run: bun run typecheck

validate-changesets:
name: Validate Changesets
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Validate changesets
run: |
if command -v changeset &> /dev/null; then
pnpm exec changeset status --since=origin/main
else
echo "Changesets not configured, skipping validation"
fi

required-checks-pr:
name: All checks passed
runs-on: ubuntu-latest
needs: [test_pr, lint]
if: always() && github.event_name == 'pull_request'
steps:
- name: Verify all checks passed
run: |
if [[ "${{ needs.test_pr.result }}" != "success" ]]; then
echo "Test job failed"
exit 1
fi
if [[ "${{ needs.lint.result }}" != "success" ]]; then
echo "Lint job failed"
exit 1
fi
echo "All required checks passed!"

required-checks-main:
name: All checks passed
runs-on: ubuntu-latest
needs: [test_matrix, lint]
if: always() && github.event_name != 'pull_request'
steps:
- name: Verify all checks passed
run: |
if [[ "${{ needs.test_matrix.result }}" != "success" ]]; then
echo "Matrix test job failed"
exit 1
fi
if [[ "${{ needs.lint.result }}" != "success" ]]; then
echo "Lint job failed"
exit 1
fi
echo "All required checks passed!"
- run: bun run lint
Loading