Skip to content
Open
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
1 change: 1 addition & 0 deletions .changepacks/changepack_log_MKrnQd_SF1OEJcvW1GeJa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"changes": {"crates/vespertide-cli/Cargo.toml": "Minor", "bridge/node/package.json": "Minor"}, "note": "vespertide-cli를 lib + bin으로 나누고(run / main / run_cli 진입점) 그 위에 N-API 브리지 bridge/node를 추가해 CLI를 npm 패키지 vespertide(플랫폼 패키지 @vespertide/cli-*)로 배포한다. cli는 다른 크레이트가 핀하지 않는 leaf라 단독 Minor로 올리고, npm 매니페스트는 updateOn으로 매 크레이트 웨이브에 Patch로 따라오며, 이번처럼 같은 단계로 올릴 때는 명시한다.", "date": "2026-09-08T09:00:00.0000000Z"}
11 changes: 9 additions & 2 deletions .changepacks/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
"**",
"!crates/**",
"crates/vespertide-schema-gen/Cargo.toml",
"!apps/vscode-extension/package.json"
"!apps/vscode-extension/package.json",
"!bridge/node/package.json"
],
"baseBranch": "main",
"latestPackage": "crates/vespertide/Cargo.toml",
"publish": {
"apps/vscode-extension/package.json": "echo skip npm publish for vscode-extension - shipped via vsce in the vscode-release job"
"apps/vscode-extension/package.json": "echo skip npm publish for vscode-extension - shipped via vsce in the vscode-release job",
"bridge/node/package.json": "echo skip npm publish here - published by the node-publish job"
},
"updateOn": {
"crates/*": [
"bridge/node/package.json"
]
}
}
141 changes: 140 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ jobs:
echo "Computed cargo-semver-checks release-type: '${RT:-<derive-from-version>}'"
- uses: obi1kenobi/cargo-semver-checks-action@v2
with:
# Only check published crates; skip cli (binary) and schema-gen (publish=false)
# Only check published crates; skip schema-gen (publish=false) and cli, whose
# lib target is new — add it once a release with the lib is on crates.io
package: vespertide,vespertide-core,vespertide-config,vespertide-loader,vespertide-naming,vespertide-planner,vespertide-query,vespertide-exporter,vespertide-macro
feature-group: default-features
# Empty => action derives strictly from the Cargo.toml version.
Expand Down Expand Up @@ -564,6 +565,144 @@ jobs:
- name: Check schema drift
run: git diff --no-index --exit-code -- schemas _tmp_schemas

# npm: the CLI as a Node addon (bridge/node, napi-rs). Fires only when the
# npm manifest is in the changepacks wave. Mirrors lsp-release's target
# table; `cross` is used for the same single aarch64-linux cell.
node-build:
name: npm Build (${{ matrix.target }})
needs: changepacks
if: ${{ contains(needs.changepacks.outputs.changepacks, 'bridge/node/package.json') }}
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runs-on: ubuntu-latest
use_cross: false
- target: aarch64-unknown-linux-gnu
runs-on: ubuntu-latest
use_cross: true
- target: x86_64-apple-darwin
# Cross-arch on the ARM runner, as in lsp-release.
runs-on: macos-latest
use_cross: false
- target: aarch64-apple-darwin
runs-on: macos-latest
use_cross: false
- target: x86_64-pc-windows-msvc
runs-on: windows-latest
use_cross: false
steps:
- uses: actions/checkout@v7

- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
target: ${{ matrix.target }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install cross (aarch64-unknown-linux-gnu only)
if: matrix.use_cross
uses: taiki-e/install-action@v2.86.3
with:
tool: cross

- name: Install
working-directory: bridge/node
run: bun install --frozen-lockfile

- name: Build addon (native)
if: ${{ !matrix.use_cross }}
working-directory: bridge/node
run: bun run build --target ${{ matrix.target }}

- name: Build addon (cross)
if: matrix.use_cross
working-directory: bridge/node
run: bun run build --target ${{ matrix.target }} --use-cross

# The addon only loads where it was built for; the two cross-arch
# cells skip the smoke test.
- name: Smoke test
if: ${{ matrix.target != 'aarch64-unknown-linux-gnu' && matrix.target != 'x86_64-apple-darwin' }}
working-directory: bridge/node
run: bun test

- uses: actions/upload-artifact@v7
with:
name: bindings-${{ matrix.target }}
path: bridge/node/vespertide.*.node
if-no-files-found: error
retention-days: 1

node-publish:
name: npm Publish
needs: [changepacks, node-build]
if: ${{ contains(needs.changepacks.outputs.changepacks, 'bridge/node/package.json') }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

# npm (not bun) performs the publish so the registry auth from
# setup-node applies; `npm publish` runs `prepublishOnly`, which pushes
# the five platform packages before the root one.
- uses: actions/setup-node@v7
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'

- uses: actions-rust-lang/setup-rust-toolchain@v1

- name: Install
working-directory: bridge/node
run: bun install --frozen-lockfile

# `index.js` / `index.d.ts` are build outputs (gitignored); only
# `napi build` writes them, so the publish host builds once for
# its own platform before assembling the packages.
- name: Build addon (regenerates the JS loader)
working-directory: bridge/node
run: bun run build

- name: Create platform package dirs
working-directory: bridge/node
run: bunx napi create-npm-dirs

- uses: actions/download-artifact@v8
with:
path: bridge/node/artifacts

- name: Move addons into platform packages
working-directory: bridge/node
run: bun run artifacts

- name: Upload addons to changepacks release
uses: owjs3901/upload-github-release-asset@main
with:
upload_url: ${{ fromJson(needs.changepacks.outputs.release_assets_urls)['bridge/node/package.json'] }}
asset_path: bridge/node/npm/*/vespertide.*.node

- name: Publish to npm
working-directory: bridge/node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NODE_AUTH_TOKEN" ]; then
echo "::warning::NPM_TOKEN not set — skipping npm publish"
else
npm publish --access public
fi
shell: bash

insta-pending:
name: insta-pending
runs-on: ubuntu-latest
Expand Down
17 changes: 14 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ vespertide/
│ ├── vespertide-naming/ # Naming convention utilities
│ ├── vespertide-schema-gen/# JSON Schema generation
│ └── vespertide/ # Re-export crate (user-facing API)
├── bridge/node/ # N-API bridge: the CLI as the `vespertide` npm package (+ @vespertide/cli-* platform packages)
├── examples/app/ # Example project with models/migrations (out-of-workspace)
├── tools/lsp-profile/ # LSP synthetic / realistic workload + latency profiler (out-of-workspace)
├── fuzz/ # cargo-fuzz targets (4 targets, see FUZZING section)
Expand Down Expand Up @@ -522,6 +523,13 @@ There is no separate `lsp-release.yml` or `vscode-release.yml`.
`crates/vespertide-lsp/Cargo.toml` is in the wave. Builds the
`vespertide-lsp` binary natively + cross + windows, packages `tar.gz`/`zip`
with `sha256`, uploads to the changepacks release.
- **`node-build`** (matrix × 5 targets) + **`node-publish`** — fire only when
`bridge/node/package.json` is in the wave. Build the napi addon per
target, rebuild once on the publish host (only `napi build` writes the
gitignored `index.js` loader), assemble the `@vespertide/cli-*` platform packages with
`napi create-npm-dirs` / `napi artifacts`, upload the `.node` files to
the changepacks release, then `npm publish` (skipped with a warning
when `NPM_TOKEN` is unset).
- **`vscode-release`** (matrix × 5 vsce targets) — fires only when
`apps/vscode-extension/package.json` is in the wave. Pulls the matching
LSP binary (just-released if LSP is also in the wave, otherwise the latest
Expand All @@ -530,10 +538,13 @@ There is no separate `lsp-release.yml` or `vscode-release.yml`.

### Configuration
- `.changepacks/config.json` — tracks `crates/**/Cargo.toml` (except
`vespertide-schema-gen` which is `publish=false`) and
`apps/vscode-extension/package.json`. `apps/landing`, `apps/zed-extension`,
`vespertide-schema-gen` which is `publish=false`),
`apps/vscode-extension/package.json` and `bridge/node/package.json`.
`updateOn` adds the npm manifest to every crate wave as a **Patch** bump so
`node-publish` always fires; list it explicitly in the descriptor when the
npm version should move at the same level as the crates. `apps/landing`, `apps/zed-extension`,
`tools/`, and `tests/` are intentionally not tracked.
- Required secrets: `CARGO_REGISTRY_TOKEN`, `VSCE_PAT`, `OVSX_PAT`.
- Required secrets: `CARGO_REGISTRY_TOKEN`, `VSCE_PAT`, `OVSX_PAT`, `NPM_TOKEN`.
- `.changepacks/changepack_log_*.json` files are the **committed bump
descriptors** (written by `bunx @changepacks/cli`, consumed by
`changepacks/action` on merge — analogous to changesets' `.changeset/*.md`),
Expand Down
108 changes: 107 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# cargo test --manifest-path tests/runtime-sqlite/Cargo.toml
# cargo build --manifest-path examples/app/Cargo.toml
# cargo run --release --manifest-path tools/lsp-profile/Cargo.toml -- --workload synthetic
members = ["crates/*", "fuzz"]
members = ["crates/*", "fuzz", "bridge/*"]
exclude = ["apps/zed-extension", "examples/app", "tests/runtime-sqlite", "tools/lsp-profile"]
default-members = [
"crates/vespertide",
Expand Down Expand Up @@ -95,6 +95,7 @@ vespertide-planner = { path = "crates/vespertide-planner", version = "=0.3.0" }
vespertide-query = { path = "crates/vespertide-query", version = "=0.3.0" }
vespertide-exporter = { path = "crates/vespertide-exporter", version = "=0.3.0" }
vespertide-lsp = { path = "crates/vespertide-lsp", version = "=0.3.0" }
vespertide-cli = { path = "crates/vespertide-cli", version = "=0.3.0" }

[profile.dev]
debug = 1 # Line tables only — faster DWARF generation for large codegen output
Loading
Loading