Skip to content

1.8.0

1.8.0 #11

Workflow file for this run

name: Build and Release
on:
push:
tags:
- "v*" # Triggers on tags like v1.0.0, v1.2.3, etc.
workflow_dispatch: # Allows manual triggering for testing workflow only
inputs:
dry_run:
description: "Run validation without creating release"
required: false
default: "true"
type: boolean
jobs:
# Validation job - runs on both tag push and manual trigger
validate:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
version: ${{ steps.get_version.outputs.version }}
is_tag: ${{ steps.check_trigger.outputs.is_tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check trigger type
id: check_trigger
run: |
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
echo "is_tag=true" >> $GITHUB_OUTPUT
echo "Triggered by tag push"
else
echo "is_tag=false" >> $GITHUB_OUTPUT
echo "Triggered manually - validation only"
fi
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Verify build artifacts exist
run: |
echo "Checking for required build artifacts..."
if [ ! -d "dist" ]; then
echo "❌ Error: dist directory not found"
exit 1
fi
if [ ! -f "dist/index.js" ]; then
echo "❌ Error: dist/index.js not found"
exit 1
fi
if [ ! -d "dist/types" ]; then
echo "❌ Error: dist/types directory not found"
exit 1
fi
if [ ! -f "dist/types/index.d.ts" ]; then
echo "❌ Error: dist/types/index.d.ts not found"
exit 1
fi
echo "✅ All build artifacts verified successfully"
- name: Extract version from tag
id: get_version
run: |
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version from tag: $VERSION"
else
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version from package.json: $VERSION"
fi
- name: Verify package.json version matches tag
if: startsWith(github.ref, 'refs/tags/')
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
TAG_VERSION="${{ steps.get_version.outputs.version }}"
echo "Package version: $PACKAGE_VERSION"
echo "Tag version: $TAG_VERSION"
if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
echo "❌ Error: package.json version ($PACKAGE_VERSION) doesn't match tag version ($TAG_VERSION)"
echo "Please update package.json version to match the tag or create a new tag matching package.json"
exit 1
fi
echo "✅ Version verification passed"
- name: Verify package.json configuration
run: |
echo "Verifying package.json configuration..."
MAIN=$(node -p "require('./package.json').main")
if [ "$MAIN" != "dist/index.js" ]; then
echo "⚠️ Warning: main entry point is '$MAIN', expected 'dist/index.js'"
fi
TYPES=$(node -p "require('./package.json').types")
if [ "$TYPES" != "dist/types/index.d.ts" ]; then
echo "⚠️ Warning: types entry point is '$TYPES', expected 'dist/types/index.d.ts'"
fi
FILES=$(node -p "JSON.stringify(require('./package.json').files || [])")
echo "Package includes files: $FILES"
echo "✅ Package configuration verified"
# Release job - only runs on tag push (not on manual trigger)
release:
needs: validate
if: needs.validate.outputs.is_tag == 'true' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Verify build artifacts
run: |
echo "Verifying build artifacts..."
if [ ! -d "dist" ] || [ ! -f "dist/index.js" ] || [ ! -f "dist/types/index.d.ts" ]; then
echo "❌ Build artifacts missing"
exit 1
fi
echo "✅ Build artifacts verified"
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Add built artifacts to tag
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
echo "Adding built artifacts to tag: $TAG_NAME"
# Add built artifacts (force add despite .gitignore)
git add -f dist/
# Commit the built artifacts
git commit -m "chore: add built artifacts for $TAG_NAME" \
-m "Auto-generated by GitHub Actions workflow." \
-m "Built from commit: ${{ github.sha }}"
# Delete the old tag locally
git tag -d $TAG_NAME
# Create new tag with built artifacts
git tag $TAG_NAME
# TECH DEBT: Force push is required here because:
# 1. The tag is created by `npm run release:*` before the workflow runs
# 2. We need to update that tag to include built artifacts (dist/)
# 3. Git doesn't allow updating tags without force push (immutability by design)
# 4. This is safe because it happens immediately in CI before anyone fetches the tag
# 5. Alternative would be npm registry, but we're doing GitHub-only distribution
# Trade-off: Pragmatic solution for GitHub package distribution vs strict git best practices
git push origin $TAG_NAME --force
echo "✅ Tag $TAG_NAME updated with built artifacts"
- name: Update release branch with built artifacts
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
echo "Updating release branch to point to: $TAG_NAME"
# Fetch all branches and tags
git fetch origin
# Delete local release branch if it exists
git branch -D release 2>/dev/null || true
# Create new release branch from current commit (which has dist/)
echo "Creating release branch..."
git checkout -b release
# Delete remote release branch if it exists
echo "Deleting old release branch on remote (if exists)..."
git push origin --delete release 2>/dev/null || echo "No existing release branch to delete"
# Push the new release branch
echo "Pushing release branch..."
git push origin release
echo "✅ Release branch updated successfully"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: Release v${{ needs.validate.outputs.version }}
tag_name: ${{ github.ref_name }}
body: |
## 🚀 Release v${{ needs.validate.outputs.version }}
### 📦 Installation
#### Option 1: Use release branch (auto-updates to latest release)
Add to your `package.json`:
```json
{
"dependencies": {
"github-release-consumer": "github:${{ github.repository }}#release"
}
}
```
#### Option 2: Pin to specific version (recommended for production)
Add to your `package.json`:
```json
{
"dependencies": {
"github-release-consumer": "github:${{ github.repository }}#v${{ needs.validate.outputs.version }}"
}
}
```
Then run:
```bash
npm install
# or
pnpm install
# or
yarn install
```
### 🔧 How it works
- Pre-built artifacts are included in the tag and release branch
- **No build required** during installation - fast and efficient!
- Works perfectly in CI/CD environments (no `npm ci` slowdown)
- TypeScript types and source maps are pre-generated
### 📋 What's included
- ✅ Build validated and verified
- ✅ Pre-built JavaScript bundles
- ✅ TypeScript type definitions
- ✅ Source maps for debugging
- ✅ Zero build overhead for consumers
### ⚡ Performance
Installing from GitHub with pre-built artifacts is:
- 🚀 **Faster** - No compilation needed
- 💾 **Lighter** - No devDependencies required
- 🔒 **Safer** - No build scripts executed during install
---
*Generated automatically by GitHub Actions*
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}