skills/github-actions/SKILL.md
CI/CD workflow patterns, testing pipelines, deployment automation. Use when setting up GitHub Actions workflows for testing, building, linting, or deploying a fullstack app.
npx skillsauth add sabahattinkalkan/antigravity-fullstack-hq github-actionsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # Cancel stale runs on new push
jobs:
# ─── Lint & Type Check ─────────────────────────────────────
lint:
name: Lint & Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Type check (API)
run: pnpm --filter api run type-check
- name: Type check (Web)
run: pnpm --filter web run type-check
- name: Lint
run: pnpm run lint
# ─── Unit Tests ────────────────────────────────────────────
test-unit:
name: Unit Tests
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Run unit tests
run: pnpm --filter api run test:cov
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./apps/api/coverage/lcov.info
# ─── Integration Tests ─────────────────────────────────────
test-integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: lint
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 5s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports: ["6379:6379"]
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 22, cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Run migrations
run: pnpm --filter api run migration:run
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
- name: Run integration tests
run: pnpm --filter api run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-secret-32-chars-minimum-length
# ─── E2E Tests ─────────────────────────────────────────────
test-e2e:
name: E2E Tests (Playwright)
runs-on: ubuntu-latest
needs: [test-unit, test-integration]
timeout-minutes: 20
services:
postgres:
image: postgres:16-alpine
env: { POSTGRES_DB: e2e_db, POSTGRES_USER: postgres, POSTGRES_PASSWORD: postgres }
ports: ["5432:5432"]
options: --health-cmd pg_isready --health-interval 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 22, cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Cache Playwright browsers
uses: actions/cache@v4
id: pw-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('**/package.json') }}
- name: Install Playwright browsers
if: steps.pw-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install --with-deps chromium
- name: Build apps
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/e2e_db
run: pnpm run build
- name: Run E2E tests
run: pnpm run test:e2e
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/e2e_db
PLAYWRIGHT_BASE_URL: http://localhost:3000
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 7
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
inputs:
environment:
description: Target environment
required: true
default: staging
type: choice
options: [staging, production]
jobs:
deploy-backend:
name: Deploy API to Railway
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'staging' }}
steps:
- uses: actions/checkout@v4
- name: Install Railway CLI
run: npm i -g @railway/cli
- name: Deploy to Railway
run: railway up --service api --detach
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
- name: Wait for deployment health
run: |
for i in {1..12}; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ vars.API_URL }}/health/liveness)
if [ "$STATUS" == "200" ]; then
echo "API is healthy"
exit 0
fi
echo "Attempt $i: status=$STATUS, waiting..."
sleep 10
done
echo "Health check failed after 2 minutes"
exit 1
deploy-frontend:
name: Deploy Web to Vercel
runs-on: ubuntu-latest
needs: deploy-backend
environment: ${{ github.event.inputs.environment || 'staging' }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 22, cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Deploy to Vercel
run: |
pnpm dlx vercel \
--token=${{ secrets.VERCEL_TOKEN }} \
--prod \
${{ github.event.inputs.environment == 'production' && '--prod' || '' }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
# .github/workflows/_setup-node.yml
name: Setup Node (Reusable)
on:
workflow_call:
inputs:
node-version:
type: string
default: '22'
jobs:
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
# Usage:
# jobs:
# setup:
# uses: ./.github/workflows/_setup-node.yml
# .github/workflows/pr-checks.yml
name: PR Checks
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
pr-title:
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: [feat, fix, refactor, docs, test, chore, perf, ci]
requireScope: false
check-diff:
name: Check Changed Files
runs-on: ubuntu-latest
outputs:
api-changed: ${{ steps.changes.outputs.api }}
web-changed: ${{ steps.changes.outputs.web }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
api:
- 'apps/api/**'
- 'packages/**'
web:
- 'apps/web/**'
- 'packages/**'
# Repository → Settings → Secrets and variables → Actions
RAILWAY_TOKEN — Railway API token for backend deploys
VERCEL_TOKEN — Vercel CLI token
VERCEL_ORG_ID — Vercel organization ID
VERCEL_PROJECT_ID — Vercel project ID
CODECOV_TOKEN — Codecov upload token
# Variables (non-secret)
API_URL — https://api.example.com (for health checks)
# Cache node_modules (pnpm store)
- uses: actions/cache@v4
with:
path: ~/.local/share/pnpm/store
key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: pnpm-${{ runner.os }}-
# Cache Next.js build
- uses: actions/cache@v4
with:
path: ${{ github.workspace }}/apps/web/.next/cache
key: nextjs-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('apps/web/**/*.ts', 'apps/web/**/*.tsx') }}
restore-keys: nextjs-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}-
continue-on-error: true to hide test failuresactions/checkout@v2 or older — use v4--frozen-lockfile — it ensures reproducible installspermissions: read-all as default)testing
Generating Excel files with xlsx/exceljs in Node.js. Use when generating .xlsx reports, data exports, dashboards, or spreadsheets from database data.
development
Playwright E2E patterns, Testing Library component tests, test selectors. Use when writing browser tests, component tests, or setting up an E2E testing pipeline for a Next.js or React app.
development
Web design best practices, accessibility, responsive layout, color contrast. Use when auditing a UI for a11y compliance, designing responsive layouts, or establishing design standards across a web app.
tools
TypeScript type system patterns, generics, utility types, and strict mode best practices. Use when writing or reviewing TypeScript code.