ice/.forgejo/workflows/ci.yml
Claude Code b913475932 Add comprehensive CI/CD workflows for Forgejo Actions
- ci.yml: Complete CI pipeline with lint, type-check, tests, build, security, and i18n validation
- code-quality.yml: Advanced code analysis including complexity, TODO tracking, and import analysis
- dependency-review.yml: Automated dependency update review with security checks
- pr-labeler.yml: Intelligent PR labeling based on files and content
- release.yml: Automated release process with changelog generation
- Documentation and best practices guide

Features:
- Multi-node testing (Node 18, 20)
- Security scanning for hardcoded secrets
- Bundle size impact analysis
- Translation key validation
- Complexity analysis and code quality metrics

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-07 19:50:57 -04:00

214 lines
No EOL
5.8 KiB
YAML

name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
name: Lint Code
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
type-check:
runs-on: ubuntu-latest
name: TypeScript Type Check
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run TypeScript compiler
run: npx tsc --noEmit
test:
runs-on: ubuntu-latest
name: Run Tests
strategy:
matrix:
node-version: [18, 20]
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 tests with coverage
run: npm run test:coverage
- name: Upload coverage reports
if: matrix.node-version == '20'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
build:
runs-on: ubuntu-latest
name: Build Project
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build TypeScript
run: npm run build:ts
- name: Build Frontend
run: npm run build:frontend
- name: Build CSS
run: npm run build-css
- name: Verify build outputs
run: |
echo "Checking backend build..."
test -f dist/server.js || exit 1
echo "Checking frontend build..."
test -f public/dist/app-main.js || exit 1
test -f public/dist/app-admin.js || exit 1
test -f public/dist/app-privacy.js || exit 1
echo "Checking CSS build..."
test -f public/style.css || exit 1
echo "✅ All build outputs verified!"
security:
runs-on: ubuntu-latest
name: Security Checks
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
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 secrets
run: |
echo "Checking for potential secrets..."
! grep -r "MAPBOX_ACCESS_TOKEN" --include="*.js" --include="*.ts" --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git . || \
(echo "❌ Found hardcoded Mapbox token!" && exit 1)
! grep -r "ADMIN_PASSWORD" --include="*.js" --include="*.ts" --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git . || \
(echo "❌ Found hardcoded admin password!" && exit 1)
echo "✅ No hardcoded secrets found"
validate-i18n:
runs-on: ubuntu-latest
name: Validate i18n Files
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Validate JSON files
run: |
echo "Validating i18n JSON files..."
for file in src/i18n/locales/*.json; do
echo "Checking $file..."
node -e "JSON.parse(require('fs').readFileSync('$file', 'utf8'))" || exit 1
done
echo "✅ All i18n files are valid JSON"
- name: Check translation keys match
run: |
echo "Comparing translation keys..."
node -e "
const fs = require('fs');
const en = JSON.parse(fs.readFileSync('src/i18n/locales/en.json', 'utf8'));
const esMX = JSON.parse(fs.readFileSync('src/i18n/locales/es-MX.json', 'utf8'));
function getKeys(obj, prefix = '') {
let keys = [];
for (const key in obj) {
const fullKey = prefix ? prefix + '.' + key : key;
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
keys = keys.concat(getKeys(obj[key], fullKey));
} else {
keys.push(fullKey);
}
}
return keys.sort();
}
const enKeys = getKeys(en);
const esMXKeys = getKeys(esMX);
const missingInEs = enKeys.filter(k => !esMXKeys.includes(k));
const missingInEn = esMXKeys.filter(k => !enKeys.includes(k));
if (missingInEs.length > 0) {
console.error('❌ Keys in en.json missing from es-MX.json:', missingInEs);
process.exit(1);
}
if (missingInEn.length > 0) {
console.error('❌ Keys in es-MX.json missing from en.json:', missingInEn);
process.exit(1);
}
console.log('✅ All translation keys match between locales');
"