Files
zebbern f73c6d0a76 feat: restructure repo with guides, agents, and root CHANGELOG
- Rename 'Guide On CLAUDE.md' folder to 'guides/'
- Move CHANGELOG.md to root (was in Official Claude Releases/)
- Delete 'Official Claude Releases' folder
- Add agents/ directory with 100+ subagent definitions
- Add new guide sections: testing/, typescript/, security/
- Update zebbern CLAUDE.md with 2026 best practices
- Update sync workflow to target root CHANGELOG.md
2026-02-08 05:06:23 +01:00

286 lines
9.5 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Sync Anthropic Release Notes
on:
schedule:
# Runs once every 24h at 00:15 UTC
- cron: "15 0 * * *"
workflow_dispatch:
inputs:
force_update:
description: 'Force update all files'
required: false
type: boolean
default: false
permissions:
contents: write
concurrency:
group: sync-release-notes
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
persist-credentials: true
fetch-depth: 0
- name: Download and process release notes
id: sync_files
env:
FORCE_UPDATE: ${{ github.event.inputs.force_update || 'false' }}
run: |
set -euo pipefail
# Configuration - Now syncing directly to root
readonly MAX_RETRIES=3
readonly RETRY_DELAY=5
# Color output for better readability in logs
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Source URLs mapped to destination filenames (synced to root)
# Only raw markdown URLs are supported (HTML pages cannot be fetched as markdown)
declare -A FILES=(
["https://raw.githubusercontent.com/anthropics/claude-code/main/CHANGELOG.md"]="CHANGELOG.md"
)
# Function to download with retries
download_with_retry() {
local url="$1"
local output="$2"
local attempt=1
while [[ $attempt -le $MAX_RETRIES ]]; do
if curl -fsSL \
-H "Accept: text/markdown, text/plain;q=0.9, text/x-markdown;q=0.9, */*;q=0.1" \
-H "User-Agent: GitHub-Actions-Release-Notes-Sync/1.0" \
--connect-timeout 10 \
--max-time 30 \
"$url" -o "$output"; then
return 0
fi
echo -e "${YELLOW}Attempt $attempt/$MAX_RETRIES failed for $url${NC}" >&2
if [[ $attempt -lt $MAX_RETRIES ]]; then
sleep $RETRY_DELAY
fi
((attempt++))
done
echo -e "${RED}Failed to download $url after $MAX_RETRIES attempts${NC}" >&2
return 1
}
# Validate downloaded content
validate_content() {
local file="$1"
local min_size=10
# Check file exists and has content
if [[ ! -f "$file" ]] || [[ ! -s "$file" ]]; then
echo -e "${RED}File $file is empty or doesn't exist${NC}" >&2
return 1
fi
# Check minimum size
local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [[ $size -lt $min_size ]]; then
echo -e "${RED}File $file is too small ($size bytes)${NC}" >&2
return 1
fi
return 0
}
# Arrays to track changes
declare -a CHANGED_FILES=()
COMMIT_BODY=""
README_LIST=""
TOTAL_ADDED=0
TOTAL_DELETED=0
# Process each file
for url in "${!FILES[@]}"; do
name="${FILES[$url]}"
out="$name"
tmp="$out.tmp"
echo -e "${GREEN}Processing: $name${NC}"
# Download file
if ! download_with_retry "$url" "$tmp"; then
echo -e "${RED}Skipping $name due to download failure${NC}"
rm -f "$tmp"
continue
fi
# Validate downloaded content
if ! validate_content "$tmp"; then
echo -e "${RED}Skipping $name due to validation failure${NC}"
rm -f "$tmp"
continue
fi
# Check if file needs updating
needs_update=false
if [[ "$FORCE_UPDATE" == "true" ]]; then
needs_update=true
echo "Force update enabled"
elif [[ ! -f "$out" ]]; then
needs_update=true
echo "New file detected"
elif ! git --no-pager diff --no-index --ignore-all-space --quiet -- "$out" "$tmp" 2>/dev/null; then
needs_update=true
echo "Changes detected"
fi
if [[ "$needs_update" == "false" ]]; then
echo "No changes for $name"
rm -f "$tmp"
continue
fi
# Calculate statistics
base_file="$out"
[[ -f "$out" ]] || base_file="/dev/null"
numstat=$(git --no-pager diff --no-index --numstat -- "$base_file" "$tmp" 2>/dev/null || echo "0 0 -")
read -r added deleted _ <<< "$numstat"
# Extract highlights from changes
highlights=$(
git --no-pager diff --no-index -U0 -- "$base_file" "$tmp" 2>/dev/null \
| sed -n 's/^+[^+]//p' \
| grep -E '^(#{1,3} |- |\* |[0-9]+\. )' \
| head -n 5 || true
)
# Fallback to first few lines if no structured content
if [[ -z "$highlights" ]]; then
highlights=$(
git --no-pager diff --no-index -U0 -- "$base_file" "$tmp" 2>/dev/null \
| sed -n 's/^+[^+]//p' \
| grep -v '^$' \
| head -n 3 || true
)
fi
# Update file and track changes
mv -f "$tmp" "$out"
CHANGED_FILES+=("$out")
# Build commit message body
COMMIT_BODY+="- **${name}** (+${added:-0} / -${deleted:-0})"$'\n'
if [[ -n "$highlights" ]]; then
while IFS= read -r line; do
# Truncate long lines
line="${line:0:100}"
COMMIT_BODY+=" • ${line}"$'\n'
done <<< "$highlights"
fi
# Build README summary
README_LIST+="- **${name}**: +${added:-0} / -${deleted:-0}"$'\n'
# Track totals
((TOTAL_ADDED += added)) || true
((TOTAL_DELETED += deleted)) || true
echo -e "${GREEN}✓ Updated $name (+$added / -$deleted)${NC}"
done
# Stage changed files
if [[ ${#CHANGED_FILES[@]} -gt 0 ]]; then
git add "${CHANGED_FILES[@]}"
echo "files_changed=true" >> "$GITHUB_OUTPUT"
else
echo "files_changed=false" >> "$GITHUB_OUTPUT"
fi
# Save data for next steps
{
printf '%b' "$COMMIT_BODY"
} > /tmp/commit_body.txt
{
printf '%b' "$README_LIST"
} > /tmp/readme_list.txt
echo "total_added=$TOTAL_ADDED" >> "$GITHUB_OUTPUT"
echo "total_deleted=$TOTAL_DELETED" >> "$GITHUB_OUTPUT"
echo "changed_count=${#CHANGED_FILES[@]}" >> "$GITHUB_OUTPUT"
- name: Commit and push changes
if: always()
run: |
set -euo pipefail
# Configure git
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# Check if there are changes to commit
if ! git diff --cached --quiet; then
date_str=$(date -u +%Y-%m-%d)
if [[ "${{ steps.sync_files.outputs.files_changed }}" == "true" ]]; then
# Content changes detected
title="Sync release notes ($date_str)"
body=$(cat /tmp/commit_body.txt 2>/dev/null || echo "Updated release notes")
git commit -m "$title" -m "$body"
echo "✅ Committed content changes"
else
# Only README status update
title="Update sync status ($date_str)"
body="No release note content changes. Updated status in README."
git commit -m "$title" -m "$body"
echo "✅ Committed status update"
fi
# Push changes
git push
echo "✅ Pushed changes to repository"
else
echo "️ No changes to commit"
fi
- name: Create summary
if: always()
run: |
{
echo "## Sync Summary"
echo
if [[ "${{ steps.sync_files.outputs.files_changed }}" == "true" ]]; then
echo "### ✅ Success"
echo
echo "**Files updated**: ${{ steps.sync_files.outputs.changed_count }}"
echo "**Lines added**: +${{ steps.sync_files.outputs.total_added }}"
echo "**Lines deleted**: -${{ steps.sync_files.outputs.total_deleted }}"
echo
echo "### 📝 Changes"
echo
echo '```'
cat /tmp/commit_body.txt 2>/dev/null || echo "No details available"
echo '```'
else
echo "### ️ No Changes"
echo
echo "All tracked files are up to date. Status README was updated."
fi
} >> "$GITHUB_STEP_SUMMARY"