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
44 changes: 44 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,55 @@ jobs:
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
publish-npm:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # mint an OIDC token for npm trusted publishing (no NPM_TOKEN needed)
needs:
- build
- configure
if: ${{ needs.configure.outputs.should_release == 'true' }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup PNPM
uses: pnpm/action-setup@v3
- name: Setup Node
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Build Publishable Packages
run: |
# Build each publishable package and its dependency closure (turbo skips
# packages that have no build script, e.g. those that publish source directly).
filters=()
while IFS=$'\t' read -r name version pkgPath; do
filters+=("--filter=${name}...")
done < <(scripts/list-publishable.sh)
pnpm exec turbo run build "${filters[@]}"
- name: Publish Packages
run: |
# Publish each marked package whose version is not already on npm. The version
# check keeps this idempotent across workflow re-runs.
while IFS=$'\t' read -r name version pkgPath; do
if [ -n "$(npm view "${name}@${version}" version 2>/dev/null)" ]; then
echo "Skipping ${name}@${version} (already published)"
continue
fi
echo "Publishing ${name}@${version}"
pnpm --filter "${name}" publish --no-git-checks
done < <(scripts/list-publishable.sh)
release:
runs-on: ubuntu-latest
needs:
- build
- configure
- publish-npm
steps:
- name: Checkout Repository
uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "opendatacapture",
"type": "module",
"version": "1.16.3",
"version": "1.16.4",
"private": true,
"packageManager": "pnpm@10.7.0",
"packageManager": "pnpm@10.34.1",
"license": "Apache-2.0",
"engines": {
"node": ">=v22.11.0"
Expand Down
5 changes: 4 additions & 1 deletion packages/instrument-bundler/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"name": "@opendatacapture/instrument-bundler",
"type": "module",
"version": "0.0.0",
"version": "1.16.4",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"exports": {
".": "./src/index.ts"
},
Expand Down
5 changes: 4 additions & 1 deletion packages/instrument-guidelines/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"name": "@opendatacapture/instrument-guidelines",
"type": "module",
"version": "0.0.1",
"version": "1.16.4",
"description": "Guidelines for authoring Open Data Capture instruments, intended to be read by an AI agent (e.g. Claude Code).",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"keywords": [
"opendatacapture",
"instrument",
Expand Down
5 changes: 4 additions & 1 deletion packages/serve-instrument/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"name": "@opendatacapture/serve-instrument",
"type": "module",
"version": "0.0.9",
"version": "1.16.4",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"bin": {
"serve-instrument": "./dist/cli.js"
},
Expand Down
5 changes: 4 additions & 1 deletion runtime/v1/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
{
"name": "@opendatacapture/runtime-v1",
"type": "module",
"version": "1.8.10",
"version": "1.16.4",
"author": {
"name": "Douglas Neuroinformatics",
"email": "support@douglasneuroinformatics.ca"
},
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"homepage": "https://github.com/DouglasNeuroInformatics/OpenDataCapture/#readme",
"repository": {
"type": "git",
Expand Down
20 changes: 9 additions & 11 deletions scripts/increment-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ IFS=$'\n\t'

projectRoot="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"

# package.json files (relative to projectRoot) kept in sync with the root version
packages=(
"package.json"
"runtime/v1/package.json"
"packages/instrument-bundler/package.json"
"packages/serve-instrument/package.json"
"packages/instrument-guidelines/package.json"
)
# package.json files kept in sync with the root version: the (private) root package,
# plus every publishable package discovered via its `publishConfig` marker. See
# scripts/list-publishable.sh — adding a new publishable package needs no edit here.
packages=("$projectRoot/package.json")
while IFS=$'\t' read -r _name _version pkgPath; do
packages+=("$pkgPath")
done < <("$projectRoot/scripts/list-publishable.sh")

currentVersion=$(node -e 'process.stdout.write(require(process.argv[1]).version)' "$projectRoot/package.json")
IFS='.' read -r major minor patch <<< "$currentVersion"
Expand All @@ -38,8 +37,7 @@ case "$confirm" in
*) echo "Aborted."; exit 0 ;;
esac

for pkg in "${packages[@]}"; do
file="$projectRoot/$pkg"
for file in "${packages[@]}"; do
node -e '
const fs = require("fs");
const [file, version] = process.argv.slice(1);
Expand All @@ -51,7 +49,7 @@ for pkg in "${packages[@]}"; do
}
fs.writeFileSync(file, updated);
' "$file" "$newVersion"
echo "Updated $pkg -> $newVersion"
echo "Updated ${file#"$projectRoot"/} -> $newVersion"
done

echo "Done! All packages set to $newVersion"
30 changes: 30 additions & 0 deletions scripts/list-publishable.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
#
# Lists the workspace packages that should be published to npm on release.
#
# A package is "publishable" when it is not private and declares a `publishConfig`
# field in its package.json. This is the single source of truth consumed by both
# scripts/increment-version.sh (to keep versions in sync) and the release workflow
# (to decide what to publish). Adding a future package only requires the
# `publishConfig` field — no list needs editing here.
#
# Output (one package per line, tab-separated): <name>\t<version>\t<package.json path>

set -euo pipefail
IFS=$'\n\t'

[ "${BASH_VERSINFO:-0}" -ge 5 ] || (echo "Error: Bash >= 5.0 is required for this script" >&2 && exit 1)

projectRoot="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"

# Enumerate every workspace package (depth -1 = workspace packages only, no deps),
# then keep the non-private ones that declare a publishConfig.
pnpm -C "$projectRoot" ls -r --depth -1 --json \
| jq -r '.[].path' \
| while read -r dir; do
pkg="$dir/package.json"
[ -f "$pkg" ] || continue
jq -r --arg path "$pkg" \
'select(.private != true and .publishConfig != null) | [.name, .version, $path] | @tsv' "$pkg"
done \
| sort
Loading