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
16 changes: 16 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changesets

Add a changeset for every user-facing package change:

```sh
pnpm changeset
```

Use the summary as adopter-facing release notes. The release workflow turns
merged changesets into package changelogs, npm publishes, Git tags, and GitHub
Releases.

The JavaScript packages are currently linked so `@seamless-auth/core` and
official adapters move together while the API is pre-1.0. After the v1 contract
is stable, remove packages from the linked group when they can safely version
independently.
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [["@seamless-auth/core", "@seamless-auth/express"]],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
8 changes: 8 additions & 0 deletions .changeset/workspace-release-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@seamless-auth/core": patch
"@seamless-auth/express": patch
---

Move package development and release management to a pnpm workspace backed by
Changesets. The Express adapter now resolves core through a local workspace link
in development while publishing a normal semver dependency for adopters.
25 changes: 10 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,17 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
- uses: pnpm/action-setup@v4
with:
node-version: 20

- name: Install Core dependencies
working-directory: packages/core
run: npm ci
version: 10.33.0

- name: Install Express dependencies
working-directory: packages/express
run: npm ci
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm

- name: Test Core
working-directory: packages/core
run: npm test
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Test Express
working-directory: packages/express
run: npm test
- name: Test workspace
run: pnpm test
74 changes: 74 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Prerelease

on:
push:
branches:
- dev
- "release/**"
workflow_dispatch:
inputs:
tag:
description: npm dist-tag to publish
required: true
default: alpha
type: choice
options:
- alpha
- beta
- rc

jobs:
prerelease:
name: Publish Prerelease Snapshot
runs-on: ubuntu-latest

permissions:
contents: read
id-token: write

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

- uses: pnpm/action-setup@v4
with:
version: 10.33.0

- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org/

- name: Determine release channel
id: channel
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
elif [ "${{ github.ref_name }}" = "dev" ]; then
TAG="beta"
else
TAG="rc"
fi

echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Check release intent
id: changesets
run: |
node -e "const fs = require('fs'); const hasChangesets = fs.readdirSync('.changeset').some((name) => name.endsWith('.md') && name !== 'README.md'); fs.appendFileSync(process.env.GITHUB_OUTPUT, 'has_changesets=' + hasChangesets + '\n');"

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

- name: Test workspace
run: pnpm test

