2020 - patch
2121 - minor
2222 - major
23+ - prerelease
24+ - preminor
25+ - premajor
2326 default : " patch"
27+ preid :
28+ description : " Prerelease identifier (used with pre* version types)"
29+ required : false
30+ type : choice
31+ options :
32+ - beta
33+ - alpha
34+ - rc
35+ - next
36+ default : " beta"
37+ tag :
38+ description : " NPM dist-tag (use beta/alpha/next for prereleases, latest for stable)"
39+ required : false
40+ type : choice
41+ options :
42+ - latest
43+ - beta
44+ - alpha
45+ - rc
46+ - next
47+ default : " latest"
2448 custom_version :
2549 description : " Custom version (optional, overrides version type)"
2650 required : false
5074 runs-on : ubuntu-latest
5175 outputs :
5276 new_version : ${{ steps.bump.outputs.new_version }}
77+ is_prerelease : ${{ steps.bump.outputs.is_prerelease }}
5378
5479 steps :
5580 - uses : actions/checkout@v4
@@ -71,12 +96,16 @@ jobs:
7196 run : |
7297 CUSTOM_VERSION="${{ github.event.inputs.custom_version }}"
7398 VERSION_TYPE="${{ github.event.inputs.version }}"
99+ PREID="${{ github.event.inputs.preid || 'beta' }}"
74100 CURRENT_VERSION=$(node -p "require('./package.json').version")
75101 echo "Current version: $CURRENT_VERSION"
76102
77103 if [ -n "$CUSTOM_VERSION" ]; then
78104 echo "Setting version to custom value: $CUSTOM_VERSION"
79105 npm version "$CUSTOM_VERSION" --no-git-tag-version --allow-same-version
106+ elif [[ "$VERSION_TYPE" == pre* ]]; then
107+ echo "Bumping version: $VERSION_TYPE with preid=$PREID"
108+ npm version "$VERSION_TYPE" --preid="$PREID" --no-git-tag-version
80109 else
81110 echo "Bumping version: $VERSION_TYPE"
82111 npm version "$VERSION_TYPE" --no-git-tag-version
@@ -86,6 +115,15 @@ jobs:
86115 echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
87116 echo "New version: $NEW_VERSION"
88117
118+ # Detect prerelease (version contains a hyphen, e.g. 2.0.66-beta.0)
119+ if [[ "$NEW_VERSION" == *"-"* ]]; then
120+ echo "is_prerelease=true" >> $GITHUB_OUTPUT
121+ echo "Prerelease detected: $NEW_VERSION"
122+ else
123+ echo "is_prerelease=false" >> $GITHUB_OUTPUT
124+ echo "Stable release: $NEW_VERSION"
125+ fi
126+
89127 # Sync all package versions
90128 node -e "
91129 const fs = require('fs');
@@ -155,6 +193,18 @@ jobs:
155193 name : build-output
156194 path : .
157195
196+ - name : Validate tag for prerelease
197+ if : startsWith(github.event.inputs.version, 'pre') && (github.event.inputs.tag == 'latest' || github.event.inputs.tag == '')
198+ run : |
199+ echo "::error::Prerelease versions must not use the 'latest' dist-tag. Please set tag to 'beta', 'alpha', 'rc', or 'next'."
200+ exit 1
201+
202+ - name : Validate tag for custom prerelease version
203+ if : contains(needs.build.outputs.new_version, '-') && (github.event.inputs.tag == 'latest' || github.event.inputs.tag == '')
204+ run : |
205+ echo "::error::Custom version '${{ needs.build.outputs.new_version }}' is a prerelease and must not use the 'latest' dist-tag. Please set tag to 'beta', 'alpha', 'rc', or 'next'."
206+ exit 1
207+
158208 - name : Update npm for OIDC support
159209 run : npm install -g npm@latest
160210
@@ -171,14 +221,14 @@ jobs:
171221 - name : Publish @agent-relay/dashboard
172222 if : github.event.inputs.dry_run != 'true' && (github.event.inputs.package == 'all' || github.event.inputs.package == 'dashboard')
173223 working-directory : packages/dashboard
174- run : npm publish --provenance --access public --ignore-scripts
224+ run : npm publish --provenance --access public --ignore-scripts --tag ${{ github.event.inputs.tag || 'latest' }}
175225 env :
176226 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
177227
178228 - name : Publish @agent-relay/dashboard-server
179229 if : github.event.inputs.dry_run != 'true' && (github.event.inputs.package == 'all' || github.event.inputs.package == 'dashboard-server')
180230 working-directory : packages/dashboard-server
181- run : npm publish --provenance --access public --ignore-scripts
231+ run : npm publish --provenance --access public --ignore-scripts --tag ${{ github.event.inputs.tag || 'latest' }}
182232 env :
183233 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
184234
@@ -319,17 +369,24 @@ jobs:
319369 git config user.email "actions@github.com"
320370
321371 NEW_VERSION="${{ needs.build.outputs.new_version }}"
372+ IS_PRERELEASE="${{ needs.build.outputs.is_prerelease }}"
322373
323374 git add package.json package-lock.json packages/*/package.json
324375 if ! git diff --staged --quiet; then
325- git commit -m "chore(release): v${NEW_VERSION}"
326- git push origin HEAD:main
376+ if [ "$IS_PRERELEASE" = "true" ]; then
377+ git commit -m "chore(prerelease): v${NEW_VERSION}"
378+ git push origin HEAD:staging --force
379+ else
380+ git commit -m "chore(release): v${NEW_VERSION}"
381+ git push origin HEAD:main
382+ fi
327383 fi
328384
329385 git tag -a "v${NEW_VERSION}" -m "Release v${NEW_VERSION}"
330386 git push origin "v${NEW_VERSION}"
331387
332- - name : Create GitHub Release
388+ - name : Create GitHub Release (stable)
389+ if : needs.build.outputs.is_prerelease != 'true'
333390 uses : softprops/action-gh-release@v2
334391 with :
335392 tag_name : v${{ needs.build.outputs.new_version }}
@@ -377,6 +434,36 @@ jobs:
377434 env :
378435 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
379436
437+ - name : Create GitHub Release (prerelease)
438+ if : needs.build.outputs.is_prerelease == 'true'
439+ uses : softprops/action-gh-release@v2
440+ with :
441+ tag_name : v${{ needs.build.outputs.new_version }}
442+ name : v${{ needs.build.outputs.new_version }} (prerelease)
443+ prerelease : true
444+ body : |
445+ ## @agent-relay/dashboard v${{ needs.build.outputs.new_version }} (prerelease)
446+
447+ > **This is a prerelease.** `npm install @agent-relay/dashboard-server` still returns the latest stable version.
448+
449+ ### Installation
450+
451+ ```bash
452+ npm install -g @agent-relay/dashboard-server@${{ needs.build.outputs.new_version }}
453+ # or via dist-tag:
454+ npm install -g @agent-relay/dashboard-server@${{ github.event.inputs.tag || 'beta' }}
455+ ```
456+
457+ ### Next Steps
458+
459+ 1. Deploy to staging: update relay-cloud staging with this version
460+ 2. Test on staging environment
461+ 3. If good, publish a stable release with `tag: latest`
462+ files : release-assets/*
463+ generate_release_notes : true
464+ env :
465+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
466+
380467 summary :
381468 name : Summary
382469 needs : [build, publish, build-standalone, create-release]
@@ -390,8 +477,18 @@ jobs:
390477 echo "" >> $GITHUB_STEP_SUMMARY
391478 echo "**Version**: \`${{ needs.build.outputs.new_version }}\`" >> $GITHUB_STEP_SUMMARY
392479 echo "**Package**: \`${{ github.event.inputs.package }}\`" >> $GITHUB_STEP_SUMMARY
480+ echo "**Dist-tag**: \`${{ github.event.inputs.tag || 'latest' }}\`" >> $GITHUB_STEP_SUMMARY
481+ echo "**Prerelease**: \`${{ needs.build.outputs.is_prerelease }}\`" >> $GITHUB_STEP_SUMMARY
393482 echo "**Dry Run**: \`${{ github.event.inputs.dry_run }}\`" >> $GITHUB_STEP_SUMMARY
394483 echo "" >> $GITHUB_STEP_SUMMARY
484+
485+ if [ "${{ needs.build.outputs.is_prerelease }}" = "true" ]; then
486+ echo "> **Prerelease** — published under \`${{ github.event.inputs.tag || 'beta' }}\` dist-tag. \`npm install\` still returns the latest stable version." >> $GITHUB_STEP_SUMMARY
487+ echo "" >> $GITHUB_STEP_SUMMARY
488+ echo "**Next:** Deploy to staging via relay-cloud Deploy Staging workflow." >> $GITHUB_STEP_SUMMARY
489+ echo "" >> $GITHUB_STEP_SUMMARY
490+ fi
491+
395492 echo "### Results" >> $GITHUB_STEP_SUMMARY
396493 echo "" >> $GITHUB_STEP_SUMMARY
397494 echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
0 commit comments