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

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to validate, for example v0.2.0-alpha.0'
required: true

permissions:
contents: write
id-token: write

jobs:
release:
name: Validate, publish, and release
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org

- name: Verify tag matches package version
id: version
shell: bash
run: |
set -euo pipefail

if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
tag="${{ inputs.tag }}"
else
tag="${GITHUB_REF_NAME}"
fi

if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "Release tags must look like v0.1.4 or v0.2.0-alpha.0; got $tag" >&2
exit 1
fi

package_version="$(node -p "require('./package.json').version")"
tag_version="${tag#v}"

if [ "$package_version" != "$tag_version" ]; then
echo "Tag $tag does not match package.json version $package_version" >&2
exit 1
fi

npm_tag="latest"
prerelease="false"
if [[ "$package_version" == *-* ]]; then
prerelease="true"
npm_tag="${package_version#*-}"
npm_tag="${npm_tag%%.*}"
fi

echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=$package_version" >> "$GITHUB_OUTPUT"
echo "npm_tag=$npm_tag" >> "$GITHUB_OUTPUT"
echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT"

- name: Install dependencies
run: npm ci

- name: Test
run: npm test

- name: Build
run: npm run build

- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
set -euo pipefail

package="radius-cli@${{ steps.version.outputs.version }}"
if npm view "$package" version >/dev/null 2>&1; then
echo "$package is already published; skipping npm publish."
exit 0
fi

npm publish --provenance --access public --tag ${{ steps.version.outputs.npm_tag }}

- name: Ensure npm dist-tag
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
set -euo pipefail

npm dist-tag add \
"radius-cli@${{ steps.version.outputs.version }}" \
"${{ steps.version.outputs.npm_tag }}"

- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail

args=(
"${{ steps.version.outputs.tag }}"
--title "radius-cli ${{ steps.version.outputs.tag }}"
--generate-notes
)

if [ "${{ steps.version.outputs.prerelease }}" = "true" ]; then
args+=(--prerelease)
else
args+=(--latest)
fi

if gh release view "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
echo "GitHub release ${{ steps.version.outputs.tag }} already exists; skipping release creation."
else
gh release create "${args[@]}"
fi
50 changes: 50 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Release Process

The release source of truth is the version in `package.json`. Every published
npm version should have a matching git tag and GitHub release.

`v0.1.4` is the baseline release for the already-published npm package. Future
releases should be created by bumping the package version and pushing the
matching `v*` tag.

## Stable Release

```bash
npm version 0.1.5
git push origin main --tags
```

Pushing the `v0.1.5` tag starts the release workflow. The workflow verifies that
the tag matches `package.json`, runs tests and build, publishes `radius-cli` to
npm with the `latest` dist-tag, ensures the npm dist-tag points at that version,
and creates the GitHub release.

## Alpha Release

```bash
npm version 0.2.0-alpha.0
git push origin main --tags
```

Pushing the `v0.2.0-alpha.0` tag starts the same workflow. Because the package
version is a prerelease, npm gets the `alpha` dist-tag and the GitHub release is
marked as a prerelease. The workflow also ensures `radius-cli@alpha` points at
that version.

Consumers can install the alpha explicitly:

```bash
npm install -g radius-cli@alpha
npx radius-cli@alpha --help
```

## Required Repository Setup

The workflow needs npm publish permission. Configure one of:

- npm trusted publishing for this repository and workflow, or
- an `NPM_TOKEN` repository secret with publish access to the `radius-cli`
package.

Do not publish to npm manually without also creating the matching git tag,
GitHub release, and npm dist-tag.