Skip to content

feat(payments): implement Stripe integration for real payments and we… #51

feat(payments): implement Stripe integration for real payments and we…

feat(payments): implement Stripe integration for real payments and we… #51

Workflow file for this run

name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: '20'
NODE_OPTIONS: '--max-old-space-size=4096'
jobs:
install:
name: Install Dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci --prefer-offline
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
lint:
name: ESLint
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npx eslint "{src,apps,libs,test}/**/*.ts" --max-warnings 0
format:
name: Prettier Format Check
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npx prettier --check "src/**/*.ts" "test/**/*.ts"
typecheck:
name: TypeScript Type Check
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npx tsc --project tsconfig.build.json --noEmit
build:
name: Build
runs-on: ubuntu-latest
needs: [lint, format, typecheck]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npm run build
- uses: actions/upload-artifact@v4
with: { name: dist, path: dist/, retention-days: 1 }
unit-tests:
name: Unit Tests & Coverage
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npm run test:ci
env:
NODE_ENV: test
JWT_SECRET: ci-test-secret
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/teachlink_test
- name: Publish coverage summary
if: always()
run: |
node -e "
const fs = require('fs');
const path = 'coverage/coverage-summary.json';
if (!fs.existsSync(path)) {
console.log('Coverage summary file not found.');
process.exit(0);
}
const s = JSON.parse(fs.readFileSync(path, 'utf8')).total;
const row = (name, metric) => '| ' + name + ' | ' + metric.pct.toFixed(2) + '% | ' + metric.covered + '/' + metric.total + ' |';
const summary = [
'## Coverage Summary',
'',
'| Metric | Percentage | Covered/Total |',
'|---|---:|---:|',
row('Lines', s.lines),
row('Statements', s.statements),
row('Functions', s.functions),
row('Branches', s.branches),
].join('\n');
fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, summary + '\n');
"
- uses: actions/upload-artifact@v4
if: always()
with: { name: coverage-report, path: coverage/, retention-days: 7 }
e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
needs: build
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: teachlink_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s --health-timeout 5s --health-retries 5
redis:
image: redis:7-alpine
ports: ['6379:6379']
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '${{ env.NODE_VERSION }}', cache: 'npm' }
- uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- uses: actions/download-artifact@v4
with: { name: dist, path: dist/ }
- run: npx jest --config test/jest-e2e.json --forceExit --runInBand
env:
NODE_ENV: test
DB_HOST: localhost
DB_PORT: 5432
DB_USERNAME: postgres
DB_PASSWORD: postgres
DB_NAME: teachlink_test
REDIS_HOST: localhost
REDIS_PORT: 6379
JWT_SECRET: ci-e2e-test-secret
ci-success:
name: CI Passed
runs-on: ubuntu-latest
needs: [install, lint, format, typecheck, build, unit-tests, e2e-tests]
if: always()
steps:
- name: Check all jobs passed
env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
node -e '
const needs = JSON.parse(process.env.NEEDS_JSON);
const failed = [];
for (const [name, info] of Object.entries(needs)) {
const result = info.result;
console.log(`${name}: ${result}`);
if (result !== "success") failed.push(`${name}=${result}`);
}
if (failed.length) {
console.error(`❌ CI failed: ${failed.join(", ")}`);
process.exit(1);
}
console.log("✅ All CI jobs passed.");
'