Skip to content

CI

CI #35

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Run unit tests
run: npx jest@30 --config '{}' tests/scripts/ --ci
- name: Validate plugin manifest
run: |
node -e "
const fs = require('fs');
const plugin = JSON.parse(fs.readFileSync('.claude-plugin/plugin.json', 'utf8'));
if (!plugin.name || !plugin.version || !plugin.description) {
console.error('Invalid plugin.json: missing required fields');
process.exit(1);
}
console.log('plugin.json is valid:', plugin.name, 'v' + plugin.version);
"
- name: Check for secrets in repo
run: node skills/setup/scripts/lib/check-secrets.js --all || true
- name: Verify no files exceed 300 lines
run: |
node -e "
const fs = require('fs');
const path = require('path');
const dirs = ['skills', 'scripts', 'tests/scripts', 'tests/evals'];
let violations = 0;
function walk(dir) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== 'fixtures') {
walk(full);
} else if (entry.isFile() && /\.(js|ts|md)$/.test(entry.name)) {
const lines = fs.readFileSync(full, 'utf8').split('\n').length;
if (lines > 300 && !full.includes('SKILL.md') && !full.includes('README.md') && !full.includes('global-claude.md')) {
console.error(full + ': ' + lines + ' lines (max 300)');
violations++;
}
}
}
}
dirs.forEach(d => { if (fs.existsSync(d)) walk(d); });
if (violations > 0) process.exit(1);
console.log('All files within line limits');
"