Add QR codes to deploy preview links in PR comments#1530
Conversation
Deploy previewhttps://deploy-preview-1530--mui-internal.netlify.app/ Bundle sizeTotal Size Change: 0B(0.00%) - Total Gzip Change: 0B(0.00%) Show details for 63 more bundles@mui/internal-docs-infra/abstractCreateDemo parsed: 0B(0.00%) gzip: 0B(0.00%) PerformanceTotal duration: 18.73 ms +1.79 ms(+10.5%) | Renders: 4 (+0) | Paint: 76.12 ms +0.98 ms(+1.3%)
2 tests within noise — details Check out the code infra dashboard for more information about this PR. |
There was a problem hiding this comment.
Pull request overview
Adds signed, cacheable QR codes for deploy preview links in the CI PR comment generated by the code-infra dashboard, making it easier to open preview pages on mobile while keeping the endpoint from becoming a general-purpose QR generator.
Changes:
- Introduces
/api/qr-code?url=...&sig=...that verifies an HMAC signature and returns an SVG QR code with long-term caching headers. - Updates deploy preview report output to wrap preview/doc links in a collapsible
<details>block that includes the QR image (with plain-link fallback whenQR_CODE_SECRETis unset). - Fixes doc preview link construction to avoid double slashes by using
new URL(docPath, previewUrl).
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
render.yaml |
Adds QR_CODE_SECRET env var generation for dashboard deployments. |
apps/code-infra-dashboard/package.json |
Adds qrcode + @types/qrcode dependencies for SVG generation. |
pnpm-lock.yaml |
Locks the new QR code dependencies and transitive graph. |
apps/code-infra-dashboard/src/lib/qrCode.ts |
Implements signing/verifying and SVG QR rendering helpers. |
apps/code-infra-dashboard/src/lib/qrCode.test.ts |
Unit tests for signing, verification behavior, and SVG generation. |
apps/code-infra-dashboard/src/lib/ciReports/deployPreviewReport.ts |
Wraps deploy preview links in collapsible QR blocks; fixes doc URL joining. |
apps/code-infra-dashboard/src/lib/ciReports/deployPreviewReport.test.ts |
Tests QR-wrapped output, signed URL embedding, and fallback behavior. |
apps/code-infra-dashboard/app/api/qr-code/route.ts |
New signed QR code endpoint with caching + security headers. |
apps/code-infra-dashboard/app/api/qr-code/route.test.ts |
Route tests for success + error paths (missing params, invalid sig, non-https, etc.). |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| /** | ||
| * Formats a link with a collapsible QR code for opening it on a phone. | ||
| * Falls back to a plain markdown link when no signing key is configured. | ||
| * Single-line HTML so it renders correctly inside markdown list items. | ||
| */ | ||
| function formatLinkWithQr(label: string, url: string): string { | ||
| const qrCodeUrl = signQrCodeUrl(url); | ||
| if (!qrCodeUrl) { | ||
| return `[${label}](${url})`; | ||
| } | ||
| return `<details><summary><a href="${url}">${label}</a></summary><img src="${qrCodeUrl}" width="150" alt="QR code for ${label}"></details>`; | ||
| } |
| const url = request.nextUrl.searchParams.get('url'); | ||
| const signature = request.nextUrl.searchParams.get('sig'); | ||
|
|
||
| if (!url || !signature) { | ||
| return errorResponse('Missing url or sig query parameter', 400); | ||
| } | ||
|
|
||
| if (url.length > QR_CODE_MAX_URL_LENGTH) { | ||
| return errorResponse('url query parameter is too long', 400); | ||
| } |
Closes #261. Revives mui/material-ui#45078, now that the PR comment is generated by the dashboard.
Adds a
GET /api/qr-code?url=...&sig=...endpoint to the code-infra-dashboard and wraps each deploy preview link in the PR comment in a collapsible QR code, for opening preview pages on a phone.QR_CODE_SECRET, generated by Render (generateValue: true), so it can be rotated independently of other app secrets.Cache-Control: public, max-age=31536000, immutable. GitHub proxies comment images through camo, which caches based on these headers, so repeat views never hit the server. Error responses areno-store.Land a small quiet zone — ~1.4 kB raw, a few hundred bytes gzipped, crisp at any scale.Without
QR_CODE_SECRETconfigured (e.g. local dev), the report falls back to plain links and the endpoint returns 503.Also fixes doc preview links being joined with a double slash (
netlify.app//material-ui/...) by constructing them withnew URL().