|
| 1 | +name: CI — Validate Skills & Script |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: [main, develop] |
| 6 | + pull_request: |
| 7 | + branches: [main] |
| 8 | + |
| 9 | +jobs: |
| 10 | + # ─── 1. Validate setup.sh syntax ─────────────────────────── |
| 11 | + validate-script: |
| 12 | + name: Validate setup.sh |
| 13 | + runs-on: ubuntu-latest |
| 14 | + steps: |
| 15 | + - uses: actions/checkout@v4 |
| 16 | + |
| 17 | + - name: Check bash syntax |
| 18 | + run: bash -n setup.sh && echo "✅ setup.sh syntax OK" |
| 19 | + |
| 20 | + - name: Check script is executable |
| 21 | + run: | |
| 22 | + if [ -x setup.sh ]; then |
| 23 | + echo "✅ setup.sh is executable" |
| 24 | + else |
| 25 | + echo "⚠️ setup.sh not executable — run: chmod +x setup.sh" |
| 26 | + exit 1 |
| 27 | + fi |
| 28 | +
|
| 29 | + - name: Lint with shellcheck |
| 30 | + uses: ludeeus/action-shellcheck@master |
| 31 | + with: |
| 32 | + scandir: '.' |
| 33 | + severity: warning |
| 34 | + continue-on-error: true |
| 35 | + |
| 36 | + # ─── 2. Validate all SKILL.md files ──────────────────────── |
| 37 | + validate-skills: |
| 38 | + name: Validate Skills |
| 39 | + runs-on: ubuntu-latest |
| 40 | + steps: |
| 41 | + - uses: actions/checkout@v4 |
| 42 | + |
| 43 | + - name: Check every skill has a SKILL.md |
| 44 | + run: | |
| 45 | + ERRORS=0 |
| 46 | + for dir in skills/*/; do |
| 47 | + skill=$(basename "$dir") |
| 48 | + if [ ! -f "${dir}SKILL.md" ]; then |
| 49 | + echo "❌ Missing SKILL.md in: $skill" |
| 50 | + ERRORS=$((ERRORS + 1)) |
| 51 | + else |
| 52 | + echo "✅ $skill" |
| 53 | + fi |
| 54 | + done |
| 55 | + if [ $ERRORS -gt 0 ]; then |
| 56 | + echo "$ERRORS skill(s) missing SKILL.md" |
| 57 | + exit 1 |
| 58 | + fi |
| 59 | + echo "All $(ls skills/ | wc -l | tr -d ' ') skills valid" |
| 60 | +
|
| 61 | + - name: Check SKILL.md frontmatter has name and description |
| 62 | + run: | |
| 63 | + ERRORS=0 |
| 64 | + for skill_file in skills/*/SKILL.md; do |
| 65 | + skill=$(basename $(dirname "$skill_file")) |
| 66 | + if ! grep -q "^name:" "$skill_file"; then |
| 67 | + echo "❌ $skill: missing 'name:' in frontmatter" |
| 68 | + ERRORS=$((ERRORS + 1)) |
| 69 | + fi |
| 70 | + if ! grep -q "^description:" "$skill_file"; then |
| 71 | + echo "❌ $skill: missing 'description:' in frontmatter" |
| 72 | + ERRORS=$((ERRORS + 1)) |
| 73 | + fi |
| 74 | + done |
| 75 | + if [ $ERRORS -gt 0 ]; then |
| 76 | + echo "$ERRORS frontmatter error(s) found" |
| 77 | + exit 1 |
| 78 | + fi |
| 79 | + echo "✅ All skill frontmatters valid" |
| 80 | +
|
| 81 | + - name: Count and report skills |
| 82 | + run: | |
| 83 | + COUNT=$(ls skills/ | wc -l | tr -d ' ') |
| 84 | + echo "📦 Total skills: $COUNT" |
| 85 | + ls skills/ | sed 's/^/ - /' |
| 86 | +
|
| 87 | + # ─── 3. Validate VS Code config JSON ─────────────────────── |
| 88 | + validate-vscode: |
| 89 | + name: Validate VS Code JSON |
| 90 | + runs-on: ubuntu-latest |
| 91 | + steps: |
| 92 | + - uses: actions/checkout@v4 |
| 93 | + |
| 94 | + - name: Validate settings.json |
| 95 | + run: python3 -c "import json; json.load(open('vscode/settings.json')); print('✅ settings.json valid')" |
| 96 | + |
| 97 | + - name: Validate keybindings.json |
| 98 | + run: python3 -c "import json; json.load(open('vscode/keybindings.json')); print('✅ keybindings.json valid')" |
| 99 | + |
| 100 | + # ─── 4. Check README is up to date ───────────────────────── |
| 101 | + validate-docs: |
| 102 | + name: Validate Documentation |
| 103 | + runs-on: ubuntu-latest |
| 104 | + steps: |
| 105 | + - uses: actions/checkout@v4 |
| 106 | + |
| 107 | + - name: Check required files exist |
| 108 | + run: | |
| 109 | + FILES=(README.md CONTRIBUTING.md CHANGELOG.md LICENSE .gitignore CLAUDE.md setup.sh) |
| 110 | + ERRORS=0 |
| 111 | + for f in "${FILES[@]}"; do |
| 112 | + if [ -f "$f" ]; then |
| 113 | + echo "✅ $f" |
| 114 | + else |
| 115 | + echo "❌ Missing: $f" |
| 116 | + ERRORS=$((ERRORS + 1)) |
| 117 | + fi |
| 118 | + done |
| 119 | + if [ $ERRORS -gt 0 ]; then exit 1; fi |
| 120 | +
|
| 121 | + - name: Check README mentions all skills |
| 122 | + run: | |
| 123 | + MISSING=0 |
| 124 | + for dir in skills/*/; do |
| 125 | + skill=$(basename "$dir") |
| 126 | + if ! grep -q "$skill" README.md; then |
| 127 | + echo "⚠️ README doesn't mention skill: $skill" |
| 128 | + MISSING=$((MISSING + 1)) |
| 129 | + fi |
| 130 | + done |
| 131 | + if [ $MISSING -gt 0 ]; then |
| 132 | + echo "$MISSING skill(s) not documented in README" |
| 133 | + else |
| 134 | + echo "✅ All skills documented in README" |
| 135 | + fi |
| 136 | + continue-on-error: true |
0 commit comments