name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
types: [opened, synchronize, reopened]
release:
types: [ published ]
env:
NODE_VERSION: '20.x'
jobs:
test:
name: Test on ${{ matrix.os }} with Node ${{ matrix.node-version }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18.x, 20.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run type checking
run: npm run compile
- name: Run tests
run: npm run test:coverage
- name: Validate Sprint 4 Auto-Deployment
run: npm run validate:sprint4
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x'
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
fail_ci_if_error: false
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=moderate
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: typescript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
quality:
name: Code Quality Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check code formatting
run: npm run format:check
- name: Run production build
run: npm run compile:prod
- name: Verify clean git status
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "Working directory is not clean after build"
git status
exit 1
fi
package:
name: Package Extension
runs-on: ubuntu-latest
needs: [test, security, quality]
if: github.event_name == 'release' || github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install VSCE
run: npm install -g @vscode/vsce
- name: Package extension
run: vsce package
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: extension-vsix-${{ github.sha }}
path: '*.vsix'
retention-days: 30
publish-pre-release:
name: Publish Pre-release
runs-on: ubuntu-latest
needs: [package]
if: github.ref == 'refs/heads/develop'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install VSCE
run: npm install -g @vscode/vsce
- name: Publish pre-release
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
run: vsce publish --pre-release --pat $VSCE_PAT
publish-release:
name: Publish to Marketplace
runs-on: ubuntu-latest
needs: [package]
if: github.event_name == 'release'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install VSCE
run: npm install -g @vscode/vsce
- name: Download VSIX artifact
uses: actions/download-artifact@v4
with:
name: extension-vsix-${{ github.sha }}
- name: Publish to VS Code Marketplace
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
run: vsce publish --pat $VSCE_PAT
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: '*.vsix'
generate_release_notes: true
tag_name: ${{ github.event.release.tag_name }}
name: ${{ github.event.release.name }}
body: ${{ github.event.release.body }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
performance-test:
name: Performance Testing
runs-on: ubuntu-latest
needs: [test]
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run performance tests
run: |
# Create large test workspace
mkdir -p test-workspace
for i in {1..100}; do
echo "console.log('file $i');" > test-workspace/file$i.js
done
# Run extension performance test
npm run test -- --testNamePattern="performance"
- name: Check bundle size
run: |
npm run package
VSIX_SIZE=$(stat -c%s *.vsix)
echo "Extension size: $VSIX_SIZE bytes"
if [ $VSIX_SIZE -gt 1048576 ]; then # 1MB limit
echo "Extension size exceeds 1MB limit"
exit 1
fi