freshness check #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Freshness Check | |
| # --------------------------------------------------------------- | |
| # weekly stale content check. | |
| # scans docs/, hooks/, plugins/ for "tested with" version stamps, | |
| # flags files where the stamp is more than 2 versions behind. | |
| # creates a single tracking issue (no duplicates). | |
| # | |
| # cost: ~$0.01 per run (mostly shell, minimal claude usage) | |
| # --------------------------------------------------------------- | |
| on: | |
| schedule: | |
| - cron: '0 10 * * 1' # every monday at 10:00 UTC | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| issues: write | |
| jobs: | |
| check-freshness: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Get latest Claude Code version | |
| id: latest | |
| run: | | |
| # npm view works without installing the package | |
| LATEST=$(npm view @anthropic-ai/claude-code version 2>/dev/null || echo "unknown") | |
| echo "version=$LATEST" >> "$GITHUB_OUTPUT" | |
| echo "Latest Claude Code version: $LATEST" | |
| - name: Scan for stale stamps | |
| id: scan | |
| env: | |
| LATEST_VERSION: ${{ steps.latest.outputs.version }} | |
| run: | | |
| STALE_FILES="" | |
| MISSING_FILES="" | |
| CHECKED=0 | |
| DIRS="docs hooks plugins agents skills commands" | |
| for dir in $DIRS; do | |
| [ ! -d "$dir" ] && continue | |
| while IFS= read -r file; do | |
| CHECKED=$((CHECKED + 1)) | |
| # look for version stamps like "tested with: claude code v1.0.x" | |
| STAMP=$(grep -ioE 'tested.with[: ]+claude.code.v?[0-9]+\.[0-9]+\.[0-9]+' "$file" 2>/dev/null || true) | |
| if [ -z "$STAMP" ]; then | |
| MISSING_FILES="$MISSING_FILES\n- \`$file\` -- no stamp" | |
| else | |
| # extract version number from stamp | |
| STAMP_VER=$(echo "$STAMP" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) | |
| if [ -n "$STAMP_VER" ] && [ -n "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "unknown" ]; then | |
| # compare major.minor (ignore patch) | |
| STAMP_MAJOR=$(echo "$STAMP_VER" | cut -d. -f1) | |
| STAMP_MINOR=$(echo "$STAMP_VER" | cut -d. -f2) | |
| LATEST_MAJOR=$(echo "$LATEST_VERSION" | cut -d. -f1) | |
| LATEST_MINOR=$(echo "$LATEST_VERSION" | cut -d. -f2) | |
| # stale if minor version is 2+ behind (same major) or major behind | |
| if [ "$STAMP_MAJOR" -lt "$LATEST_MAJOR" ] 2>/dev/null || \ | |
| { [ "$STAMP_MAJOR" -eq "$LATEST_MAJOR" ] && [ $((LATEST_MINOR - STAMP_MINOR)) -ge 2 ]; } 2>/dev/null; then | |
| STALE_FILES="$STALE_FILES\n- \`$file\` -- stamped v$STAMP_VER, latest v$LATEST_VERSION" | |
| fi | |
| fi | |
| fi | |
| done < <(git ls-files "$dir") | |
| done | |
| echo "Checked $CHECKED files" | |
| # write report | |
| if [ -n "$STALE_FILES" ] || [ -n "$MISSING_FILES" ]; then | |
| { | |
| echo "## freshness report $(date +%Y-%m-%d)" | |
| echo "" | |
| echo "latest claude code: v$LATEST_VERSION" | |
| echo "" | |
| if [ -n "$STALE_FILES" ]; then | |
| echo "### stale stamps (2+ versions behind)" | |
| echo -e "$STALE_FILES" | |
| echo "" | |
| fi | |
| if [ -n "$MISSING_FILES" ]; then | |
| echo "### missing stamps" | |
| echo -e "$MISSING_FILES" | |
| echo "" | |
| fi | |
| echo "---" | |
| echo "automated check -- update stamps after re-testing with current version." | |
| } > /tmp/freshness-report.md | |
| echo "has_stale=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "all stamps are current" | |
| echo "has_stale=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Create or update tracking issue | |
| if: steps.scan.outputs.has_stale == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ISSUE_TITLE="stale content: freshness check $(date +%Y-%m-%d)" | |
| # ensure label exists (self-healing) | |
| gh label create "freshness-check" --color "FBCA04" --description "automated freshness check" 2>/dev/null || true | |
| # close any previous freshness check issues to avoid duplicates | |
| EXISTING=$(gh issue list --label "freshness-check" --state open --json number -q '.[].number' 2>/dev/null || true) | |
| for num in $EXISTING; do | |
| gh issue close "$num" --comment "superseded by new freshness check" 2>/dev/null || true | |
| done | |
| gh issue create \ | |
| --title "$ISSUE_TITLE" \ | |
| --body-file /tmp/freshness-report.md \ | |
| --label "freshness-check" |