- name: Publish snapshot packages
if: steps.changesets.outputs.has_changesets == 'true'
run: pnpm release:${{ steps.channel.outputs.tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
93 changes: 25 additions & 68 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,93 +1,50 @@
name: Release

on:
release:
types:
- published
push:
branches:
- main
workflow_dispatch:

jobs:
publish:
name: Publish Package
release:
name: Version or Publish Stable Packages
runs-on: ubuntu-latest

permissions:
contents: read
contents: write
pull-requests: write
id-token: write

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

- uses: pnpm/action-setup@v4
with:
version: 10.33.0

- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org/

- name: Determine package and version
id: meta
run: |
TAG="${{ github.event.release.tag_name }}"

if [[ "$TAG" == core-v* ]]; then
PACKAGE="core"
VERSION="${TAG#core-v}"
elif [[ "$TAG" == express-v* ]]; then
PACKAGE="express"
VERSION="${TAG#express-v}"
else
echo "Invalid tag format"
exit 1
fi

echo "package=$PACKAGE" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT

echo "Publishing $PACKAGE version $VERSION"

- name: Validate package.json version matches tag
working-directory: packages/${{ steps.meta.outputs.package }}
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if [ "$PACKAGE_VERSION" != "${{ steps.meta.outputs.version }}" ]; then
echo "Version mismatch!"
echo "Tag version: ${{ steps.meta.outputs.version }}"
echo "package.json version: $PACKAGE_VERSION"
exit 1
fi

- name: Validate express core dependency
if: steps.meta.outputs.package == 'express'
working-directory: packages/express
run: |
CORE_RANGE=$(node -p "require('./package.json').dependencies['@seamless-auth/core']")
CORE_VERSION=$(node -p "require('../core/package.json').version")
EXPECTED="^${CORE_VERSION}"

if [ "$CORE_RANGE" != "$EXPECTED" ]; then
echo "Express must depend on @seamless-auth/core ${EXPECTED}, found ${CORE_RANGE}"
exit 1
fi

- name: Install dependencies
run: |
if [ "${{ steps.meta.outputs.package }}" = "express" ]; then
npm --prefix packages/core ci
npm --prefix packages/express ci
else
npm --prefix packages/core ci
fi
run: pnpm install --frozen-lockfile

- name: Test package
run: |
if [ "${{ steps.meta.outputs.package }}" = "express" ]; then
npm --prefix packages/express test
else
npm --prefix packages/core test
fi
- name: Test workspace
run: pnpm test

- name: Publish to npm
working-directory: packages/${{ steps.meta.outputs.package }}
run: npm publish --access public --provenance
- name: Version or publish packages
uses: changesets/action@v1
with:
version: pnpm version-packages
publish: pnpm release:stable
createGithubReleases: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.DS_Store
node_modules/
**/node_modules/
**/dist/
.pnpm-store/
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
link-workspace-packages=true
shared-workspace-lockfile=true
34 changes: 29 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,36 @@ Adding a new adapter does not require changes to the core authentication model.

## Versioning and Releases

This repository uses a staged release model:
This repository uses pnpm workspaces and Changesets for package releases.

- Local package dependencies use `workspace:^`, so adapters can test against
unpublished core changes without waiting for core to land on npm first.

- Every adopter-facing change should include a changeset:

```sh
pnpm changeset
```

- **Alpha releases**
Manually published from the `Prerelease` workflow under the `alpha` npm
dist-tag.

- **Beta releases**
Automatically published from the `dev` branch under the `beta` npm dist-tag.
Automatically published from the `dev` branch under the `beta` npm dist-tag
as snapshot builds.

- **RC releases**
Automatically published from `release/**` branches under the `rc` npm
dist-tag as snapshot builds.

- **Stable releases**
Published when a GitHub Release is published for an explicit package tag
(for example `core-v1.0.0` or `express-v1.0.0`).
Published from `main`. Changesets opens a version PR, then publishes npm
packages, Git tags, changelogs, and GitHub Releases when that PR is merged.

Each package is versioned and released independently.
The core and official JavaScript adapters are linked while the API is pre-1.0
so adopters can treat releases as a known-good set. See `RELEASES.md` for the
release policy.

---

Expand All @@ -157,9 +177,13 @@ The documentation covers:

```
.
├─ package.json # Workspace scripts and release tooling
├─ pnpm-workspace.yaml
├─ RELEASES.md
├─ packages/
│ ├─ core/ # Framework-agnostic authentication logic
│ └─ express/ # Express middleware adapter
├─ .changeset/ # Release intent and Changesets config
├─ .github/
│ └─ workflows/ # CI and release pipelines
└─ README.md
Expand Down
54 changes: 54 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Release Management

This repo uses pnpm workspaces plus Changesets.

## Package Graph

- `@seamless-auth/core` is the framework-agnostic package.
- `@seamless-auth/express` depends on `@seamless-auth/core` through
`workspace:^` during local development.
- When packages are packed or published, pnpm rewrites `workspace:^` to the
released semver range, so adapters can be tested against local core changes
before core exists on npm.

## Daily Development

1. Make the code change.
2. Run `pnpm changeset`.
3. Select the package or packages that have adopter-facing changes.
4. Choose the semver bump.
5. Write release notes for adopters, not implementation notes.

## Channels

- `alpha`: manual prerelease snapshots from the `Prerelease` workflow.
- `beta`: automatic snapshots from `dev`.
- `rc`: automatic snapshots from `release/**` branches.
- `latest`: stable releases from `main` through the `Release` workflow.

Prerelease snapshots publish to npm dist-tags without Git tags. Stable releases
publish to npm, create package Git tags, and create GitHub Releases from the
changeset summaries.

## Pre-1.0 Policy

The core and official JavaScript adapters are linked in `.changeset/config.json`
so they move as a known-good set while the API is still settling.

Recommended pre-1.0 behavior:

- core behavior changes: bump core and publish linked adapters.
- adapter-only fixes: bump the adapter; linked packages keep the release train
visible.
- breaking API changes before v1: use a minor bump and clear release notes.

## After v1

Once `@seamless-auth/core` and `@seamless-auth/express` are stable:

- remove adapters from the linked Changesets group when independent versioning
becomes valuable.
- keep adapters compatible with `@seamless-auth/core@^1` unless a core major
requires a coordinated adapter major.
- add new adapters only after they pass the shared conformance suite for the
current known-good core version.
Loading
Loading