|
| 1 | +# check-skills.yml — Drop this into your library repo's .github/workflows/ |
| 2 | +# |
| 3 | +# Checks for stale intent skills after a release 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: new release published, or manual workflow_dispatch. |
| 8 | +# |
| 9 | +# Template variables (replaced by `intent setup`): |
| 10 | +# @tanstack/devtools — e.g. @tanstack/query |
| 11 | + |
| 12 | +name: Check Skills |
| 13 | + |
| 14 | +on: |
| 15 | + release: |
| 16 | + types: [published] |
| 17 | + workflow_dispatch: {} |
| 18 | + |
| 19 | +permissions: |
| 20 | + contents: write |
| 21 | + pull-requests: write |
| 22 | + |
| 23 | +jobs: |
| 24 | + check: |
| 25 | + name: Check for stale skills |
| 26 | + runs-on: ubuntu-latest |
| 27 | + steps: |
| 28 | + - name: Checkout |
| 29 | + uses: actions/checkout@v4 |
| 30 | + with: |
| 31 | + fetch-depth: 0 |
| 32 | + |
| 33 | + - name: Setup Node |
| 34 | + uses: actions/setup-node@v4 |
| 35 | + with: |
| 36 | + node-version: 20 |
| 37 | + |
| 38 | + - name: Install intent |
| 39 | + run: npm install -g @tanstack/intent |
| 40 | + |
| 41 | + - name: Check staleness |
| 42 | + id: stale |
| 43 | + run: | |
| 44 | + OUTPUT=$(npx @tanstack/intent stale --json 2>&1) || true |
| 45 | + echo "$OUTPUT" |
| 46 | +
|
| 47 | + # Check if any skills need review |
| 48 | + NEEDS_REVIEW=$(echo "$OUTPUT" | node -e " |
| 49 | + const input = require('fs').readFileSync('/dev/stdin','utf8'); |
| 50 | + try { |
| 51 | + const reports = JSON.parse(input); |
| 52 | + const stale = reports.flatMap(r => |
| 53 | + r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons })) |
| 54 | + ); |
| 55 | + if (stale.length > 0) { |
| 56 | + console.log(JSON.stringify(stale)); |
| 57 | + } |
| 58 | + } catch {} |
| 59 | + ") |
| 60 | +
|
| 61 | + if [ -z "$NEEDS_REVIEW" ]; then |
| 62 | + echo "has_stale=false" >> "$GITHUB_OUTPUT" |
| 63 | + else |
| 64 | + echo "has_stale=true" >> "$GITHUB_OUTPUT" |
| 65 | + # Escape for multiline GH output |
| 66 | + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) |
| 67 | + echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT" |
| 68 | + echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT" |
| 69 | + echo "$EOF" >> "$GITHUB_OUTPUT" |
| 70 | + fi |
| 71 | +
|
| 72 | + - name: Build summary |
| 73 | + if: steps.stale.outputs.has_stale == 'true' |
| 74 | + id: summary |
| 75 | + run: | |
| 76 | + node -e " |
| 77 | + const stale = JSON.parse(process.env.STALE_JSON); |
| 78 | + const lines = stale.map(s => |
| 79 | + '- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ') |
| 80 | + ); |
| 81 | + const summary = lines.join('\n'); |
| 82 | +
|
| 83 | + const prompt = [ |
| 84 | + 'Review and update the following stale intent skills for @tanstack/devtools:', |
| 85 | + '', |
| 86 | + ...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')), |
| 87 | + '', |
| 88 | + 'For each stale skill:', |
| 89 | + '1. Read the current SKILL.md file', |
| 90 | + '2. Check what changed in the library since the skill was last updated', |
| 91 | + '3. Update the skill content to reflect current APIs and behavior', |
| 92 | + '4. Run \`npx @tanstack/intent validate\` to verify the updated skill', |
| 93 | + ].join('\n'); |
| 94 | +
|
| 95 | + // Write outputs |
| 96 | + const fs = require('fs'); |
| 97 | + const env = fs.readFileSync(process.env.GITHUB_OUTPUT, 'utf8'); |
| 98 | + const eof = require('crypto').randomBytes(15).toString('base64'); |
| 99 | + fs.appendFileSync(process.env.GITHUB_OUTPUT, |
| 100 | + 'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' + |
| 101 | + 'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n' |
| 102 | + ); |
| 103 | + " |
| 104 | + env: |
| 105 | + STALE_JSON: ${{ steps.stale.outputs.stale_json }} |
| 106 | + |
| 107 | + - name: Open review PR |
| 108 | + if: steps.stale.outputs.has_stale == 'true' |
| 109 | + env: |
| 110 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 111 | + run: | |
| 112 | + VERSION="${{ github.event.release.tag_name || 'manual' }}" |
| 113 | + BRANCH="skills/review-${VERSION}" |
| 114 | +
|
| 115 | + git config user.name "github-actions[bot]" |
| 116 | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" |
| 117 | + git checkout -b "$BRANCH" |
| 118 | + git commit --allow-empty -m "chore: review stale skills for ${VERSION}" |
| 119 | + git push origin "$BRANCH" |
| 120 | +
|
| 121 | + gh pr create \ |
| 122 | + --title "Review stale skills (${VERSION})" \ |
| 123 | + --body "$(cat <<'PREOF' |
| 124 | + ## Stale Skills Detected |
| 125 | +
|
| 126 | + The following skills may need updates after the latest release: |
| 127 | +
|
| 128 | + ${{ steps.summary.outputs.summary }} |
| 129 | +
|
| 130 | + --- |
| 131 | +
|
| 132 | + ### Update Prompt |
| 133 | +
|
| 134 | + Paste this into your coding agent (Claude Code, Cursor, etc.): |
| 135 | +
|
| 136 | + ~~~ |
| 137 | + ${{ steps.summary.outputs.prompt }} |
| 138 | + ~~~ |
| 139 | +
|
| 140 | + PREOF |
| 141 | + )" \ |
| 142 | + --head "$BRANCH" \ |
| 143 | + --base main |
0 commit comments