Skip to content

npm Release

npm Release #5

Workflow file for this run

name: "npm Release"
# Fork-specific workflow for publishing to npm with OIDC
# Separate from release.yaml to make merging upstream changes easier
#
# APPROACH: We bundle all platform binaries in a single npm package (like
# prebuildify) rather than using platform-specific optionalDependencies (like
# esbuild/swc). Rationale:
# - Simpler: one package to publish, not 5+ platform packages
# - More secure: avoids post-install scripts and dependency on npm registry
# - Reliable: works offline, with disabled scripts, and custom registries
# - Small overhead: sqlite-vec binaries are ~200KB each, so bundling all is
# fine
#
# FIRST-TIME SETUP (required before this workflow will work):
#
# 1. Build and publish the package locally to create it on npm:
# ```sh
# ./scripts/vendor.sh
# make loadable
# mkdir -p dist/$(node -p "process.platform + '-' + process.arch")
# cp dist/vec0.* dist/$(node -p "process.platform + '-' + process.arch")/
# npm login
# npm publish --access public --tag alpha # use --tag for prerelease versions
# ```
#
# 2. Configure OIDC trusted publishing on npmjs.com:
# - Go to https://www.npmjs.com/package/@USER/sqlite-vec/access
# - Under "Publishing access" click "Add a trusted publisher"
# - Repository: USER/sqlite-vec
# - Workflow: npm-release.yaml
# - Environment: (leave blank)
#
# 3. Now this workflow can publish subsequent versions automatically
#
# RELEASE FLOW:
# 1. prepare-release: Creates a release branch, bumps VERSION/sqlite-vec.h/package.json
# 2. build-*: All builds run from the release branch (with correct version baked in)
# 3. publish-npm: Publishes to npm, then merges release branch to main on success
#
# If any step fails, main is untouched and the release branch can be deleted.
#
on:
workflow_dispatch:
inputs:
version:
description: "Version bump type"
required: false
type: choice
default: "patch"
options:
- patch
- minor
- major
permissions:
contents: read
jobs:
prepare-release:
runs-on: ubuntu-24.04
permissions:
contents: write
outputs:
release_branch: ${{ steps.prepare.outputs.branch }}
new_version: ${{ steps.prepare.outputs.version }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: "20"
- uses: photostructure/git-ssh-signing-action@fdd4b062a9ba41473f013258cc9c7eea1640f826 # v1.2.0
with:
ssh-signing-key: ${{ secrets.SSH_SIGNING_KEY }}
git-user-name: ${{ secrets.GIT_USER_NAME }}
git-user-email: ${{ secrets.GIT_USER_EMAIL }}
- name: Prepare release branch
id: prepare
run: |
# Get current version from VERSION file (source of truth)
CURRENT=$(cat VERSION | tr -d '[:space:]')
echo "Current version: $CURRENT"
# Calculate new version using npm's semver
# Strip any prerelease suffix for the bump, then we'll keep it simple (no prerelease)
BASE_VERSION=$(echo "$CURRENT" | sed 's/-.*//')
NEW_VERSION=$(npx semver -i ${{ github.event.inputs.version }} "$BASE_VERSION")
echo "New version: $NEW_VERSION"
# Create release branch
BRANCH="release/v${NEW_VERSION}"
git checkout -b "$BRANCH"
# Update VERSION file
echo "$NEW_VERSION" > VERSION
# Regenerate sqlite-vec.h from template
make sqlite-vec.h
# Update package.json (without creating git commit/tag)
npm version "$NEW_VERSION" --no-git-tag-version
# Commit all version changes
git add VERSION sqlite-vec.h package.json package-lock.json
git commit -S -m "release: v${NEW_VERSION}"
git push origin "$BRANCH"
# Output for subsequent jobs
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
build-linux-x64:
needs: [prepare-release]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: ./scripts/vendor.sh
- run: make loadable
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: linux-x64
path: dist/vec0.so
build-linux-arm64:
needs: [prepare-release]
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: ./scripts/vendor.sh
- run: make loadable
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: linux-arm64
path: dist/vec0.so
build-linux-x64-musl:
needs: [prepare-release]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/amd64 node:20-alpine -c "\
apk add build-base bash curl unzip --update-cache && \
cd /tmp/project && \
./scripts/vendor.sh && \
make loadable"
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: linux-x64-musl
path: dist/vec0.so
build-linux-arm64-musl:
needs: [prepare-release]
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/arm64 node:20-alpine -c "\
apk add build-base bash curl unzip --update-cache && \
cd /tmp/project && \
./scripts/vendor.sh && \
make loadable"
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: linux-arm64-musl
path: dist/vec0.so
build-darwin-x64:
needs: [prepare-release]
runs-on: macos-15-intel
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: ./scripts/vendor.sh
- run: make loadable
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: darwin-x64
path: dist/vec0.dylib
build-darwin-arm64:
needs: [prepare-release]
runs-on: macos-14
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- run: ./scripts/vendor.sh
- run: make loadable
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: darwin-arm64
path: dist/vec0.dylib
build-win32-x64:
needs: [prepare-release]
runs-on: windows-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
- run: ./scripts/vendor.sh
shell: bash
- run: mkdir dist
- run: cl.exe /fPIC -shared /W4 /Ivendor/ /O2 /LD sqlite-vec.c -o dist/vec0.dll
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: win32-x64
path: dist/vec0.dll
build-win32-arm64:
needs: [prepare-release]
runs-on: windows-11-arm
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: arm64
- run: ./scripts/vendor.sh
shell: bash
- run: mkdir dist
- run: cl.exe /fPIC -shared /W4 /Ivendor/ /O2 /LD sqlite-vec.c -o dist/vec0.dll
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: win32-arm64
path: dist/vec0.dll
publish-npm:
runs-on: ubuntu-24.04
needs:
[
prepare-release,
build-linux-x64,
build-linux-arm64,
build-linux-x64-musl,
build-linux-arm64-musl,
build-darwin-x64,
build-darwin-arm64,
build-win32-x64,
build-win32-arm64,
]
permissions:
contents: write # Required to push version commits and tags
id-token: write # Required for npm OIDC trusted publishing
env:
NEW_VERSION: ${{ needs.prepare-release.outputs.new_version }}
RELEASE_BRANCH: ${{ needs.prepare-release.outputs.release_branch }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ needs.prepare-release.outputs.release_branch }}
fetch-depth: 0 # Full history for merging
# Download all artifacts into platform-specific subdirectories
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: linux-x64
path: dist/linux-x64
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: linux-arm64
path: dist/linux-arm64
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: linux-x64-musl
path: dist/linux-x64-musl
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: linux-arm64-musl
path: dist/linux-arm64-musl
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: darwin-x64
path: dist/darwin-x64
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: darwin-arm64
path: dist/darwin-arm64
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: win32-x64
path: dist/win32-x64
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: win32-arm64
path: dist/win32-arm64
- run: ls -laR dist/
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- uses: photostructure/git-ssh-signing-action@fdd4b062a9ba41473f013258cc9c7eea1640f826 # v1.2.0
with:
ssh-signing-key: ${{ secrets.SSH_SIGNING_KEY }}
git-user-name: ${{ secrets.GIT_USER_NAME }}
git-user-email: ${{ secrets.GIT_USER_EMAIL }}
- run: npm install -g npm@latest
- name: Bump version and create signed tag
run: |
npm version ${{ github.event.inputs.version }} --sign-git-tag -m "release: %s"
echo "NEW_VERSION=$(npm pkg get version | tr -d '\"')" >> $GITHUB_ENV
- name: Push version commit and tag
run: git push origin main --follow-tags
- name: Create GitHub Release
run: gh release create "v${{ env.NEW_VERSION }}" --generate-notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to npm with OIDC
run: |
VERSION="${NEW_VERSION}"
# Extract prerelease identifier if present (e.g., "beta" from "1.0.0-beta.1")
if [[ "$VERSION" == *"-"* ]]; then
TAG=$(echo "$VERSION" | sed 's/.*-\([a-zA-Z]*\).*/\1/')
npm publish --provenance --access public --tag "$TAG"
else
npm publish --provenance --access public
fi
# Only after successful npm publish: merge to main, tag, and create release
- name: Merge release branch to main
run: |
git checkout main
git merge --ff-only "$RELEASE_BRANCH"
- name: Create signed tag
run: git tag -s "v${NEW_VERSION}" -m "v${NEW_VERSION}"
- name: Push to main with tag
run: git push origin main --follow-tags
- name: Delete release branch
run: git push origin --delete "$RELEASE_BRANCH"
- name: Create GitHub Release
run: gh release create "v${NEW_VERSION}" --generate-notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}