-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
chore(docs): auto-replace 9 stale screenshots #17814
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
github-actions
wants to merge
6
commits into
master
Choose a base branch
from
docs/auto-screenshot-update-2026-05-19
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
6dd252b
feat(docs): add automated screenshot pipeline with Playwright
f4b185d
fix(pipeline): add SENTRY_BASE_URL to CI workflow, remove unnecessary…
12976fb
fix: address security and path issues in screenshot pipeline workflow
f39c5bb
fix: skip auth state path in dry-run mode to prevent ENOENT
d708a80
fix: configure git identity in auto-replace for CI environments
63a55d3
chore(docs): auto-replace 9 stale screenshots
github-actions[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| name: Auto-add sentry_ui_url | ||
|
|
||
| # Automatically adds sentry_ui_url to MDX frontmatter when a PR | ||
| # adds or modifies image references in docs pages. This ensures | ||
| # the screenshot pipeline can always find the right Sentry UI page | ||
| # to capture, without writers having to remember a manual step. | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize] | ||
| paths: | ||
| - 'docs/**/*.mdx' | ||
| - 'docs/**/*.md' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| add-screenshot-urls: | ||
| runs-on: ubuntu-latest | ||
| # Don't run on PRs from the screenshot pipeline itself | ||
| if: ${{ !startsWith(github.head_ref, 'docs/auto-screenshot-update') }} | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.head_ref }} | ||
| fetch-depth: 0 | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
|
|
||
| - uses: pnpm/action-setup@v2 | ||
|
|
||
| - name: Install root dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Check for missing sentry_ui_url | ||
| id: check | ||
| run: | | ||
| # Get list of changed MDX files in this PR | ||
| CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR origin/${{ github.base_ref }}...HEAD -- 'docs/**/*.mdx' 'docs/**/*.md') | ||
|
|
||
| if [ -z "$CHANGED_FILES" ]; then | ||
| echo "No changed MDX files found" | ||
| echo "needs_fix=false" >> $GITHUB_OUTPUT | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Check each changed file for images without sentry_ui_url | ||
| MISSING_FILES="" | ||
| for file in $CHANGED_FILES; do | ||
| if [ ! -f "$file" ]; then | ||
| continue | ||
| fi | ||
|
|
||
| # Check if file has image references (skip external URLs) | ||
| HAS_IMAGES=$(grep -cE '!\[[^\]]*\]\([^)]+\.(png|jpg|jpeg|gif|webp)\)' "$file" 2>/dev/null || true) | ||
| if [ "$HAS_IMAGES" -eq "0" ] 2>/dev/null; then | ||
| continue | ||
| fi | ||
|
|
||
| # Check if frontmatter has sentry_ui_url | ||
| HAS_URL=$(head -30 "$file" | grep -c 'sentry_ui_url:' || true) | ||
| if [ "$HAS_URL" -eq "0" ]; then | ||
| MISSING_FILES="$MISSING_FILES $file" | ||
| fi | ||
| done | ||
|
|
||
| if [ -z "$MISSING_FILES" ]; then | ||
| echo "All changed files with images have sentry_ui_url" | ||
| echo "needs_fix=false" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "Files missing sentry_ui_url:$MISSING_FILES" | ||
| echo "needs_fix=true" >> $GITHUB_OUTPUT | ||
| echo "missing_files=$MISSING_FILES" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Install pipeline dependencies | ||
| if: steps.check.outputs.needs_fix == 'true' | ||
| run: npm install | ||
| working-directory: scripts/screenshot-pipeline | ||
|
|
||
| - name: Run auto-map and inject | ||
| if: steps.check.outputs.needs_fix == 'true' | ||
| run: | | ||
| # Run the crawler to build manifest | ||
| npx ts-node src/crawl-inventory.ts --scope docs/product | ||
| # Run auto-mapper | ||
| npx ts-node tools/auto-map-urls.ts | ||
| # Inject URLs into frontmatter | ||
| npx ts-node tools/inject-frontmatter-urls.ts | ||
| working-directory: scripts/screenshot-pipeline | ||
| env: | ||
| UI_REFRESH_CUTOFF: '2025-06-01' | ||
|
|
||
| - name: Commit changes | ||
| if: steps.check.outputs.needs_fix == 'true' | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| # Only commit the MDX files that were changed (not pipeline output) | ||
| git add 'docs/**/*.mdx' 'docs/**/*.md' | ||
|
|
||
| # Check if there are actual changes | ||
| if git diff --cached --quiet; then | ||
| echo "No frontmatter changes to commit" | ||
| else | ||
| git commit -m "chore(docs): auto-add sentry_ui_url to screenshot pages" | ||
| git push | ||
| echo "Committed sentry_ui_url additions" | ||
| fi | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| name: Screenshot Pipeline | ||
|
|
||
| # Automated screenshot capture, diff, and replacement pipeline. | ||
| # Detects stale screenshots and Arcade embeds, auto-replaces high-confidence | ||
| # diffs, and creates Linear issues for items requiring manual review. | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 6 * * 1' # Weekly on Monday at 6am UTC | ||
| workflow_dispatch: # Manual trigger | ||
| inputs: | ||
| scope: | ||
| description: 'Limit crawl to a specific directory (e.g., docs/product/issues)' | ||
| required: false | ||
| type: string | ||
| dry_run: | ||
| description: 'Dry run mode (no file changes, no PRs, no Linear issues)' | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| diff_threshold_low: | ||
| description: 'Min diff % to consider changed (default: 0.01 = 1%)' | ||
| required: false | ||
| type: string | ||
| default: '0.01' | ||
| diff_threshold_high: | ||
| description: 'Max diff % before flagging as suspicious (default: 0.50 = 50%)' | ||
| required: false | ||
| type: string | ||
| default: '0.50' | ||
|
|
||
| jobs: | ||
| screenshot-pipeline: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history for git log queries | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
|
|
||
| - name: Install pipeline dependencies | ||
| run: npm install | ||
| working-directory: scripts/screenshot-pipeline | ||
|
|
||
| - name: Install Playwright browsers | ||
| run: npx playwright install --with-deps chromium | ||
| working-directory: scripts/screenshot-pipeline | ||
|
|
||
| - name: Restore auth state | ||
| if: ${{ !inputs.dry_run }} | ||
| run: | | ||
| echo "$SENTRY_STORAGE_STATE" | base64 -d > /tmp/storageState.json | ||
| env: | ||
| SENTRY_STORAGE_STATE: ${{ secrets.SENTRY_STORAGE_STATE }} | ||
|
|
||
| - name: Validate scope input | ||
| if: ${{ inputs.scope != '' }} | ||
| run: | | ||
| # Validate scope is a safe directory path (alphanumeric, hyphens, slashes, dots only) | ||
| if ! echo "$PIPELINE_SCOPE" | grep -qE '^[a-zA-Z0-9/_.-]+$'; then | ||
| echo "Error: Invalid scope input. Must be a directory path (e.g., docs/product/issues)" | ||
| exit 1 | ||
| fi | ||
| env: | ||
| PIPELINE_SCOPE: ${{ inputs.scope }} | ||
|
|
||
| - name: Run inventory crawler | ||
| run: | | ||
| SCOPE_ARGS=() | ||
| if [ -n "$PIPELINE_SCOPE" ]; then | ||
| SCOPE_ARGS=(--scope "$PIPELINE_SCOPE") | ||
| fi | ||
| npx ts-node src/crawl-inventory.ts "${SCOPE_ARGS[@]}" | ||
| working-directory: scripts/screenshot-pipeline | ||
| env: | ||
| UI_REFRESH_CUTOFF: '2025-06-01' | ||
| PIPELINE_SCOPE: ${{ inputs.scope }} | ||
|
|
||
| - name: Run screenshot capture & diff | ||
| run: | | ||
| DRY_RUN_ARGS=() | ||
| if [ "$PIPELINE_DRY_RUN" = "true" ]; then | ||
| DRY_RUN_ARGS=(--dry-run) | ||
| fi | ||
| npx ts-node src/capture-and-diff.ts "${DRY_RUN_ARGS[@]}" | ||
| working-directory: scripts/screenshot-pipeline | ||
| env: | ||
| SENTRY_STORAGE_STATE_PATH: ${{ inputs.dry_run && '' || '/tmp/storageState.json' }} | ||
| SENTRY_ORG_SLUG: ${{ secrets.SENTRY_ORG_SLUG }} | ||
| SENTRY_BASE_URL: ${{ secrets.SENTRY_BASE_URL }} | ||
| DIFF_THRESHOLD_LOW: ${{ inputs.diff_threshold_low || '0.01' }} | ||
| DIFF_THRESHOLD_HIGH: ${{ inputs.diff_threshold_high || '0.50' }} | ||
| PIPELINE_DRY_RUN: ${{ inputs.dry_run }} | ||
|
|
||
| - name: Auto-replace and open PR | ||
| if: ${{ !inputs.dry_run }} | ||
| run: npx ts-node src/auto-replace.ts | ||
| working-directory: scripts/screenshot-pipeline | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Create Linear issues | ||
| if: ${{ !inputs.dry_run }} | ||
| run: npx ts-node src/create-linear-issues.ts | ||
| working-directory: scripts/screenshot-pipeline | ||
| env: | ||
| LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }} | ||
| LINEAR_TEAM_ID: ${{ vars.LINEAR_TEAM_ID }} | ||
| SENTRY_BASE_URL: ${{ secrets.SENTRY_BASE_URL }} | ||
|
|
||
| - name: Upload pipeline artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: screenshot-pipeline-output | ||
| path: scripts/screenshot-pipeline/output/ | ||
| retention-days: 30 | ||
|
|
||
| - name: Write job summary | ||
| if: always() | ||
| run: | | ||
| echo "## Screenshot Pipeline Results" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| if [ -f scripts/screenshot-pipeline/output/inventory-manifest.json ]; then | ||
| TOTAL=$(jq length scripts/screenshot-pipeline/output/inventory-manifest.json) | ||
| STALE=$(jq '[.[] | select(.is_stale == true)] | length' scripts/screenshot-pipeline/output/inventory-manifest.json) | ||
| echo "**Inventory:** ${TOTAL} total assets, ${STALE} stale" >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
|
|
||
| if [ -f scripts/screenshot-pipeline/output/diff-results.json ]; then | ||
| CAPTURED=$(jq length scripts/screenshot-pipeline/output/diff-results.json) | ||
| AUTO=$(jq '[.[] | select(.status == "auto_replace")] | length' scripts/screenshot-pipeline/output/diff-results.json) | ||
| REVIEW=$(jq '[.[] | select(.status == "needs_review")] | length' scripts/screenshot-pipeline/output/diff-results.json) | ||
| FAILED=$(jq '[.[] | select(.status == "capture_failed")] | length' scripts/screenshot-pipeline/output/diff-results.json) | ||
| echo "**Captures:** ${CAPTURED} processed" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Auto-replace: ${AUTO}" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Needs review: ${REVIEW}" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Capture failed: ${FAILED}" >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
|
|
||
| if [ -f scripts/screenshot-pipeline/output/linear-issues.json ]; then | ||
| CREATED=$(jq '[.[] | select(.isNew == true)] | length' scripts/screenshot-pipeline/output/linear-issues.json) | ||
| echo "**Linear issues created:** ${CREATED}" >> $GITHUB_STEP_SUMMARY | ||
| fi |
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR workflow commits unrelated docs
High Severity
The frontmatter workflow injects URLs from a broad
docs/productcrawl, then stages everydocs/**/*.mdxchange. A PR that touches one page can get unrelatedsentry_ui_urlcommits pushed to the contributor’s branch.Reviewed by Cursor Bugbot for commit 63a55d3. Configure here.