Skip to content

Commit a65318f

Browse files
Merge pull request #28 from ServiceNow/scratch/release-automation
MAINT:Add automated release workflows and documentation
2 parents a204b70 + 4bcc790 commit a65318f

File tree

3 files changed

+676
-0
lines changed

3 files changed

+676
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
name: Create Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: 'Release version tag (e.g., v2.0.0)'
8+
required: true
9+
type: string
10+
release_notes:
11+
description: 'Release notes/description'
12+
required: true
13+
type: string
14+
set_as_latest:
15+
description: 'Set as the latest release'
16+
required: false
17+
type: boolean
18+
default: true
19+
is_prerelease:
20+
description: 'Set as a pre-release'
21+
required: false
22+
type: boolean
23+
default: false
24+
25+
jobs:
26+
create-release:
27+
name: Create and Publish Release
28+
runs-on: ubuntu-latest
29+
permissions:
30+
contents: write
31+
32+
steps:
33+
- name: Checkout repository
34+
uses: actions/checkout@v4
35+
with:
36+
ref: main
37+
fetch-depth: 0
38+
39+
- name: Validate tag format
40+
run: |
41+
TAG="${{ inputs.tag }}"
42+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
43+
echo "Error: Tag must be in format v*.*.* (e.g., v2.0.0)"
44+
exit 1
45+
fi
46+
echo "Tag format is valid: $TAG"
47+
48+
- name: Check if tag already exists
49+
run: |
50+
TAG="${{ inputs.tag }}"
51+
if git rev-parse "$TAG" >/dev/null 2>&1; then
52+
echo "Error: Tag $TAG already exists"
53+
exit 1
54+
fi
55+
echo "Tag $TAG is available"
56+
57+
- name: Verify branch is main
58+
run: |
59+
BRANCH=$(git rev-parse --abbrev-ref HEAD)
60+
if [ "$BRANCH" != "main" ]; then
61+
echo "Error: Current branch is $BRANCH, must be main"
62+
exit 1
63+
fi
64+
echo "Confirmed on main branch"
65+
66+
- name: Setup Node.js
67+
uses: actions/setup-node@v4
68+
with:
69+
node-version: '18'
70+
71+
- name: Clean and install dependencies
72+
run: |
73+
echo "Cleaning any existing installation..."
74+
rm -rf node_modules package-lock.json
75+
76+
echo "Installing dependencies with npm install..."
77+
npm install --prefer-offline --no-audit
78+
79+
echo "Verifying installation..."
80+
if [ -f "node_modules/.bin/ncc" ]; then
81+
echo "✅ ncc binary found"
82+
ls -la node_modules/.bin/ncc
83+
else
84+
echo "❌ ncc binary not found"
85+
echo "Contents of node_modules/.bin/:"
86+
ls -la node_modules/.bin/ || echo "node_modules/.bin/ directory does not exist"
87+
echo "Contents of @vercel/ncc:"
88+
ls -la node_modules/@vercel/ || echo "@vercel directory not found"
89+
exit 1
90+
fi
91+
92+
- name: Build distribution
93+
run: npm run build
94+
95+
- name: Verify build artifacts
96+
run: |
97+
if [ ! -f "dist/index.js" ]; then
98+
echo "Error: dist/index.js not found after build"
99+
exit 1
100+
fi
101+
echo "Build artifacts verified"
102+
103+
- name: Commit build artifacts (if changed)
104+
run: |
105+
git config user.name "github-actions[bot]"
106+
git config user.email "github-actions[bot]@users.noreply.github.com"
107+
108+
if [[ -n $(git status -s dist/) ]]; then
109+
git add dist/
110+
git commit -m "Build distribution for ${{ inputs.tag }}"
111+
git push origin main
112+
echo "Build artifacts committed and pushed"
113+
else
114+
echo "No changes to build artifacts"
115+
fi
116+
117+
- name: Create and push tag
118+
run: |
119+
TAG="${{ inputs.tag }}"
120+
git tag -a "$TAG" -m "Release $TAG"
121+
git push origin "$TAG"
122+
echo "Tag $TAG created and pushed"
123+
124+
- name: Create GitHub Release
125+
uses: actions/create-release@v1
126+
id: create_release
127+
env:
128+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
129+
with:
130+
tag_name: ${{ inputs.tag }}
131+
release_name: ${{ inputs.tag }}
132+
body: ${{ inputs.release_notes }}
133+
draft: false
134+
prerelease: ${{ inputs.is_prerelease }}
135+
make_latest: ${{ inputs.set_as_latest }}
136+
137+
- name: Release Summary
138+
run: |
139+
echo "## Release Created Successfully! 🎉" >> $GITHUB_STEP_SUMMARY
140+
echo "" >> $GITHUB_STEP_SUMMARY
141+
echo "**Version:** ${{ inputs.tag }}" >> $GITHUB_STEP_SUMMARY
142+
echo "**Release URL:** ${{ steps.create_release.outputs.html_url }}" >> $GITHUB_STEP_SUMMARY
143+
echo "**Pre-release:** ${{ inputs.is_prerelease }}" >> $GITHUB_STEP_SUMMARY
144+
echo "**Latest Release:** ${{ inputs.set_as_latest }}" >> $GITHUB_STEP_SUMMARY
145+
echo "" >> $GITHUB_STEP_SUMMARY
146+
echo "### Next Steps:" >> $GITHUB_STEP_SUMMARY
147+
echo "1. ✅ Verify the release at: ${{ steps.create_release.outputs.html_url }}" >> $GITHUB_STEP_SUMMARY
148+
echo "2. ✅ Check GitHub Marketplace for the new version" >> $GITHUB_STEP_SUMMARY
149+
echo "3. ✅ Inform QE team to test the GitHub Action" >> $GITHUB_STEP_SUMMARY
150+
151+
- name: Notify on failure
152+
if: failure()
153+
run: |
154+
echo "## Release Creation Failed ❌" >> $GITHUB_STEP_SUMMARY
155+
echo "" >> $GITHUB_STEP_SUMMARY
156+
echo "Please check the workflow logs for details." >> $GITHUB_STEP_SUMMARY
157+
echo "Common issues:" >> $GITHUB_STEP_SUMMARY
158+
echo "- Tag already exists" >> $GITHUB_STEP_SUMMARY
159+
echo "- Invalid tag format" >> $GITHUB_STEP_SUMMARY
160+
echo "- Build failures" >> $GITHUB_STEP_SUMMARY
161+
echo "- Permission issues" >> $GITHUB_STEP_SUMMARY
162+
ls -la /home/runner/.npm/_logs/
163+
164+
echo "Finding the latest log file..."
165+
LATEST_LOG=$(ls -t /home/runner/.npm/_logs | head -n 1)
166+
167+
if [ -z "$LATEST_LOG" ]; then
168+
echo "No log file found."
169+
else
170+
echo "Displaying latest npm debug log: $LATEST_LOG"
171+
cat /home/runner/.npm/_logs/$LATEST_LOG
172+
# Use Node.js to read and print the file to avoid shell issues
173+
node -e "console.log(require('fs').readFileSync('/home/runner/.npm/_logs/' + process.argv[1], 'utf-8'))" "$LATEST_LOG"
174+
fi

