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
117 changes: 117 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
build-lsp:
name: Build jaw-lsp (${{ matrix.target }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
archive: tar.gz
- os: macos-13
target: x86_64-apple-darwin
archive: tar.gz
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
archive: tar.gz
- os: windows-latest
target: x86_64-pc-windows-msvc
archive: zip

steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- name: Build jaw-lsp
run: cargo build --release --target ${{ matrix.target }} -p jaw-lsp

- name: Package (unix)
if: matrix.archive == 'tar.gz'
run: |
mkdir -p dist
tar -czf dist/jaw-lsp-${{ matrix.target }}.tar.gz \
-C target/${{ matrix.target }}/release jaw-lsp
shell: bash

- name: Package (windows)
if: matrix.archive == 'zip'
run: |
mkdir dist
Compress-Archive `
-Path target/${{ matrix.target }}/release/jaw-lsp.exe `
-DestinationPath dist/jaw-lsp-${{ matrix.target }}.zip
shell: pwsh

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: jaw-lsp-${{ matrix.target }}
path: dist/*

build-vsix:
name: Build VS Code extension
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Install dependencies
working-directory: editors/vscode
run: npm ci

- name: Build extension
working-directory: editors/vscode
run: npm run build

- name: Package VSIX
working-directory: editors/vscode
run: npm run package

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: vsix
path: editors/vscode/*.vsix

release:
name: Create GitHub Release
needs: [build-lsp, build-vsix]
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Flatten artifacts
run: |
mkdir -p release
find artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" -o -name "*.vsix" \) \
-exec cp {} release/ \;
ls -la release/

- name: Create release
uses: softprops/action-gh-release@v2
with:
files: release/*
generate_release_notes: true
fail_on_unmatched_files: true
38 changes: 34 additions & 4 deletions docs/installation/vscode.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,50 @@
# VS Code Installation

## Prerequisites
## Option A: Prebuilt download (recommended)

1. Go to the [Releases page](https://github.com/dishmint/jaw/releases) and download:
- The `.vsix` extension file (e.g. `jaw-language-0.1.0.vsix`)
- The `jaw-lsp` archive for your platform:
- macOS (Apple Silicon): `jaw-lsp-aarch64-apple-darwin.tar.gz`
- macOS (Intel): `jaw-lsp-x86_64-apple-darwin.tar.gz`
- Linux: `jaw-lsp-x86_64-unknown-linux-gnu.tar.gz`
- Windows: `jaw-lsp-x86_64-pc-windows-msvc.zip`

2. Extract the `jaw-lsp` archive and move the binary somewhere stable (e.g. `~/.local/bin/jaw-lsp` or `/usr/local/bin/jaw-lsp`).

3. Install the extension:

```bash
code --install-extension jaw-language-0.1.0.vsix
```

4. In VS Code settings, set `jaw.server.path` to the absolute path of the `jaw-lsp` binary:

```json
{
"jaw.server.path": "/absolute/path/to/jaw-lsp"
}
```

If `jaw-lsp` is on your `PATH`, this step is optional.

## Option B: Build from source

### Prerequisites

- [Rust toolchain](https://rustup.rs/)
- [Node.js](https://nodejs.org/) (for building the extension)
- VS Code 1.75.0 or later

## 1. Build the language server
### 1. Build the language server

```bash
cargo build --release
```

This produces the `jaw-lsp` binary at `target/release/jaw-lsp`.

## 2. Build and install the VS Code extension
### 2. Build and package the VS Code extension

```bash
cd editors/vscode
Expand All @@ -29,7 +59,7 @@ This produces a `.vsix` file. Install it in VS Code:
code --install-extension jaw-language-0.1.0.vsix
```

## 3. Configure the LSP path
### 3. Configure the LSP path

In VS Code settings, set `jaw.server.path` to the absolute path of the `jaw-lsp` binary:

Expand Down
49 changes: 49 additions & 0 deletions docs/releasing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Releasing JAW

JAW uses Git tags to trigger releases. Pushing a tag matching `v*` runs the
release workflow at `.github/workflows/release.yml`, which builds the
`jaw-lsp` binaries for macOS, Linux, and Windows, packages the VS Code
extension as a `.vsix`, and attaches everything to a new GitHub Release.

## Cutting a release

From a clean working tree on `main`:

```bash
scripts/release.sh 0.2.0
```

The script will:

1. Validate the version is valid semver
2. Bump the version in `jaw-parse/Cargo.toml`, `jaw-lsp/Cargo.toml`, and `editors/vscode/package.json`
3. Refresh `Cargo.lock` and `editors/vscode/package-lock.json`
4. Commit the bumps as `Release v0.2.0`
5. Create the annotated tag `v0.2.0`

It does **not** push. Review the commit, then:

```bash
git push && git push origin v0.2.0
```

Pushing the tag triggers the release workflow. Check the [Actions tab](https://github.com/dishmint/jaw/actions) for progress, and the [Releases page](https://github.com/dishmint/jaw/releases) for the published artifacts.

## Aborting before push

If something looks wrong before you push:

```bash
git tag -d v0.2.0
git reset --hard HEAD~1
```

## Versioning

JAW follows [semantic versioning](https://semver.org/):

- **Patch** (`0.1.0` → `0.1.1`) — bug fixes, no API or syntax changes
- **Minor** (`0.1.0` → `0.2.0`) — new language features or LSP capabilities, backward compatible
- **Major** (`0.1.0` → `1.0.0`) — breaking changes to the JAW spec or LSP protocol

Pre-releases are supported (e.g. `1.0.0-beta.1`).
111 changes: 111 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
#
# Prepare a JAW release: bump versions, commit, and tag.
#
# Usage:
# scripts/release.sh <version>
#
# Example:
# scripts/release.sh 0.2.0
#
# This script does NOT push. After it finishes, review the commit and tag, then:
# git push && git push origin v<version>
# Pushing the tag triggers the release workflow which builds artifacts and
# creates the GitHub Release.

set -euo pipefail

if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version>" >&2
echo "Example: $0 0.2.0" >&2
exit 1
fi

VERSION="$1"

# Validate semver (MAJOR.MINOR.PATCH with optional -prerelease)
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "Error: '$VERSION' is not a valid semver version (e.g. 0.2.0 or 1.0.0-beta.1)" >&2
exit 1
fi

TAG="v$VERSION"

# Run from repo root
REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"

# Refuse to release with a dirty working tree
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Error: working tree is dirty. Commit or stash changes first." >&2
exit 1
fi

# Refuse if the tag already exists
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: tag $TAG already exists." >&2
exit 1
fi

echo "==> Bumping versions to $VERSION"

# Replace the first matching line in a file. Portable across BSD and GNU.
bump_first() {
local file="$1" pattern="$2" replacement="$3"
awk -v pat="$pattern" -v rep="$replacement" '
BEGIN { done = 0 }
!done && $0 ~ pat { print rep; done = 1; next }
{ print }
' "$file" > "$file.new"
mv "$file.new" "$file"
}

# Cargo crates: first `version = "..."` line
bump_first jaw-parse/Cargo.toml '^version = ".*"$' "version = \"$VERSION\""
bump_first jaw-lsp/Cargo.toml '^version = ".*"$' "version = \"$VERSION\""

# VS Code extension: first `"version": "..."` line (the top-level field)
bump_first editors/vscode/package.json '"version": ".*"' " \"version\": \"$VERSION\","

echo "==> Updating Cargo.lock"
cargo check --quiet

echo "==> Updating editors/vscode/package-lock.json"
(cd editors/vscode && npm install --silent)

if git diff --quiet; then
echo "==> Version is already $VERSION; nothing to commit"
COMMIT_SHA="$(git rev-parse --short HEAD)"
else
echo "==> Staging and committing"
git add \
jaw-parse/Cargo.toml \
jaw-lsp/Cargo.toml \
Cargo.lock \
editors/vscode/package.json \
editors/vscode/package-lock.json
git commit -m "Release $TAG"
COMMIT_SHA="$(git rev-parse --short HEAD)"
fi

echo "==> Tagging $TAG"
git tag -a "$TAG" -m "Release $TAG"

cat <<EOF

Release prepared:
- Commit: $COMMIT_SHA
- Tag: $TAG

Next steps:
1. Review the commit: git show HEAD
2. Push commit and tag: git push && git push origin $TAG

Pushing the tag triggers the release workflow at .github/workflows/release.yml,
which builds the jaw-lsp binaries and VSIX and creates the GitHub Release.

To abort instead:
git tag -d $TAG
# If a release commit was created, also undo it:
# git reset --hard HEAD~1
EOF