name: Release
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., 1.0.0)'
required: true
prerelease:
description: 'Is this a pre-release?'
required: false
default: false
type: boolean
permissions:
contents: write
packages: write
id-token: write
jobs:
# Job 1: Validate and Prepare Release
prepare-release:
name: Prepare Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
changelog: ${{ steps.changelog.outputs.changelog }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="v${{ github.event.inputs.version }}"
else
VERSION="${{ github.ref_name }}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_ENV
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build project
run: npm run build
- name: Generate changelog
id: changelog
run: |
# Get the previous tag
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
# Generate changelog
if [ -z "$PREV_TAG" ]; then
CHANGELOG=$(git log --pretty=format:"- %s" --reverse)
else
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s")
fi
# Save to file for multi-line output
echo "$CHANGELOG" > changelog.md
echo "changelog<<EOF" >> $GITHUB_OUTPUT
cat changelog.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Update version in package.json
run: |
VERSION="${{ steps.version.outputs.version }}"
VERSION="${VERSION#v}" # Remove 'v' prefix
npm version $VERSION --no-git-tag-version
- name: Update CHANGELOG.md
run: |
VERSION="${{ steps.version.outputs.version }}"
DATE=$(date +"%Y-%m-%d")
# Create new changelog entry
cat > new_changelog.md << EOF
# Changelog
## [$VERSION] - $DATE
### Added
EOF
# Add commit messages
cat changelog.md >> new_changelog.md
# Append existing changelog
if [ -f CHANGELOG.md ]; then
echo "" >> new_changelog.md
tail -n +2 CHANGELOG.md >> new_changelog.md
fi
mv new_changelog.md CHANGELOG.md
- name: Commit version bump
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add package.json package-lock.json CHANGELOG.md
git commit -m "chore: bump version to ${{ steps.version.outputs.version }}" || true
git push origin HEAD:main || true
# Job 2: Create GitHub Release
github-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [prepare-release]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Install dependencies
run: npm ci
- name: Build distributables
run: |
npm run build
# Create dist archive
tar -czf hurricane-tracker-mcp-dist.tar.gz dist/
zip -r hurricane-tracker-mcp-dist.zip dist/
- name: Create Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ needs.prepare-release.outputs.version }}
name: Release ${{ needs.prepare-release.outputs.version }}
body: |
## π Hurricane Tracker MCP ${{ needs.prepare-release.outputs.version }}
### π Changes
${{ needs.prepare-release.outputs.changelog }}
### π³ Docker
```bash
docker pull ghcr.io/kumaran-is/hurricane-tracker-mcp:${{ needs.prepare-release.outputs.version }}
```
### π Documentation
- [Setup Guide](https://github.com/kumaran-is/hurricane-tracker-mcp/blob/main/README.md)
- [API Documentation](https://github.com/kumaran-is/hurricane-tracker-mcp/wiki)
draft: false
prerelease: ${{ github.event.inputs.prerelease == 'true' }}
files: |
hurricane-tracker-mcp-dist.tar.gz
hurricane-tracker-mcp-dist.zip
- name: Update latest tag
if: ${{ github.event.inputs.prerelease != 'true' }}
run: |
git tag -fa latest -m "Latest release ${{ needs.prepare-release.outputs.version }}"
git push origin latest --force
# Job 3: Build and Push Docker Images
docker-release:
name: Docker Build & Push
runs-on: ubuntu-latest
needs: [prepare-release]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}},value=${{ needs.prepare-release.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.prepare-release.outputs.version }}
type=semver,pattern={{major}},value=${{ needs.prepare-release.outputs.version }}
type=raw,value=latest,enable=${{ github.event.inputs.prerelease != 'true' }}
- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ needs.prepare-release.outputs.version }}
# Job 4: Update Documentation
update-docs:
name: Update Documentation
runs-on: ubuntu-latest
needs: [prepare-release, github-release]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: main
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Generate API documentation
run: |
npm ci
npx typedoc --out docs/api src/
- name: Update README badges
run: |
VERSION="${{ needs.prepare-release.outputs.version }}"
VERSION="${VERSION#v}" # Remove 'v' prefix
# Update Docker version badge in README (GitHub Container Registry)
echo "Version $VERSION updated in package.json"
- name: Commit documentation updates
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add docs/ README.md
git commit -m "docs: update documentation for ${{ needs.prepare-release.outputs.version }}" || true
git push origin main || true
# Job 5: Post-Release Notifications
notify:
name: Release Notifications
runs-on: ubuntu-latest
needs: [prepare-release, docker-release, github-release]
if: always()
steps:
- name: Create summary
run: |
echo "# π Release ${{ needs.prepare-release.outputs.version }} Complete!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## π Release Status" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Component | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| GitHub Release | ${{ needs.github-release.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Docker Images | ${{ needs.docker-release.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## π¦ Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Docker: \`ghcr.io/kumaran-is/hurricane-tracker-mcp:${{ needs.prepare-release.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
echo "- GitHub: [Release Page](https://github.com/${{ github.repository }}/releases/tag/${{ needs.prepare-release.outputs.version }})" >> $GITHUB_STEP_SUMMARY