.github/workflows/test-release.yml

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: Test Release (Dry Run)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: 'Release version tag (e.g., v2.0.0-test)'
8+
required: true
9+
type: string
10+
release_notes:
11+
description: 'Release notes/description'
12+
required: true
13+
type: string
14+
set_as_latest:
15+
description: 'Set as the latest release'
16+
required: false
17+
type: boolean
18+
default: false
19+
is_prerelease:
20+
description: 'Set as a pre-release'
21+
required: false
22+
type: boolean
23+
default: true
24+
25+
jobs:
26+
test-release:
27+
name: Test Release Process (Dry Run)
28+
runs-on: ubuntu-latest
29+
permissions:
30+
contents: write
31+
32+
steps:
33+
- name: Checkout repository
34+
uses: actions/checkout@v4
35+
with:
36+
ref: main
37+
fetch-depth: 0
38+
39+
- name: Validate tag format
40+
run: |
41+
TAG="${{ inputs.tag }}"
42+
echo "Testing with tag: $TAG"
43+
44+
# For testing, allow -test, -rc, -beta suffixes
45+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
46+
echo "Error: Tag must be in format v*.*.* or v*.*.*-suffix (e.g., v2.0.0-test)"
47+
exit 1
48+
fi
49+
echo "✅ Tag format is valid: $TAG"
50+
51+
- name: Check if tag already exists
52+
run: |
53+
TAG="${{ inputs.tag }}"
54+
if git rev-parse "$TAG" >/dev/null 2>&1; then
55+
echo "⚠️ Warning: Tag $TAG already exists (will skip tag creation)"
56+
echo "TAG_EXISTS=true" >> $GITHUB_ENV
57+
else
58+
echo "✅ Tag $TAG is available"
59+
echo "TAG_EXISTS=false" >> $GITHUB_ENV
60+
fi
61+
62+
- name: Verify branch is main
63+
run: |
64+
BRANCH=$(git rev-parse --abbrev-ref HEAD)
65+
if [ "$BRANCH" != "main" ]; then
66+
echo "Error: Current branch is $BRANCH, must be main"
67+
exit 1
68+
fi
69+
echo "✅ Confirmed on main branch"
70+
71+
- name: Setup Node.js
72+
uses: actions/setup-node@v4
73+
with:
74+
node-version: '18'
75+
76+
- name: Clean and install dependencies
77+
run: |
78+
echo "Cleaning any existing installation..."
79+
rm -rf node_modules package-lock.json
80+
81+
echo "Installing dependencies with npm install..."
82+
npm install --prefer-offline --no-audit
83+
84+
echo "Verifying installation..."
85+
if [ -f "node_modules/.bin/ncc" ]; then
86+
echo "✅ ncc binary found"
87+
ls -la node_modules/.bin/ncc
88+
else
89+
echo "❌ ncc binary not found"
90+
echo "Contents of node_modules/.bin/:"
91+
ls -la node_modules/.bin/ || echo "node_modules/.bin/ directory does not exist"
92+
echo "Contents of @vercel/ncc:"
93+
ls -la node_modules/@vercel/ || echo "@vercel directory not found"
94+
exit 1
95+
fi
96+
echo "✅ Dependencies installed"
97+
98+
- name: Build distribution
99+
run: |
100+
echo "Building distribution..."
101+
npm run build
102+
echo "✅ Build completed"
103+
104+
- name: Verify build artifacts
105+
run: |
106+
if [ ! -f "dist/index.js" ]; then
107+
echo "❌ Error: dist/index.js not found after build"
108+
exit 1
109+
fi
110+
111+
echo "✅ Build artifacts verified"
112+
echo "dist/index.js size: $(wc -c < dist/index.js) bytes"
113+
114+
- name: Check for uncommitted changes
115+
run: |
116+
if [[ -n $(git status -s dist/) ]]; then
117+
echo "⚠️ Warning: There are uncommitted changes in dist/"
118+
git status -s dist/
119+
echo ""
120+
echo "In production, these would be committed and pushed"
121+
else
122+
echo "✅ No changes to build artifacts"
123+
fi
124+
125+
- name: Simulate tag creation (DRY RUN)
126+
run: |
127+
TAG="${{ inputs.tag }}"
128+
if [ "$TAG_EXISTS" = "false" ]; then
129+
echo "🔍 DRY RUN: Would create tag: $TAG"
130+
echo "Command: git tag -a '$TAG' -m 'Release $TAG'"
131+
echo "Command: git push origin '$TAG'"
132+
else
133+
echo "⏭️ Skipping tag creation (already exists)"
134+
fi
135+
136+
- name: Create Draft Release (TEST)
137+
uses: actions/create-release@v1
138+
id: create_release
139+
env:
140+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
with:
142+
tag_name: ${{ inputs.tag }}
143+
release_name: ${{ inputs.tag }} (TEST)
144+
body: |
145+
🧪 **THIS IS A TEST RELEASE**
146+
147+
${{ inputs.release_notes }}
148+
149+
---
150+
*This is a test release created for validation purposes.*
151+
draft: true
152+
prerelease: ${{ inputs.is_prerelease }}
153+
154+
- name: Test Summary
155+
run: |
156+
echo "## 🧪 Test Release Summary" >> $GITHUB_STEP_SUMMARY
157+
echo "" >> $GITHUB_STEP_SUMMARY
158+
echo "**Version:** ${{ inputs.tag }}" >> $GITHUB_STEP_SUMMARY
159+
echo "**Draft Release URL:** ${{ steps.create_release.outputs.html_url }}" >> $GITHUB_STEP_SUMMARY
160+
echo "**Pre-release:** ${{ inputs.is_prerelease }}" >> $GITHUB_STEP_SUMMARY
161+
echo "**Latest Release:** ${{ inputs.set_as_latest }}" >> $GITHUB_STEP_SUMMARY
162+
echo "" >> $GITHUB_STEP_SUMMARY
163+
echo "### ✅ Test Results:" >> $GITHUB_STEP_SUMMARY
164+
echo "- Tag format validation: PASSED" >> $GITHUB_STEP_SUMMARY
165+
echo "- Branch verification: PASSED" >> $GITHUB_STEP_SUMMARY
166+
echo "- Dependencies installation: PASSED" >> $GITHUB_STEP_SUMMARY
167+
echo "- Build process: PASSED" >> $GITHUB_STEP_SUMMARY
168+
echo "- Build artifacts: VERIFIED" >> $GITHUB_STEP_SUMMARY
169+
echo "- Draft release: CREATED" >> $GITHUB_STEP_SUMMARY
170+
echo "" >> $GITHUB_STEP_SUMMARY
171+
echo "### 📝 Next Steps:" >> $GITHUB_STEP_SUMMARY
172+
echo "1. Review the draft release at: ${{ steps.create_release.outputs.html_url }}" >> $GITHUB_STEP_SUMMARY
173+
echo "2. If everything looks good, delete this draft release" >> $GITHUB_STEP_SUMMARY
174+
echo "3. Run the actual 'Create Release' workflow for production" >> $GITHUB_STEP_SUMMARY
175+
echo "" >> $GITHUB_STEP_SUMMARY
176+
echo "### ⚠️ Remember:" >> $GITHUB_STEP_SUMMARY
177+
echo "- This created a DRAFT release that won't be published" >> $GITHUB_STEP_SUMMARY
178+
echo "- Delete the draft release after testing" >> $GITHUB_STEP_SUMMARY
179+
echo "- Use a test tag like v2.0.0-test to avoid conflicts" >> $GITHUB_STEP_SUMMARY
180+
181+
- name: Notify on failure
182+
if: failure()
183+
run: |
184+
echo "## ❌ Test Failed" >> $GITHUB_STEP_SUMMARY
185+
echo "" >> $GITHUB_STEP_SUMMARY
186+
echo "Please check the workflow logs for details." >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)