Skip to content

Extensions - Release #32

Extensions - Release

Extensions - Release #32

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*' # Triggers on version tags like v1.0.0, v1.2.3, etc.
workflow_dispatch: # Allows manual trigger from GitHub UI
inputs:
create_tag:
description: 'Create tag from package.json version'
required: false
default: 'true'
type: boolean
permissions:
contents: read
jobs:
release:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
with:
egress-policy: audit
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20.x'
cache: 'npm'
- name: Determine trigger type
id: trigger_type
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "is_manual=true" >> $GITHUB_OUTPUT
echo "Triggered manually via workflow_dispatch"
else
echo "is_manual=false" >> $GITHUB_OUTPUT
echo "Triggered by tag push"
fi
- name: Extract version from package.json
id: package_version
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
echo "package_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
echo "Package version: $PACKAGE_VERSION"
- name: Create tag for manual trigger
if: steps.trigger_type.outputs.is_manual == 'true' && inputs.create_tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="v${{ steps.package_version.outputs.package_version }}"
echo "Creating tag: $VERSION"
# Check if tag already exists on remote using exit code
if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then
echo "❌ Tag $VERSION already exists on remote!"
echo "Please update the version in package.json or delete the existing tag."
exit 1
fi
# Create and push the tag
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"
# Verify tag was created successfully on remote
echo "Verifying tag was created on remote..."
for i in {1..5}; do
if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then
echo "✅ Tag $VERSION created and verified on remote"
exit 0
fi
echo "Waiting for tag to propagate (attempt $i/5)..."
sleep 2
done
echo "❌ Failed to verify tag creation on remote"
exit 1
- name: Extract version from tag
id: extract_version
run: |
if [ "${{ steps.trigger_type.outputs.is_manual }}" == "true" ]; then
# For manual triggers, use package.json version
TAG_VERSION="${{ steps.package_version.outputs.package_version }}"
else
# For tag triggers, extract from the tag
TAG_VERSION=${GITHUB_REF#refs/tags/v}
fi
echo "tag_version=$TAG_VERSION" >> $GITHUB_OUTPUT
echo "Release version: $TAG_VERSION"
- name: Verify version consistency
run: |
if [ "${{ steps.extract_version.outputs.tag_version }}" != "${{ steps.package_version.outputs.package_version }}" ]; then
echo "❌ Version mismatch!"
echo "Tag version: ${{ steps.extract_version.outputs.tag_version }}"
echo "Package.json version: ${{ steps.package_version.outputs.package_version }}"
echo "Please ensure the tag version matches the version in package.json"
exit 1
fi
echo "✅ Version check passed: ${{ steps.extract_version.outputs.tag_version }}"
- name: Determine tag name
id: tag_name
run: |
if [ "${{ steps.trigger_type.outputs.is_manual }}" == "true" ]; then
TAG_NAME="v${{ steps.extract_version.outputs.tag_version }}"
else
TAG_NAME="${{ github.ref_name }}"
fi
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
echo "Tag name: $TAG_NAME"
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run type checking
run: npm run check-types
- name: Compile extension
run: npm run compile
- name: Build production package
run: npm run package
- name: Compile tests
run: npm run compile-tests
- name: Run tests
uses: coactions/setup-xvfb@b6b4fcfb9f5a895edadc3bc76318fae0ac17c8b3 # v1.0.1
with:
run: npm test
options: -screen 0 1024x768x24
continue-on-error: false # Fail the release if tests fail
- name: Create VSIX package
run: npx vsce package
- name: Get VSIX filename
id: vsix_filename
run: |
VSIX_FILE=$(ls *.vsix | head -n 1)
echo "vsix_file=$VSIX_FILE" >> $GITHUB_OUTPUT
echo "VSIX file: $VSIX_FILE"
- name: Generate release notes
run: |
# Extract the latest changes from CHANGELOG.md if it has been updated
# Write to a file to avoid shell interpretation issues with special characters
if grep -q "## \[.*\]" CHANGELOG.md; then
# Try to extract the latest version section from changelog
NOTES=$(sed -n '/## \[.*\]/,/## \[.*\]/p' CHANGELOG.md | head -n -1 | tail -n +2)
if [ -n "$NOTES" ]; then
echo "$NOTES" > /tmp/release_notes.md
else
echo "Release ${{ steps.extract_version.outputs.tag_version }}" > /tmp/release_notes.md
fi
else
echo "Release ${{ steps.extract_version.outputs.tag_version }}" > /tmp/release_notes.md
fi
- name: Create Release
id: create_release
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true
run: |
set -o pipefail
echo "Creating release for tag: ${{ steps.tag_name.outputs.tag_name }}"
# Create release with notes from file and upload VSIX file
gh release create "${{ steps.tag_name.outputs.tag_name }}" \
--title "Release ${{ steps.extract_version.outputs.tag_version }}" \
--notes-file /tmp/release_notes.md \
./${{ steps.vsix_filename.outputs.vsix_file }} 2>&1 | tee /tmp/release_output.txt
- name: Release Summary
if: always()
run: |
if [ "${{ steps.create_release.outcome }}" == "success" ]; then
echo "# ✅ Release Created Successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "🎉 Release ${{ steps.extract_version.outputs.tag_version }} created successfully!" >> $GITHUB_STEP_SUMMARY
echo "📦 VSIX package: ${{ steps.vsix_filename.outputs.vsix_file }}" >> $GITHUB_STEP_SUMMARY
echo "🔗 [Release URL](https://github.com/${{ github.repository }}/releases/tag/${{ steps.tag_name.outputs.tag_name }})" >> $GITHUB_STEP_SUMMARY
else
echo "# ❌ Release Creation Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ steps.extract_version.outputs.tag_version }}" >> $GITHUB_STEP_SUMMARY
echo "**Tag:** ${{ steps.tag_name.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Error Details" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
if [ -f /tmp/release_output.txt ]; then
cat /tmp/release_output.txt >> $GITHUB_STEP_SUMMARY
else
echo "No error details captured" >> $GITHUB_STEP_SUMMARY
fi
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi