Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions .github/workflows/screenshot-frontmatter.yml
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'
Copy link
Copy Markdown
Contributor

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/product crawl, then stages every docs/**/*.mdx change. A PR that touches one page can get unrelated sentry_ui_url commits pushed to the contributor’s branch.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 63a55d3. Configure here.


# 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
152 changes: 152 additions & 0 deletions .github/workflows/screenshot-pipeline.yml
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,7 @@ yalc.lock
.claude/settings.local.json
mise.toml
.yarn/install-state.gz

# Screenshot pipeline output (generated at runtime)
scripts/screenshot-pipeline/output/
scripts/screenshot-pipeline/node_modules/
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ pnpm dev:developer-docs
With that, the repo is fully set up and you are ready to open local docs under http://localhost:3000

`next-env.d.ts` is in `.gitignore` and is generated when you run `pnpm dev` or `pnpm build`. When we upgrade to Next 15.5+, we can run `next typegen` in CI and in `lint:ts` so the file is generated before type-check.

## Screenshots

Docs pages that contain screenshots of the Sentry UI use a `sentry_ui_url` field in their frontmatter. This tells the automated screenshot pipeline which Sentry page to capture when checking for stale images.

```yaml
---
title: Issue Details
sidebar_order: 10
description: Learn how to navigate the Issue Details page.
sentry_ui_url: https://sentry.io/organizations/{org}/issues/
---
```

Use `{org}` as a placeholder for the organization slug. The pipeline replaces it at capture time.

**This field is added automatically.** When you open a PR that adds or modifies images in a docs page, a GitHub Actions workflow will detect the missing field and commit it to your branch. You can also add it manually if you know the URL.

If the auto-detected URL is wrong (e.g., your screenshots show a specific sub-page), update it in the frontmatter and the bot won't overwrite it on future PRs.

See [`scripts/screenshot-pipeline/README.md`](scripts/screenshot-pipeline/README.md) for full pipeline documentation.
1 change: 1 addition & 0 deletions docs/product/dashboards/sentry-dashboards/mobile/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Learn how to use Sentry's Mobile Performance dashboard to monitor the health of
your mobile app, including app starts, screen loads, and screen rendering.
og_image: /og-images/product-insights-mobile.png
sentry_ui_url: https://sentry.io/organizations/{org}/dashboards/
---

The Mobile Dashboard found on [Sentry Dashboards](https://sentry.io/orgredirect/organizations/:orgslug/dashboards/) gives an overview of the metrics that let you know how fast your app starts, including the number of slow and frozen frames your users may be experiencing. Each metric provides insights into the overall performance health of your mobile application. Digging into the details helps prioritize critical performance issues and allows you to identify and troubleshoot the root cause faster.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ description: >-
Loads to get better visibility on your application's TTID and TTFD
performance.
og_image: /og-images/product-insights-mobile-mobile-vitals-screen-loads.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/traces/
---

{/*![Example of Screen Loads](./img/screen-loads.png)*/}
Expand Down
1 change: 1 addition & 0 deletions docs/product/dashboards/widget-builder/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Widget Builder
sidebar_order: 15
description: Learn how to create widgets for your dashboards or edit existing ones.
og_image: /og-images/product-dashboards-widget-builder.png
sentry_ui_url: https://sentry.io/organizations/{org}/dashboards/new/
---

When adding a widget or editing an existing one, a side panel opens up where you can see the dashboard widget builder.
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/discover-queries/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Discover is a powerful query engine that allows you to query all your metadata
across projects and environments to unlock insights.
og_image: /og-images/product-explore-discover-queries.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/discover/homepage/
---

The Discover homepage displays the query builder where you can immediately begin creating a new query. By default, the page shows the pre-built "All Events" query, but you can customize the homepage and [set the custom version as your default](#set-as-default). To navigate back to the query management page, where you can find [pre-built](#pre-built-queries) and [saved](#saved-queries) queries, click the "Saved Queries" button.
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/discover-queries/query-builder.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Learn how to use Discover to build a query, filter your data, and group
results.
og_image: /og-images/product-explore-discover-queries-query-builder.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/discover/homepage/
---

<Include name="feature-available-for-plan-trial-business.mdx" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Learn how to write query equations that perform operations using your query
columns.
og_image: /og-images/product-explore-discover-queries-query-builder-query-equations.gif
sentry_ui_url: https://sentry.io/organizations/{org}/explore/discover/homepage/
---

<Include name="feature-available-for-plan-trial-business.mdx" />
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/discover-queries/uncover-trends.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Learn how to work with the data in Discover to gain useful insights into the
health and stability of your applications.
og_image: /og-images/product-explore-discover-queries-uncover-trends.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/discover/homepage/
---

<Include name="feature-available-for-plan-trial-business.mdx" />
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/logs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ description: >-
Structured logs allow you to send, view and query logs and parameters sent
from your applications within Sentry.
og_image: /og-images/product-explore-logs.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/logs/
---


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Differential Flame Graphs
sidebar_order: 110
description: Learn how to use and interpret differential flame graphs.
og_image: /og-images/product-explore-profiling-differential-flamegraphs.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/profiling/
---

There are multiple ways to visualize and use profiling data, including differential flame graphs, which can help easily identify function regressions or changes in the execution context.
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/profiling/flame-charts-graphs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Flame Graphs and Aggregated Flame Graphs
sidebar_order: 100
description: Learn more about how to interpret flame graphs and aggregated flame graphs.
og_image: /og-images/product-explore-profiling-flame-charts-graphs.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/profiling/
---

Profiling data can be used to gain insight into what methods and lines of your code are slow. But getting this type of insight requires an understanding of how profiling data is represented and visualized. Sentry uses both flame graphs and aggregated flame graphs to visualize profile data. We'll explain how to read them below.
Expand Down
1 change: 1 addition & 0 deletions docs/product/explore/profiling/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ description: >-
removing the need for custom instrumentation and enabling precise code-level
visibility into your application in a production environment.
og_image: /og-images/product-explore-profiling.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/profiling/
---

Sentry’s Profiling products provide precise, code-level visibility into application execution in a production environment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ description: >-
contextualize the work your mobile app does and detect possible issues
impacting performance.
og_image: /og-images/product-explore-profiling-mobile-app-profiling-metrics.png
sentry_ui_url: https://sentry.io/organizations/{org}/explore/profiling/
---

The Sentry profiler records several system measurements to help analyze the backtraces it gathers. Some, like CPU and heap usage, are taken on a regular sampling interval using functions from `mach/mach.h`, albeit with a lower frequency than backtrace sampling. Others, like GPU information, are taken from `CADisplayLink` callback invocations, as they're received.
Expand Down
Loading