Skip to content

Commit 6be1d8e

Browse files
committed
refactor: streamline skills validation process in workflow and script
1 parent d2989fe commit 6be1d8e

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

.github/workflows/validate-skills.yml

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,4 @@ jobs:
1818

1919
- run: npm ci
2020

21-
- name: Detect changed skill directories
22-
id: changed-skills
23-
run: |
24-
# Collect top-level skill dirs touched by this PR (relative to skills/).
25-
# Passing explicit dirs means pre-existing nested skill categories
26-
# (to be flattened in a separate PR) don't block unrelated skill PRs.
27-
DIRS=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \
28-
| grep '^skills/' \
29-
| cut -d'/' -f2 \
30-
| sort -u \
31-
| tr '\n' ' ')
32-
echo "dirs=$DIRS" >> $GITHUB_OUTPUT
33-
echo "Validating skill dirs: $DIRS"
34-
35-
- name: Validate changed skills
36-
run: npx tsx scripts/validate-skills.ts ${{ steps.changed-skills.outputs.dirs }}
21+
- run: npm run validate:skills -- --changed --base=origin/${{ github.base_ref }}

scripts/validate-skills.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
// Exits with code 1 if any violations are found.
44
//
55
// Usage:
6-
// tsx scripts/validate-skills.ts # validate all skills
7-
// tsx scripts/validate-skills.ts apex-class # validate specific skill dirs
6+
// npm run validate:skills # validate all skills
7+
// npm run validate:skills -- --changed --base=origin/main # validate only skills changed vs base
88

9+
import { execSync } from "child_process"
910
import fs from "fs"
1011
import path from "path"
12+
import { parseArgs } from "util"
1113

1214
const SKILLS_DIR = path.join(__dirname, "..", "skills")
1315

@@ -136,6 +138,23 @@ const CONTENT_CHECKS: ContentCheck[] = [
136138
},
137139
]
138140

141+
// ---------------------------------------------------------------------------
142+
// Changed-skills detection
143+
// ---------------------------------------------------------------------------
144+
145+
function getChangedSkillDirs(base: string): string[] {
146+
const output = execSync(`git diff --name-only ${base}...HEAD`, { encoding: "utf8" })
147+
return [
148+
...new Set(
149+
output
150+
.split("\n")
151+
.filter((f) => f.startsWith("skills/"))
152+
.map((f) => f.split("/")[1])
153+
.filter(Boolean)
154+
),
155+
]
156+
}
157+
139158
// ---------------------------------------------------------------------------
140159
// Helpers
141160
// ---------------------------------------------------------------------------
@@ -193,10 +212,28 @@ function validateSkill(dirName: string, dirPath: string): string[] {
193212
}
194213

195214
function main(): void {
196-
// If skill dir names are passed as arguments, validate only those.
197-
// Otherwise validate all entries in skills/.
198-
const targets = process.argv.slice(2)
199-
const entries = targets.length > 0 ? targets : fs.readdirSync(SKILLS_DIR)
215+
const { values } = parseArgs({
216+
args: process.argv.slice(2),
217+
options: {
218+
/** Validate only skill dirs touched in this branch vs the given base ref. */
219+
changed: { type: "boolean", default: false },
220+
/** Base ref for --changed (e.g. origin/main). Defaults to origin/HEAD. */
221+
base: { type: "string", default: "origin/HEAD" },
222+
},
223+
})
224+
225+
let entries: string[]
226+
227+
if (values.changed) {
228+
entries = getChangedSkillDirs(values.base!)
229+
if (entries.length === 0) {
230+
console.log("No skill directories changed — nothing to validate.")
231+
return
232+
}
233+
console.log(`Validating ${entries.length} changed skill(s): ${entries.join(", ")}`)
234+
} else {
235+
entries = fs.readdirSync(SKILLS_DIR)
236+
}
200237

201238
const allErrors: string[] = []
202239
let passed = 0

0 commit comments

Comments
 (0)