name: CI/CD
on:
push:
branches: [main, feature/*, develop]
pull_request:
branches: [main]
release:
types: [published]
env:
NODE_VERSION: '20.x'
jobs:
# =============================================================================
# LINT & TYPE CHECK
# =============================================================================
lint:
name: Lint & Type 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: Run TypeScript type check
run: npm run typecheck
- name: Run ESLint
run: npm run lint
continue-on-error: true # Allow warnings but fail on errors
# =============================================================================
# UNIT & SECURITY TESTS
# =============================================================================
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: ['18.x', '20.x', '22.x']
exclude:
# Reduce matrix for faster CI
- os: macos-latest
node: '18.x'
- os: macos-latest
node: '22.x'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run tests with coverage (ubuntu only)
if: matrix.os == 'ubuntu-latest' && matrix.node == '20.x'
run: npm run test:coverage
- name: Upload coverage report
if: matrix.os == 'ubuntu-latest' && matrix.node == '20.x'
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
fail_ci_if_error: false
# =============================================================================
# BUILD
# =============================================================================
build:
name: Build
runs-on: ubuntu-latest
needs: [lint, test]
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: Build
run: npm run build
- name: Verify dist output
run: |
ls -la dist/
test -f dist/cli.js
test -f dist/index.js
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7
# =============================================================================
# PACKAGE VERIFICATION
# =============================================================================
package:
name: Package Verification
runs-on: ubuntu-latest
needs: build
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: Build
run: npm run build
- name: Pack (dry-run)
run: npm pack --dry-run
- name: Create package
run: npm pack
- name: Verify package contents
run: |
PACKAGE=$(ls *.tgz)
tar -tzf $PACKAGE | head -50
# Ensure critical files are included
tar -tzf $PACKAGE | grep -q "package/dist/cli.js"
tar -tzf $PACKAGE | grep -q "package/dist/index.js"
tar -tzf $PACKAGE | grep -q "package/README.md"
tar -tzf $PACKAGE | grep -q "package/LICENSE"
tar -tzf $PACKAGE | grep -q "package/mcp.json"
- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: npm-package
path: "*.tgz"
retention-days: 7
# =============================================================================
# SECURITY SCAN
# =============================================================================
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 npm audit
run: npm audit --audit-level=high
continue-on-error: true
- name: Check for known vulnerabilities
run: npx better-npm-audit audit --level high
continue-on-error: true
# =============================================================================
# PUBLISH (Only on release)
# =============================================================================
publish:
name: Publish to npm
runs-on: ubuntu-latest
needs: [build, package, security]
if: github.event_name == 'release'
permissions:
contents: read
id-token: write
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'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}