fix(icons): use icon exports in ejected skins #430
Workflow file for this run
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: API Reference Sync | |
| on: | |
| pull_request: | |
| types: [closed] | |
| permissions: | |
| actions: read | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| id-token: write | |
| concurrency: | |
| group: api-reference-sync-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ─── Job 0: Build API JSON at HEAD~1 and HEAD, diff them ───────────── | |
| analyze: | |
| if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has_diff: ${{ steps.classify.outputs.has_diff }} | |
| has_new: ${{ steps.classify.outputs.has_new }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: pnpm | |
| - name: Collect PR metadata | |
| id: meta | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title || 'manual run' }} | |
| run: | | |
| mkdir -p /tmp/api-sync | |
| jq -n \ | |
| --arg number "${{ github.event.pull_request.number || '' }}" \ | |
| --arg url "${{ github.event.pull_request.html_url || '' }}" \ | |
| --arg author "${{ github.event.pull_request.user.login || '' }}" \ | |
| --arg title "$PR_TITLE" \ | |
| '{number: $number, url: $url, author: $author, title: $title}' \ | |
| > /tmp/api-sync/pr-meta.json | |
| cat /tmp/api-sync/pr-meta.json | |
| - name: Build API JSON at HEAD | |
| run: | | |
| pnpm install --frozen-lockfile | |
| pnpm -C site api-docs | |
| mkdir -p /tmp/api-sync/after-components /tmp/api-sync/after-utils | |
| cp -r site/src/content/generated-component-reference/* /tmp/api-sync/after-components/ 2>/dev/null || true | |
| cp -r site/src/content/generated-util-reference/* /tmp/api-sync/after-utils/ 2>/dev/null || true | |
| - name: Build API JSON at HEAD~1 | |
| run: | | |
| git checkout HEAD~1 | |
| # If install or build fails (e.g. api-docs-builder itself changed), | |
| # treat everything as new by leaving before dirs empty | |
| mkdir -p /tmp/api-sync/before-components /tmp/api-sync/before-utils | |
| if pnpm install --frozen-lockfile && pnpm -C site api-docs; then | |
| cp -r site/src/content/generated-component-reference/* /tmp/api-sync/before-components/ 2>/dev/null || true | |
| cp -r site/src/content/generated-util-reference/* /tmp/api-sync/before-utils/ 2>/dev/null || true | |
| else | |
| echo "::warning::HEAD~1 build failed — treating all components/utils as new" | |
| fi | |
| git checkout - | |
| - name: Classify changes | |
| id: classify | |
| run: | | |
| # Unified diff of both JSON directories | |
| diff -ruN /tmp/api-sync/before-components /tmp/api-sync/after-components > /tmp/api-sync/diff.patch || true | |
| diff -ruN /tmp/api-sync/before-utils /tmp/api-sync/after-utils >> /tmp/api-sync/diff.patch || true | |
| # New: files in after but not in before | |
| comm -23 \ | |
| <(ls /tmp/api-sync/after-components/ 2>/dev/null | sort) \ | |
| <(ls /tmp/api-sync/before-components/ 2>/dev/null | sort) \ | |
| > /tmp/api-sync/new-components.txt | |
| comm -23 \ | |
| <(ls /tmp/api-sync/after-utils/ 2>/dev/null | sort) \ | |
| <(ls /tmp/api-sync/before-utils/ 2>/dev/null | sort) \ | |
| > /tmp/api-sync/new-utils.txt | |
| # Changed: files in both, but content differs | |
| comm -12 \ | |
| <(ls /tmp/api-sync/after-components/ 2>/dev/null | sort) \ | |
| <(ls /tmp/api-sync/before-components/ 2>/dev/null | sort) \ | |
| | while read -r f; do | |
| if ! diff -q "/tmp/api-sync/before-components/$f" "/tmp/api-sync/after-components/$f" >/dev/null 2>&1; then | |
| echo "$f" | |
| fi | |
| done > /tmp/api-sync/changed-components.txt | |
| comm -12 \ | |
| <(ls /tmp/api-sync/after-utils/ 2>/dev/null | sort) \ | |
| <(ls /tmp/api-sync/before-utils/ 2>/dev/null | sort) \ | |
| | while read -r f; do | |
| if ! diff -q "/tmp/api-sync/before-utils/$f" "/tmp/api-sync/after-utils/$f" >/dev/null 2>&1; then | |
| echo "$f" | |
| fi | |
| done > /tmp/api-sync/changed-utils.txt | |
| # Log results | |
| echo "=== New components ===" && cat /tmp/api-sync/new-components.txt | |
| echo "=== New utils ===" && cat /tmp/api-sync/new-utils.txt | |
| echo "=== Changed components ===" && cat /tmp/api-sync/changed-components.txt | |
| echo "=== Changed utils ===" && cat /tmp/api-sync/changed-utils.txt | |
| echo "=== Diff ===" && head -100 /tmp/api-sync/diff.patch | |
| # Set outputs | |
| if [ -s /tmp/api-sync/diff.patch ]; then | |
| echo "has_diff=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_diff=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| if [ -s /tmp/api-sync/new-components.txt ] || [ -s /tmp/api-sync/new-utils.txt ]; then | |
| echo "has_new=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_new=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload artifact | |
| if: steps.classify.outputs.has_diff == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: api-diff | |
| path: /tmp/api-sync/ | |
| retention-days: 1 | |
| # ─── Job 1: Open issues for new components/utils without reference pages | |
| new-references: | |
| needs: analyze | |
| if: needs.analyze.outputs.has_new == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: api-diff | |
| path: /tmp/api-sync | |
| - name: Open issues for missing reference pages | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| PR_NUMBER=$(jq -r .number /tmp/api-sync/pr-meta.json) | |
| PR_URL=$(jq -r .url /tmp/api-sync/pr-meta.json) | |
| PR_AUTHOR=$(jq -r .author /tmp/api-sync/pr-meta.json) | |
| REF_DIR="site/src/content/docs/reference" | |
| # --- New components --- | |
| if [ -s /tmp/api-sync/new-components.txt ]; then | |
| while read -r filename; do | |
| JSON_PATH="/tmp/api-sync/after-components/$filename" | |
| NAME=$(jq -r .name "$JSON_PATH") | |
| SLUG="${filename%.json}" | |
| # Check if a reference page already uses this component | |
| if grep -rq "<ComponentReference component=\"$NAME\"" "$REF_DIR/"; then | |
| echo "Reference exists for component $NAME — skipping" | |
| continue | |
| fi | |
| # Check for existing open issue (dedup by drift-type + component name) | |
| EXISTING=$(gh issue list \ | |
| --label "docs" \ | |
| --search "docs(reference): add $NAME API reference page" \ | |
| --state open \ | |
| --json number \ | |
| --jq 'length') | |
| if [ "$EXISTING" -gt 0 ]; then | |
| echo "Open issue already exists for $NAME — skipping" | |
| continue | |
| fi | |
| ASSIGNEE_FLAG="" | |
| if [ -n "$PR_AUTHOR" ]; then | |
| ASSIGNEE_FLAG="--assignee $PR_AUTHOR" | |
| fi | |
| BODY="$(cat <<EOF | |
| <!-- drift-type:new-reference --> | |
| <!-- trigger-pr:$PR_NUMBER --> | |
| <!-- component:$NAME --> | |
| ## New Component: \`$NAME\` | |
| A new component \`$NAME\` was added in #${PR_NUMBER} but has no API reference page yet. | |
| ### What's needed | |
| - [ ] Create reference page with anatomy, prose, demos, and \`<ComponentReference component="$NAME" />\` | |
| - [ ] Add sidebar entry in \`site/src/docs.config.ts\` | |
| - [ ] Verify build: \`pnpm -C site build\` | |
| ### Context | |
| - Triggering PR: $PR_URL | |
| - Generated JSON: \`site/src/content/generated-component-reference/$filename\` | |
| > Use the \`/api-reference $SLUG\` skill to scaffold this page. | |
| EOF | |
| )" | |
| gh issue create \ | |
| --title "docs(reference): add $NAME API reference page" \ | |
| --body "$BODY" \ | |
| --label "docs,site,components" \ | |
| $ASSIGNEE_FLAG | |
| echo "Created issue for component $NAME" | |
| done < /tmp/api-sync/new-components.txt | |
| fi | |
| # --- New utils --- | |
| if [ -s /tmp/api-sync/new-utils.txt ]; then | |
| while read -r filename; do | |
| JSON_PATH="/tmp/api-sync/after-utils/$filename" | |
| NAME=$(jq -r .name "$JSON_PATH") | |
| SLUG="${filename%.json}" | |
| # Check if a reference page already uses this util | |
| if grep -rq "<UtilReference util=\"$NAME\"" "$REF_DIR/"; then | |
| echo "Reference exists for util $NAME — skipping" | |
| continue | |
| fi | |
| # Check for existing open issue | |
| EXISTING=$(gh issue list \ | |
| --label "docs" \ | |
| --search "docs(reference): add $NAME API reference page" \ | |
| --state open \ | |
| --json number \ | |
| --jq 'length') | |
| if [ "$EXISTING" -gt 0 ]; then | |
| echo "Open issue already exists for $NAME — skipping" | |
| continue | |
| fi | |
| ASSIGNEE_FLAG="" | |
| if [ -n "$PR_AUTHOR" ]; then | |
| ASSIGNEE_FLAG="--assignee $PR_AUTHOR" | |
| fi | |
| BODY="$(cat <<EOF | |
| <!-- drift-type:new-reference --> | |
| <!-- trigger-pr:$PR_NUMBER --> | |
| <!-- util:$NAME --> | |
| ## New Utility: \`$NAME\` | |
| A new utility \`$NAME\` was added in #${PR_NUMBER} but has no API reference page yet. | |
| ### What's needed | |
| - [ ] Create reference page with usage examples and \`<UtilReference util="$NAME" />\` | |
| - [ ] Add sidebar entry in \`site/src/docs.config.ts\` | |
| - [ ] Verify build: \`pnpm -C site build\` | |
| ### Context | |
| - Triggering PR: $PR_URL | |
| - Generated JSON: \`site/src/content/generated-util-reference/$filename\` | |
| > Use the \`/api-reference $SLUG\` skill to scaffold this page. | |
| EOF | |
| )" | |
| gh issue create \ | |
| --title "docs(reference): add $NAME API reference page" \ | |
| --body "$BODY" \ | |
| --label "docs,site" \ | |
| $ASSIGNEE_FLAG | |
| echo "Created issue for util $NAME" | |
| done < /tmp/api-sync/new-utils.txt | |
| fi | |
| # ─── Job 2: Detect stale docs (Claude Opus) ───────────────────────── | |
| stale-docs: | |
| needs: analyze | |
| if: needs.analyze.outputs.has_diff == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: api-diff | |
| path: /tmp/api-sync | |
| - name: Detect stale docs | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| claude_args: | | |
| --model opus | |
| --max-turns 25 | |
| --allowedTools "Read" "Glob" "Grep" "Bash(gh:*)" "Bash(cat:*)" "Bash(jq:*)" "Bash(diff:*)" "Bash(ls:*)" "Bash(head:*)" "Bash(tail:*)" "Bash(wc:*)" "Bash(sort:*)" | |
| prompt: | | |
| You are the stale-docs detection agent. Your job: given a pre-computed API diff, | |
| find documentation that may need updating and open ONE GitHub issue summarizing all findings. | |
| ## Inputs | |
| The following files are at /tmp/api-sync/: | |
| - `diff.patch` — unified diff of API JSON between HEAD~1 and HEAD | |
| - `changed-components.txt` — filenames of changed component JSONs (one per line, may be empty) | |
| - `changed-utils.txt` — filenames of changed util JSONs (one per line, may be empty) | |
| - `after-components/` — current component JSON files | |
| - `after-utils/` — current util JSON files | |
| - `pr-meta.json` — `{number, url, author, title}` of the triggering PR | |
| Important: Focus on items in `changed-components.txt` and `changed-utils.txt`. | |
| Skip any components/utils listed in `new-components.txt` or `new-utils.txt` — | |
| a separate job already opens issues for those. | |
| ## Process | |
| Step 1: Read `pr-meta.json` and `diff.patch`. Understand what API surfaces changed and how. | |
| Step 2: For each changed component/util, read the "after" JSON to understand the current API shape. | |
| Step 3: Search for documentation that references these APIs. Check ALL of: | |
| - `site/src/content/docs/reference/` — MDX reference pages (look for stale prop descriptions, | |
| missing new props/state/data-attributes, outdated type signatures) | |
| - `site/src/content/docs/concepts/` — concept pages mentioning these APIs | |
| - `site/src/content/docs/how-to/` — how-to guides mentioning these APIs | |
| - `site/src/components/docs/demos/` — demo code using changed props/state/signatures | |
| - `packages/*/README.md` — package READMEs mentioning these APIs | |
| Use Grep and Glob to search efficiently. Look for: | |
| - The component/util name (PascalCase, camelCase) | |
| - Specific prop/state/parameter names that were added, removed, or changed in the diff | |
| - HTML element names from `platforms.html.tagName` in the JSON (e.g. `media-play-button`) | |
| - Data attribute names that changed | |
| Step 4: For each file with hits, read the relevant section and assess: | |
| - `high` — definitely stale (references a removed/renamed prop by old name, shows old signature) | |
| - `medium` — likely stale (mentions API whose behavior/type changed) | |
| - `low` — possibly stale (mentions the component but may not be affected) | |
| Discard clear false positives. Include borderline cases for human review. | |
| Step 5: If you found ANY stale references, open exactly ONE issue using `gh issue create`. | |
| If you found NOTHING stale, do NOT create an issue — just output "No stale docs detected." | |
| ## Issue format | |
| Read `pr-meta.json` to get PR_NUMBER, PR_URL, PR_AUTHOR, and PR_TITLE. | |
| Assign the issue to the PR author: `--assignee $PR_AUTHOR` (skip if author is empty). | |
| Title: `docs(site): stale docs from #$PR_NUMBER` | |
| Labels: `docs,site` | |
| Body (use this structure exactly): | |
| ``` | |
| <!-- drift-type:stale-docs --> | |
| <!-- trigger-pr:{PR_NUMBER} --> | |
| ## Summary | |
| API changes in #{PR_NUMBER} ({PR_TITLE}) may have made the following documentation stale. | |
| ## Triggering PR | |
| {PR_URL} | |
| ## API Changes | |
| {Brief summary of what changed in the API — new props, removed props, type changes, etc.} | |
| ## Stale Documentation Found | |
| ### High Confidence | |
| | File | Line(s) | Issue | API Change | | |
| |---|---|---|---| | |
| {rows or "None found"} | |
| ### Medium Confidence | |
| | File | Line(s) | Issue | API Change | | |
| |---|---|---|---| | |
| {rows or "None found"} | |
| ### Low Confidence | |
| | File | Line(s) | Issue | API Change | | |
| |---|---|---|---| | |
| {rows or "None found"} | |
| ## Recommended Actions | |
| {Bulleted list of specific things to fix} | |
| ``` | |
| ## Rules | |
| - Open at most ONE issue per run. Group everything into one issue. | |
| - Do NOT create or modify any files. Do NOT create PRs. Issues only. | |
| - Do NOT open an issue if there is nothing stale. | |
| - Before creating an issue, check for existing open issues that have BOTH | |
| `<!-- drift-type:stale-docs -->` and `<!-- trigger-pr:{PR_NUMBER} -->` in their body. | |
| If one exists, skip creation to avoid duplicates. | |
| - Be thorough but efficient — use Grep to find files, then Read only relevant sections. |