Skip to content

Commit 96b78e8

Browse files
committed
ci: add Intent skill CI workflows
1 parent 99677b2 commit 96b78e8

3 files changed

Lines changed: 249 additions & 0 deletions

File tree

.github/workflows/check-skills.yml

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# check-skills.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Checks for stale intent skills and opens a review PR
4+
# if any skills need attention. The PR body includes a prompt you can
5+
# paste into Claude Code, Cursor, or any coding agent to update them.
6+
#
7+
# Triggers: merge to develop, or manual workflow_dispatch.
8+
#
9+
# Template variables (replaced by `intent setup`):
10+
# livecodes — e.g. @tanstack/query or my-workspace workspace
11+
12+
name: Check Skills
13+
14+
on:
15+
push:
16+
branches:
17+
- develop
18+
release:
19+
types: [published]
20+
workflow_dispatch: {}
21+
22+
permissions:
23+
contents: write
24+
pull-requests: write
25+
26+
jobs:
27+
check:
28+
name: Check for stale skills
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Checkout
32+
uses: actions/checkout@v4
33+
with:
34+
fetch-depth: 0
35+
36+
- name: Setup Node
37+
uses: actions/setup-node@v4
38+
with:
39+
node-version: 20
40+
41+
- name: Install intent
42+
run: npm install -g @tanstack/intent
43+
44+
- name: Check staleness
45+
id: stale
46+
run: |
47+
OUTPUT=$(intent stale --json 2>&1) || true
48+
echo "$OUTPUT"
49+
50+
# Check if any skills need review
51+
NEEDS_REVIEW=$(echo "$OUTPUT" | node -e "
52+
const input = require('fs').readFileSync('/dev/stdin','utf8');
53+
try {
54+
const reports = JSON.parse(input);
55+
const stale = reports.flatMap(r =>
56+
r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons }))
57+
);
58+
if (stale.length > 0) {
59+
console.log(JSON.stringify(stale));
60+
}
61+
} catch {}
62+
")
63+
64+
if [ -z "$NEEDS_REVIEW" ]; then
65+
echo "has_stale=false" >> "$GITHUB_OUTPUT"
66+
else
67+
echo "has_stale=true" >> "$GITHUB_OUTPUT"
68+
# Escape for multiline GH output
69+
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
70+
echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT"
71+
echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT"
72+
echo "$EOF" >> "$GITHUB_OUTPUT"
73+
fi
74+
75+
- name: Build summary
76+
if: steps.stale.outputs.has_stale == 'true'
77+
id: summary
78+
run: |
79+
node -e "
80+
const stale = JSON.parse(process.env.STALE_JSON);
81+
const lines = stale.map(s =>
82+
'- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ')
83+
);
84+
const summary = lines.join('\n');
85+
86+
const prompt = [
87+
'Review and update the following stale intent skills for livecodes:',
88+
'',
89+
...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')),
90+
'',
91+
'For each stale skill:',
92+
'1. Read the current SKILL.md file',
93+
'2. Check what changed in the library since the skill was last updated',
94+
'3. Update the skill content to reflect current APIs and behavior',
95+
'4. Run \`npx @tanstack/intent validate\` to verify the updated skill',
96+
].join('\n');
97+
98+
// Write outputs
99+
const fs = require('fs');
100+
const env = fs.readFileSync(process.env.GITHUB_OUTPUT, 'utf8');
101+
const eof = require('crypto').randomBytes(15).toString('base64');
102+
fs.appendFileSync(process.env.GITHUB_OUTPUT,
103+
'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' +
104+
'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n'
105+
);
106+
"
107+
env:
108+
STALE_JSON: ${{ steps.stale.outputs.stale_json }}
109+
110+
- name: Open review PR
111+
if: steps.stale.outputs.has_stale == 'true'
112+
env:
113+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
114+
run: |
115+
VERSION="${{ github.event.release.tag_name || 'manual' }}"
116+
BRANCH="skills/review-${VERSION}"
117+
118+
git config user.name "github-actions[bot]"
119+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
120+
git checkout -b "$BRANCH"
121+
git commit --allow-empty -m "chore: review stale skills for ${VERSION}"
122+
git push origin "$BRANCH"
123+
124+
gh pr create \
125+
--title "Review stale skills (${VERSION})" \
126+
--body "$(cat <<'PREOF'
127+
## Stale Skills Detected
128+
129+
The following skills may need updates after the latest release:
130+
131+
${{ steps.summary.outputs.summary }}
132+
133+
---
134+
135+
### Update Prompt
136+
137+
Paste this into your coding agent (Claude Code, Cursor, etc.):
138+
139+
~~~
140+
${{ steps.summary.outputs.prompt }}
141+
~~~
142+
143+
PREOF
144+
)" \
145+
--head "$BRANCH" \
146+
--base main
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# notify-intent.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Fires a repository_dispatch event whenever docs or source files change
4+
# on merge to develop. This triggers the skill staleness check workflow.
5+
#
6+
# Requirements:
7+
# - A fine-grained PAT with contents:write on this repository stored
8+
# as the INTENT_NOTIFY_TOKEN repository secret.
9+
#
10+
# Template variables (replaced by `intent setup`):
11+
# livecodes — e.g. @tanstack/query or my-workspace workspace
12+
# docs/** — e.g. docs/**
13+
# src/** — e.g. packages/query-core/src/**
14+
15+
name: Trigger Skill Review
16+
17+
on:
18+
push:
19+
branches: [develop]
20+
paths:
21+
- "docs/**"
22+
- "src/**"
23+
24+
jobs:
25+
notify:
26+
name: Trigger Skill Review
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 2
33+
34+
- name: Collect changed files
35+
id: changes
36+
run: |
37+
FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))')
38+
echo "files=$FILES" >> "$GITHUB_OUTPUT"
39+
40+
- name: Dispatch to intent repo
41+
uses: peter-evans/repository-dispatch@v3
42+
with:
43+
token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
44+
repository: ${{ github.repository }}
45+
event-type: skill-check
46+
client-payload: |
47+
{
48+
"package": "livecodes",
49+
"sha": "${{ github.sha }}",
50+
"changed_files": ${{ steps.changes.outputs.files }}
51+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# validate-skills.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Validates skill files on PRs that touch the skills/ directory.
4+
# Ensures frontmatter is correct, names match paths, and files stay under
5+
# the 500-line limit.
6+
7+
name: Validate Skills
8+
9+
on:
10+
pull_request:
11+
paths:
12+
- 'skills/**'
13+
- '**/skills/**'
14+
15+
jobs:
16+
validate:
17+
name: Validate skill files
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup Node
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
28+
- name: Install intent CLI
29+
run: npm install -g @tanstack/intent
30+
31+
- name: Find and validate skills
32+
run: |
33+
# Find all directories containing SKILL.md files
34+
SKILLS_DIR=""
35+
if [ -d "skills" ]; then
36+
SKILLS_DIR="skills"
37+
elif [ -d "packages" ]; then
38+
# Monorepo — find skills/ under packages
39+
for dir in packages/*/skills; do
40+
if [ -d "$dir" ]; then
41+
echo "Validating $dir..."
42+
intent validate "$dir"
43+
fi
44+
done
45+
exit 0
46+
fi
47+
48+
if [ -n "$SKILLS_DIR" ]; then
49+
intent validate "$SKILLS_DIR"
50+
else
51+
echo "No skills/ directory found — skipping validation."
52+
fi

0 commit comments

Comments
 (0)