From 87c010708147d4d379df6500124f64a8993aeb7b Mon Sep 17 00:00:00 2001 From: abdellah hariti Date: Tue, 16 Jul 2024 10:27:03 +0100 Subject: [PATCH] feat: Use next.config.js dynamic redirects (#10722) --- .gitignore | 4 - docs/contributing/pages/redirects.mdx | 28 +- next.config.js | 3 + package.json | 12 +- redirects.js | 482 ++++++++++++++++++++++++++ scripts/make-vercel-json.mjs | 31 -- scripts/no-vercel-json-redirects.mjs | 8 + sdk-docs-vercel-json-redirects.json | 441 ----------------------- skip-build.sh | 7 +- src/components/search/index.tsx | 4 +- base-vercel.json => vercel.json | 0 11 files changed, 525 insertions(+), 495 deletions(-) create mode 100644 redirects.js delete mode 100644 scripts/make-vercel-json.mjs create mode 100644 scripts/no-vercel-json-redirects.mjs delete mode 100644 sdk-docs-vercel-json-redirects.json rename base-vercel.json => vercel.json (100%) diff --git a/.gitignore b/.gitignore index 08e2cbbe68ea4..5e9d599ef29ba 100644 --- a/.gitignore +++ b/.gitignore @@ -95,7 +95,3 @@ public/page-data tsconfig.tsbuildinfo public/mdx-images/* - -# the vercel.json should be generated by the ./scripts/make-vercel-json.mjs script -# to differentiate between SDK docs and developer docs redirects -vercel.json diff --git a/docs/contributing/pages/redirects.mdx b/docs/contributing/pages/redirects.mdx index 18fa65ff7baca..a2f91550dd058 100644 --- a/docs/contributing/pages/redirects.mdx +++ b/docs/contributing/pages/redirects.mdx @@ -10,9 +10,17 @@ Redirects allow you to automatically redirect an incoming request path to a new There are two ways to add redirects in the Sentry docs: - [Add a New Redirect in `middleware.ts` (Recommended)](#add-a-new-redirect-in-middlewarets-recommended) -- [Add a New Redirect in `vercel.json`](#add-a-new-redirect-in-verceljson) +- [Add a New Redirect in `redirects.js`](#example-redirect-in-redirectsjs) -Because Sentry has a limited number of Vercel redirects, you should configure your redirects in `middleware.ts` whenever possible. You should only use `vercel.json` if you need to use regular expressions in your redirects. + + Both files make the distinction between SDK docs (ie. end user docs) and developer docs. + + +Because Sentry has a limited number of `next.config.js` redirects, you should configure your redirects in `middleware.ts` whenever possible. You should only use `redirects.js` ie (`next.config.js`) if you need to use regular expressions and wildcard path segments in your redirects. + + + It's no longer recommended to use `vercel.json` for redirects due to its limitations (doesn't work on localhost, requires a static file ...) + ### Add a New Redirect in `middleware.ts` (Recommended) @@ -36,24 +44,26 @@ const REDIRECTS: {from: PathWithTrailingSlash; to: string}[] = [ ]; ``` -### Add a New Redirect in `vercel.json` +### Add a New Redirect in `redirects.js` Sentry has a limited number of Vercel redirects, so you should only configure redirects in `vercel.json` if your redirects need to use regular expressions. Otherwise, use [`middleware.ts`](#add-a-new-redirect-in-middlewarets-recommended). -To add a new redirect in [`vercel.json`](https://github.com/getsentry/sentry-docs/blob/master/vercel.json#L34), add a new object in `redirects` with the following properties: +To add a new redirect in `redirects.js` (which is consumed by `next.config.js`'s [`redirects`](https://nextjs.org/docs/app/api-reference/next-config-js/redirects)), add a new object to the corresponding redirects with the following properties: - `source`: The incoming request path pattern. - `destination`: The new destination path you want to route to. -#### Example Redirect in `vercel.json` +#### Example Redirect in `redirects.js` + +The example below redirects URLs like `https://docs.sentry.io/cli/:path*` to `https://docs.sentry.io/product/cli/:path*` with a [path pattern](https://nextjs.org/docs/app/api-reference/next-config-js/redirects#path-matching) or a [Regex](https://nextjs.org/docs/app/api-reference/next-config-js/redirects#regex-path-matching). -The example below redirects URLs like `https://docs.sentry.io/cli/(.*)` to `https://docs.sentry.io/product/cli/$1` with a matching regex pattern. For example, `https://docs.sentry.io/cli/installation/` would be redirected to `https://docs.sentry.io/product/cli/installation/`. +For example, `https://docs.sentry.io/cli/installation/` would be redirected to `https://docs.sentry.io/product/cli/installation/`. -```json {filename:vercel.json} +```json {filename:redirects.js} "redirects": [ { - "source": "/cli/(.*)", - "destination": "/product/cli/$1" + "source": "/cli/:path*", + "destination": "/product/cli/:path*", }, ] ``` diff --git a/next.config.js b/next.config.js index 0c6c2f21e4b0a..82736d9edc1dc 100644 --- a/next.config.js +++ b/next.config.js @@ -1,3 +1,5 @@ +const {redirects} = require('./redirects.js'); + const createMDX = require('@next/mdx'); const remarkPrism = require('remark-prism'); const {codecovWebpackPlugin} = require('@codecov/webpack-plugin'); @@ -28,6 +30,7 @@ const nextConfig = { // This is used on middleware DEVELOPER_DOCS_: process.env.NEXT_PUBLIC_DEVELOPER_DOCS, }, + redirects, }; const withMDX = createMDX({ diff --git a/package.json b/package.json index 817d69cbf5a44..3413ccdd5835e 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,10 @@ "url": "https://github.com/getsentry/sentry-docs/issues" }, "scripts": { - "dev": "yarn vercel-json && concurrently \"yarn sidecar\" \"node ./src/hotReloadWatcher.mjs\" \"next dev\"", - "dev:developer-docs": "NEXT_PUBLIC_DEVELOPER_DOCS=1 yarn dev", - "build:developer-docs": "git submodule init && git submodule update && NEXT_PUBLIC_DEVELOPER_DOCS=1 yarn build", - "build": "prisma generate && yarn vercel-json && next build", + "dev": "yarn enforce-redirects && concurrently \"yarn sidecar\" \"node ./src/hotReloadWatcher.mjs\" \"next dev\"", + "dev:developer-docs": "yarn enforce-redirects && NEXT_PUBLIC_DEVELOPER_DOCS=1 yarn dev", + "build:developer-docs": "yarn enforce-redirects && git submodule init && git submodule update && NEXT_PUBLIC_DEVELOPER_DOCS=1 yarn build", + "build": "yarn enforce-redirects && prisma generate && next build", "start": "next start", "migrate:dev": "dotenv -e .env.development -- yarn prisma migrate reset", "lint": "next lint", @@ -26,8 +26,8 @@ "lint:prettier:fix": "prettier --write \"./{src,app,scripts}/**/*.{md,mdx,ts,tsx,js,jsx,mjs}\"", "lint:fix": "yarn run lint:prettier:fix && yarn run lint:eslint:fix", "sidecar": "yarn spotlight-sidecar", - "vercel-json": "node scripts/make-vercel-json.mjs", - "test": "jest" + "test": "jest", + "enforce-redirects": "node ./scripts/no-vercel-json-redirects.mjs" }, "prisma": { "seed": "node prisma/seed/seed.mjs" diff --git a/redirects.js b/redirects.js new file mode 100644 index 0000000000000..d9547d1ac0901 --- /dev/null +++ b/redirects.js @@ -0,0 +1,482 @@ +const isDeveloperDocs = !!process.env.NEXT_PUBLIC_DEVELOPER_DOCS; + +/** @type {import('next/dist/lib/load-custom-routes').Redirect[]} */ +const developerDocsRedirects = [ + { + source: '/sdk/unified-api/tracing/:path*', + destination: '/sdk/performance/:path*', + }, + { + source: '/onpremise/:path*', + destination: '/self-hosted/:path*', + }, + { + source: '/self-hosted/mail/:path*', + destination: '/self-hosted/email/:path*', + }, + { + source: '/processing-tickets(/?)', + destination: 'https://open.sentry.io/triage/', + }, +]; + +/** @type {import('next/dist/lib/load-custom-routes').Redirect[]} */ +const userDocsRedirects = [ + { + source: '/internal/:path*', + destination: 'https://develop.sentry.dev', + }, + { + source: '/development/(contribute|server)/:path*', + destination: 'https://develop.sentry.dev', + }, + { + source: '/development/sdk-dev/:path*', + destination: 'https://develop.sentry.dev', + }, + { + source: '/client-dev/:path*', + destination: 'https://develop.sentry.dev/sdk/', + }, + { + source: '/clientdev/:path*', + destination: 'https://develop.sentry.dev/sdk/', + }, + { + source: '/server/config/:path*', + destination: 'https://develop.sentry.dev/config/', + }, + { + source: '/server/queue/:path*', + destination: 'https://develop.sentry.dev/services/queue/', + }, + { + source: '/server/:path*', + destination: 'https://develop.sentry.dev/self-hosted/', + }, + { + source: '/meta/relay/:path*', + destination: '/product/relay/:path*', + }, + { + source: '/meta/:path*', + destination: '/product/security/:path*', + }, + { + source: '/:type(hosted|on-premise)/:path*', + destination: '/:path*', + }, + { + source: '/error-reporting/:path*', + destination: '/platform-redirect/', + }, + { + source: '/product/cli/:path*', + destination: '/cli/:path*', + }, + { + source: '/product/reference/:path*', + destination: '/concepts/:path*', + }, + { + source: '/product/sentry-basics/concepts/:path*', + destination: '/concepts/key-terms/:path*', + }, + { + source: '/product/security/:path*', + destination: '/security-legal-pii/security/:path*', + }, + { + source: '/product/data-management-settings/scrubbing/:path*', + destination: '/security-legal-pii/scrubbing/:path*', + }, + { + source: '/product/data-management-settings/:path*', + destination: '/concepts/data-management/:path*', + }, + { + source: '/data-management/:path*', + destination: '/concepts/data-management/', + }, + { + source: '/product/integrations/:path*', + destination: '/organization/integrations/:path*', + }, + { + source: '/product/accounts/:path*', + destination: '/account/:path*', + }, + { + source: '/accounts/:path*', + destination: '/account/:path*', + }, + { + source: '/accounts/pricing/:path*', + destination: '/pricing/:path*', + }, + { + source: '/account/pricing/:path*', + destination: '/pricing/:path*', + }, + { + source: '/account/sso/:path*', + destination: '/organization/authentication/sso/:path*', + }, + { + source: '/account/quotas/:path*', + destination: '/pricing/quotas/:path*', + }, + { + source: '/account/migration/:path*', + destination: '/concepts/migration/:path*', + }, + { + source: '/organization/quotas/:path*', + destination: '/pricing/quotas/:path*', + }, + { + source: '/platforms/cocoa/:path*', + destination: '/platforms/apple/:path*', + }, + { + source: '/platforms/unrealengine/:path*', + destination: '/platforms/unreal/:path*', + }, + { + source: '/platforms/node/guides/:path*', + destination: '/platforms/javascript/guides/:path*', + }, + { + source: '/platforms/node/:path*', + destination: '/platforms/javascript/guides/node/:path*', + }, + { + source: '/platforms/:platform/configuration/capture/:path*', + destination: '/platforms/:platform/usage/', + }, + { + source: '/platforms/:platform/guides/:guide/configuration/capture/:path*', + destination: '/platforms/:platform/guides/:guide/usage/', + }, + { + source: '/platforms/:platform/configuration/install-cdn/:path*', + destination: '/platforms/:platform/install/loader/', + }, + { + source: '/platforms/:platform/enriching-error-data/set-level/:path*', + destination: '/platforms/:platform/usage/set-level/', + }, + { + source: '/platforms/:platform/guides/:guide/enriching-error-data/set-level/:path*', + destination: '/platforms/:platform/guides/:guide/usage/set-level/', + }, + { + source: + '/platforms/:platform/enriching-error-data/additional-data/manage-context/:path*', + destination: '/platforms/:platform/enriching-events/context/', + }, + { + source: + '/platforms/:platform/guides/:guide/enriching-error-data/additional-data/manage-context/:path*', + destination: '/platforms/:platform/guides/:guide/enriching-events/context/', + }, + { + source: + '/platforms/:platform/enriching-error-data/additional-data/adding-tags/:path*', + destination: '/platforms/:platform/enriching-events/tags/', + }, + { + source: '/platforms/:platform/enriching-error-data/additional-data/:path*', + destination: '/platforms/:platform/enriching-events/:path*', + }, + { + source: + '/platforms/:platform/guides/:guide/enriching-error-data/additional-data/:path*', + destination: '/platforms/:platform/guides/:guide/enriching-events/:path*', + }, + { + source: '/platforms/:platform/enriching-error-data/:path*', + destination: '/platforms/:platform/enriching-events/:path*', + }, + { + source: '/platforms/:platform/guides/:guide/enriching-error-data/:path*', + destination: '/platforms/:platform/guides/:guide/enriching-events/:path*', + }, + { + source: '/enriching-error-data/:path*', + destination: '/platforms/javascript/enriching-events/:path*', + }, + { + source: '/platforms/javascript/guides/:guide/integrations/default/', + destination: '/platforms/javascript/guides/:guide/configuration/integrations/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/integrations/default/', + destination: '/platforms/javascript/guides/:guide/configuration/integrations/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/integrations/plugin/', + destination: '/platforms/javascript/guides/:guide/configuration/integrations/', + }, + { + source: '/platforms/javascript/guides/:guide/config/', + destination: '/platforms/javascript/guides/:guide/configuration/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/sourcemaps/', + destination: '/platforms/javascript/guides/:guide/sourcemaps/', + }, + { + source: '/platforms/javascript/guides/:guide/integrations/plugin/', + destination: '/platforms/javascript/guides/:guide/configuration/integrations/plugin/', + }, + { + source: '/platforms/:platform/context/', + destination: '/platforms/:platform/enriching-events/context/', + }, + { + source: '/platforms/:platform/data-management/advanced-datascrubbing/', + destination: '/platforms/:platform/data-management/sensitive-data/', + }, + { + source: '/platforms/:platform/data-management/data-forwarding/', + destination: '/concepts/data-management/data-forwarding/', + }, + { + source: '/platforms/:platform/data-management/event-grouping/', + destination: '/concepts/data-management/event-grouping/', + }, + { + source: '/platforms/:platform/data-management/event-grouping/sdk-fingerprinting/', + destination: '/concepts/data-management/event-grouping/fingerprint-rules/', + }, + { + source: '/platforms/:platform/data-management/server-side-scrubbing/', + destination: '/platforms/:platform/data-management/sensitive-data/', + }, + { + source: + '/platforms/:platform/guides/:guide/data-management/event-grouping/fingerprint-rules/', + destination: '/concepts/data-management/event-grouping/fingerprint-rules/', + }, + { + source: '/platforms/:platform/data-management/sensitive-data/advanced-datascrubbing/', + destination: '/platforms/:platform/data-management/sensitive-data/', + }, + { + source: '/platforms/dotnet/guides/:guide/compatibility/', + destination: '/platforms/dotnet/guides/:guide/', + }, + { + source: '/platforms/javascript/guides/:guide/sourcemaps/uploading/multiple-origins/', + destination: + '/platforms/javascript/guides/:guide/sourcemaps/troubleshooting_js/#multiple-origins', + }, + { + source: '/platforms/python/configuration/integrations/:integration/', + destination: '/platforms/python/integrations/:integration/', + }, + { + source: '/platforms/python/guides/:guide/configuration/integrations/:integration/', + destination: '/platforms/python/integrations/:integration/', + }, + { + source: '/platforms/python/guides/:guide/', + destination: '/platforms/python/integrations/:guide', + }, + { + source: '/platforms/python/guides/:guide/:path*', + destination: '/platforms/python/:path*', + }, + { + source: '/platforms/php/guides/laravel/other-versions/laravel8-10/usage/:path*', + destination: '/platforms/php/guides/laravel/usage/:path*', + }, + { + source: + '/platforms/php/guides/laravel/other-versions/laravel8-10/configuration/:path*', + destination: '/platforms/php/guides/laravel/configuration/:path*', + }, + { + source: + '/platforms/javascript/guides/:guide/sourcemaps/troubleshooting_js/uploading-without-debug-ids/', + destination: '/platforms/javascript/guides/:guide/sourcemaps/troubleshooting_js/', + }, + { + source: '/platforms/javascript/guides/:guide/sourcemaps/hosting-publicly/', + destination: + '/platforms/javascript/guides/:guide/sourcemaps/uploading/hosting-publicly', + }, + { + source: + '/platforms/:platform/sourcemaps/:section(generating|validating|best-practices|artifact-and-release-bundles|)/', + destination: '/platforms/:platform/sourcemaps/', + }, + { + source: + '/platforms/:platform/guides/:guide/sourcemaps/:section(generating|validating|best-practices|artifact-and-release-bundles)/', + destination: '/platforms/:platform/guides/:guide/sourcemaps/', + }, + { + source: '/platforms/minidump/crashpad/:path*', + destination: '/platforms/native/guides/crashpad/:path*', + }, + { + source: '/platforms/minidump/breakpad/:path*', + destination: '/platforms/native/guides/breakpad/:path*', + }, + { + source: '/platforms/:platform/performance/troubleshooting-performance/', + destination: '/platforms/:platform/tracing/troubleshooting/', + }, + { + source: '/platforms/:platform/performance/troubleshooting/', + destination: '/platforms/:platform/tracing/troubleshooting/', + }, + { + source: '/platforms/:platform/guides/:guide/performance/troubleshooting-performance/', + destination: '/platforms/:platform/guides/:guide/tracing/troubleshooting/', + }, + { + source: '/platforms/:platform/guides/:guide/performance/troubleshooting/', + destination: '/platforms/:platform/guides/:guide/tracing/troubleshooting/', + }, + { + source: '/platforms/:platform/performance/connect-services/', + destination: '/platforms/:platform/tracing/trace-propagation/', + }, + { + source: '/platforms/:platform/guides/:guide/performance/connect-services/', + destination: '/platforms/:platform/guides/:guide/tracing/trace-propagation/', + }, + { + source: '/platforms/:platform/usage/distributed-tracing/', + destination: '/platforms/:platform/tracing/trace-propagation/', + }, + { + source: '/platforms/:platform/guides/:guide/usage/distributed-tracing/:path*', + destination: '/platforms/:platform/guides/:guide/tracing/trace-propagation/:path*', + }, + { + source: '/platforms/:platform/distributed-tracing/:path*', + destination: '/platforms/:platform/tracing/trace-propagation/:path*', + }, + { + source: '/platforms/:platform/guides/:guide/distributed-tracing/:path*', + destination: '/platforms/:platform/guides/:guide/tracing/trace-propagation/:path*', + }, + { + source: '/platforms/python/guides/asgi/:path*', + destination: '/platforms/python/configuration/integrations/asgi/', + }, + { + source: '/platforms/python/guides/wsgi/:path*', + destination: '/platforms/python/configuration/integrations/wsgi/', + }, + { + source: '/platforms/:platform/performance/sampling/', + destination: '/platforms/:platform/tracing/', + }, + { + source: '/platforms/:platform/guides/:guide/performance/sampling/', + destination: '/platforms/:platform/guides/:guide/tracing/', + }, + { + source: '/platforms/:platform/performance/:path*', + destination: '/platforms/:platform/tracing/:path*', + }, + { + source: '/platforms/:platform/guides/:guide/performance/:path*', + destination: '/platforms/:platform/guides/:guide/tracing/:path*', + }, + { + source: '/platforms/java/configuration/integrations/:integration/', + destination: '/platforms/java/integrations/:integration/', + }, + { + source: '/platforms/java/guides/:guide/configuration/integrations/:integration/', + destination: '/platforms/java/guides/:guide/integrations/:integration/', + }, + { + source: '/platforms/apple/configuration/integrations/:integration/', + destination: '/platforms/apple/integrations/:integration/', + }, + { + source: '/platforms/apple/guides/:guide/configuration/integrations/', + destination: '/platforms/apple/guides/:guide/integrations/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/micro-frontend-support/', + destination: '/platforms/javascript/guides/:guide/best-practices/micro-frontends/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/sentry-testkit/', + destination: '/platforms/javascript/guides/:guide/best-practices/sentry-testkit/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/webworkers/', + destination: '/platforms/javascript/guides/:guide/best-practices/web-workers/', + }, + { + source: '/platforms/apple/guides/:guide/configuration/integrations/:integration/', + destination: '/platforms/apple/guides/:guide/integrations/:integration/', + }, + { + source: '/platforms/:platform/crons/troubleshooting-crons/', + destination: '/platforms/:platform/crons/troubleshooting/', + }, + { + source: '/platforms/:platform/guides/:guide/crons/troubleshooting-crons/', + destination: '/platforms/:platform/guides/:guide/crons/troubleshooting/', + }, + { + source: '/platforms/:platform/guides/:guide/enriching-events/user-feedback/', + destination: '/platforms/:platform/guides/:guide/user-feedback/', + }, + { + source: '/platforms/:platform/enriching-events/user-feedback/', + destination: '/platforms/:platform/user-feedback/', + }, + { + source: '/product/metrics/:path*', + destination: '/product/explore/metrics/:path*', + }, + { + source: '/product/profiling/:path*', + destination: '/product/explore/profiling/:path*', + }, + { + source: '/product/discover-queries/:path*', + destination: '/product/explore/discover-queries/:path*', + }, + { + source: '/product/session-replay/:path*', + destination: '/product/explore/session-replay/:path*', + }, + { + source: '/platforms/javascript/best-practices/browser-extensions/', + destination: '/platforms/javascript/best-practices/shared-environments/', + }, + { + source: '/platforms/javascript/guides/:guide/configuration/integrations/trycatch/', + destination: '/platforms/javascript/configuration/integrations/browserapierrors/', + }, +]; + +/** + * @type {import('next').NextConfig['redirects']} + * + * loads the redirects based on the environment variable `NEXT_PUBLIC_DEVELOPER_DOCS` + */ +const redirects = async () => { + console.log( + '🔄 using', + isDeveloperDocs ? 'developer' : 'sdk', + 'docs redirects in next.config.js' + ); + return (isDeveloperDocs ? developerDocsRedirects : userDocsRedirects).map(r => { + return {...r, permanent: true}; + }); +}; + +module.exports = {redirects}; diff --git a/scripts/make-vercel-json.mjs b/scripts/make-vercel-json.mjs deleted file mode 100644 index 2b3b02a86bd4a..0000000000000 --- a/scripts/make-vercel-json.mjs +++ /dev/null @@ -1,31 +0,0 @@ -import {readFileSync, writeFileSync} from 'fs'; - -const isDeveloperDocs = !!process.env.NEXT_PUBLIC_DEVELOPER_DOCS; - -// base config that is common to both the developer and sdk docs -const baseVercelJson = JSON.parse(readFileSync('base-vercel.json', 'utf8')); - -if (baseVercelJson.redirects?.length > 0 || baseVercelJson.rewrites?.length > 0) { - throw new Error( - '🔴 base-vercel.json should not have any redirects or rewrites.\n' + - 'Please add them to sdk-docs-vercel-json-redirects.json or developer-docs-vercel-json-redirects.json file.' - ); -} - -// sdk docs redirects -const sdkDocsRedirects = JSON.parse( - readFileSync('sdk-docs-vercel-json-redirects.json', 'utf8') -); - -// TODO: read the developer docs redirects from a file when it's available -const developerDocsRedirects = {}; - -const vercelJson = { - ...baseVercelJson, - ...(isDeveloperDocs ? developerDocsRedirects : sdkDocsRedirects), -}; - -writeFileSync('vercel.json', JSON.stringify(vercelJson, null, 2)); - -// eslint-disable-next-line no-console -console.log(`⚡️ Generated ${isDeveloperDocs ? 'Developer' : 'SDK'} docs vercel.json`); diff --git a/scripts/no-vercel-json-redirects.mjs b/scripts/no-vercel-json-redirects.mjs new file mode 100644 index 0000000000000..4774590f4fa71 --- /dev/null +++ b/scripts/no-vercel-json-redirects.mjs @@ -0,0 +1,8 @@ +import {readFileSync} from 'fs'; +const vercelConfig = JSON.parse(readFileSync('./vercel.json', 'utf8')); + +if (vercelConfig.redirects && vercelConfig.redirects.length > 0) { + throw new Error( + '🔴 ERROR: vercel.json redirects are not recommended.\n 👉 Please add dynamic redirects to redirects.js and static redirects to ./src/middleware.ts' + ); +} diff --git a/sdk-docs-vercel-json-redirects.json b/sdk-docs-vercel-json-redirects.json deleted file mode 100644 index 46af81b784ef2..0000000000000 --- a/sdk-docs-vercel-json-redirects.json +++ /dev/null @@ -1,441 +0,0 @@ -{ - "redirects": [ - { - "source": "/internal/(.*)", - "destination": "https://develop.sentry.dev" - }, - { - "source": "/development/(contribute|server)/(.*)", - "destination": "https://develop.sentry.dev" - }, - { - "source": "/development/sdk-dev/(.*)", - "destination": "https://develop.sentry.dev" - }, - { - "source": "/client-dev/(.*)", - "destination": "https://develop.sentry.dev/sdk/" - }, - { - "source": "/clientdev/(.*)", - "destination": "https://develop.sentry.dev/sdk/" - }, - { - "source": "/server/config(/?)", - "destination": "https://develop.sentry.dev/config/" - }, - { - "source": "/server/queue(/?)", - "destination": "https://develop.sentry.dev/services/queue/" - }, - { - "source": "/server/(.*)", - "destination": "https://develop.sentry.dev/self-hosted/" - }, - { - "source": "/meta/relay/(.*)", - "destination": "/product/relay/$1" - }, - { - "source": "/meta/(.*)", - "destination": "/product/security/$1" - }, - { - "source": "/(hosted|on-premise)/(.*)", - "destination": "/$2" - }, - { - "source": "/error-reporting/(.*)", - "destination": "/platform-redirect/", - "permanent": false - }, - { - "source": "/product/cli/(.*)", - "destination": "/cli/$1" - }, - { - "source": "/product/reference/(.*)", - "destination": "/concepts/$1" - }, - { - "source": "/product/sentry-basics/concepts/(.*)", - "destination": "/concepts/key-terms/$1" - }, - { - "source": "/product/security/(.*)", - "destination": "/security-legal-pii/security/$1" - }, - { - "source": "/product/data-management-settings/scrubbing/(.*)", - "destination": "/security-legal-pii/scrubbing/$1" - }, - { - "source": "/product/data-management-settings/(.*)", - "destination": "/concepts/data-management/$1" - }, - { - "source": "/data-management/(.*)", - "destination": "/concepts/data-management/" - }, - { - "source": "/product/integrations/(.*)", - "destination": "/organization/integrations/$1" - }, - { - "source": "/product/accounts/(.*)", - "destination": "/account/$1" - }, - { - "source": "/accounts/(.*)", - "destination": "/account/$1" - }, - { - "source": "/accounts/pricing/(.*)", - "destination": "/pricing/$1" - }, - { - "source": "/account/pricing/(.*)", - "destination": "/pricing/$1" - }, - { - "source": "/account/sso/(.*)", - "destination": "/organization/authentication/sso/$1" - }, - { - "source": "/account/quotas/(.*)", - "destination": "/pricing/quotas/$1" - }, - { - "source": "/account/migration/(.*)", - "destination": "/concepts/migration/$1" - }, - { - "source": "/organization/quotas/(.*)", - "destination": "/pricing/quotas/$1" - }, - { - "source": "/platforms/cocoa/(.*)", - "destination": "/platforms/apple/$1" - }, - { - "source": "/platforms/unrealengine/(.*)", - "destination": "/platforms/unreal/$1" - }, - { - "source": "/platforms/node/guides/(.*)", - "destination": "/platforms/javascript/guides/$1" - }, - { - "source": "/platforms/node/(.*)", - "destination": "/platforms/javascript/guides/node/$1" - }, - { - "source": "/platforms/([^/]*)/configuration/capture/(.*)", - "destination": "/platforms/$1/usage/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/configuration/capture/(.*)", - "destination": "/platforms/$1/guides/$2/usage/" - }, - { - "source": "/platforms/([^/]*)/configuration/install-cdn/(.*)", - "destination": "/platforms/$1/install/loader/" - }, - { - "source": "/platforms/([^/]*)/enriching-error-data/set-level/(.*)", - "destination": "/platforms/$1/usage/set-level/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-error-data/set-level/(.*)", - "destination": "/platforms/$1/guides/$2/usage/set-level/" - }, - { - "source": "/platforms/([^/]*)/enriching-error-data/additional-data/manage-context/(.*)", - "destination": "/platforms/$1/enriching-events/context/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-error-data/additional-data/manage-context/(.*)", - "destination": "/platforms/$1/guides/$2/enriching-events/context/" - }, - { - "source": "/platforms/([^/]*)/enriching-error-data/additional-data/adding-tags/(.*)", - "destination": "/platforms/$1/enriching-events/tags/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-error-data/additional-data/adding-tags/(.*)", - "destination": "/platforms/$1/guides/$2/enriching-events/tags/" - }, - { - "source": "/platforms/([^/]*)/enriching-error-data/additional-data/(.*)", - "destination": "/platforms/$1/enriching-events/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-error-data/additional-data/(.*)", - "destination": "/platforms/$1/guides/$2/enriching-events/" - }, - { - "source": "/platforms/([^/]*)/enriching-error-data/(.*)", - "destination": "/platforms/$1/enriching-events/$2" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-error-data/(.*)", - "destination": "/platforms/$1/guides/$2/enriching-events/$3" - }, - { - "source": "/enriching-error-data/(.*)", - "destination": "/platforms/javascript/enriching-events/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/integrations/default/", - "destination": "/platforms/javascript/guides/$1/configuration/integrations/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/integrations/default/", - "destination": "/platforms/javascript/guides/$1/configuration/integrations/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/integrations/plugin/", - "destination": "/platforms/javascript/guides/$1/configuration/integrations/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/config/", - "destination": "/platforms/javascript/guides/$1/configuration/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/sourcemaps/", - "destination": "/platforms/javascript/guides/$1/sourcemaps/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/integrations/plugin/", - "destination": "/platforms/javascript/guides/$1/configuration/integrations/plugin/" - }, - { - "source": "/platforms/([^/]*)/context/", - "destination": "/platforms/$1/enriching-events/context/" - }, - { - "source": "/platforms/([^/]*)/data-management/advanced-datascrubbing/", - "destination": "/platforms/$1/data-management/sensitive-data/" - }, - { - "source": "/platforms/([^/]*)/data-management/data-forwarding/", - "destination": "/concepts/data-management/data-forwarding/" - }, - { - "source": "/platforms/([^/]*)/data-management/event-grouping/", - "destination": "/concepts/data-management/event-grouping/" - }, - { - "source": "/platforms/([^/]*)/data-management/event-grouping/sdk-fingerprinting/", - "destination": "/concepts/data-management/event-grouping/fingerprint-rules/" - }, - { - "source": "/platforms/([^/]*)/data-management/server-side-scrubbing/", - "destination": "/platforms/$1/data-management/sensitive-data/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/data-management/event-grouping/fingerprint-rules/", - "destination": "/concepts/data-management/event-grouping/fingerprint-rules/" - }, - { - "source": "/platforms/([^/]*)/data-management/sensitive-data/advanced-datascrubbing/", - "destination": "/platforms/$1/data-management/sensitive-data/" - }, - { - "source": "/platforms/dotnet/guides/([^/]*)/compatibility/", - "destination": "/platforms/dotnet/guides/$1/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/sourcemaps/uploading/multiple-origins/", - "destination": "/platforms/javascript/guides/$1/sourcemaps/troubleshooting_js/#multiple-origins" - }, - { - "source": "/platforms/python/configuration/integrations/([^/]*)/", - "destination": "/platforms/python/integrations/$1/" - }, - { - "source": "/platforms/python/guides/([^/]*)/configuration/integrations/([^/]*)/", - "destination": "/platforms/python/integrations/$2/" - }, - { - "source": "/platforms/python/guides/([^/]*)/", - "destination": "/platforms/python/integrations/$1" - }, - { - "source": "/platforms/python/guides/([^/]*)/(.*)", - "destination": "/platforms/python/$2" - }, - { - "source": "/platforms/php/guides/laravel/other-versions/laravel8-10/usage/(.*)", - "destination": "/platforms/php/guides/laravel/usage/$1" - }, - { - "source": "/platforms/php/guides/laravel/other-versions/laravel8-10/configuration/(.*)", - "destination": "/platforms/php/guides/laravel/configuration/$1" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/sourcemaps/troubleshooting_js/uploading-without-debug-ids/", - "destination": "/platforms/javascript/guides/$1/sourcemaps/troubleshooting_js/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/sourcemaps/hosting-publicly/", - "destination": "/platforms/javascript/guides/$1/sourcemaps/uploading/hosting-publicly" - }, - { - "source": "/platforms/([^/]*)/sourcemaps/(generating|validating|best-practices|artifact-and-release-bundles|)/", - "destination": "/platforms/$1/sourcemaps/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/sourcemaps/(generating|validating|best-practices|artifact-and-release-bundles)/", - "destination": "/platforms/$1/guides/$2/sourcemaps/" - }, - { - "source": "/platforms/minidump/crashpad/([^/]*)/", - "destination": "/platforms/native/guides/crashpad/$1/" - }, - { - "source": "/platforms/minidump/breakpad/([^/]*)/", - "destination": "/platforms/native/guides/breakpad/$1/" - }, - { - "source": "/platforms/([^/]*)/performance/troubleshooting-performance/", - "destination": "/platforms/$1/tracing/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/performance/troubleshooting/", - "destination": "/platforms/$1/tracing/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/performance/troubleshooting-performance/", - "destination": "/platforms/$1/guides/$2/tracing/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/performance/troubleshooting/", - "destination": "/platforms/$1/guides/$2/tracing/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/performance/connect-services/", - "destination": "/platforms/$1/tracing/trace-propagation/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/performance/connect-services/", - "destination": "/platforms/$1/guides/$2/tracing/trace-propagation/" - }, - { - "source": "/platforms/([^/]*)/usage/distributed-tracing/", - "destination": "/platforms/$1/tracing/trace-propagation/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/usage/distributed-tracing/(.*)", - "destination": "/platforms/$1/guides/$2/tracing/trace-propagation/$3" - }, - { - "source": "/platforms/([^/]*)/distributed-tracing/(.*)", - "destination": "/platforms/$1/tracing/trace-propagation/$2" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/distributed-tracing/(.*)", - "destination": "/platforms/$1/guides/$2/tracing/trace-propagation/$3" - }, - { - "source": "/platforms/python/guides/asgi/(.*)", - "destination": "/platforms/python/configuration/integrations/asgi/" - }, - { - "source": "/platforms/python/guides/wsgi/(.*)", - "destination": "/platforms/python/configuration/integrations/wsgi/" - }, - { - "source": "/platforms/([^/]*)/performance/sampling/", - "destination": "/platforms/$1/tracing/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/performance/sampling/", - "destination": "/platforms/$1/guides/$2/tracing/" - }, - { - "source": "/platforms/([^/]*)/performance/(.*)", - "destination": "/platforms/$1/tracing/$2" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/performance/(.*)", - "destination": "/platforms/$1/guides/$2/tracing/$3" - }, - { - "source": "/platforms/java/configuration/integrations/([^/]*)/", - "destination": "/platforms/java/integrations/$1/" - }, - { - "source": "/platforms/java/guides/([^/]*)/configuration/integrations/(.*)", - "destination": "/platforms/java/guides/$1/integrations/$2" - }, - { - "source": "/platforms/apple/configuration/integrations/([^/]*)/", - "destination": "/platforms/apple/integrations/$1/" - }, - { - "source": "/platforms/apple/guides/([^/]*)/configuration/integrations/", - "destination": "/platforms/apple/guides/$1/integrations/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/micro-frontend-support/", - "destination": "/platforms/javascript/guides/$1/best-practices/micro-frontends/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/sentry-testkit/", - "destination": "/platforms/javascript/guides/$1/best-practices/sentry-testkit/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/webworkers/", - "destination": "/platforms/javascript/guides/$1/best-practices/web-workers/" - }, - { - "source": "/platforms/apple/guides/([^/]*)/configuration/integrations/([^/]*)/", - "destination": "/platforms/apple/guides/$1/integrations/$2/" - }, - { - "source": "/platforms/([^/]*)/crons/troubleshooting-crons/", - "destination": "/platforms/$1/crons/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/crons/troubleshooting-crons/", - "destination": "/platforms/$1/guides/$2/crons/troubleshooting/" - }, - { - "source": "/platforms/([^/]*)/guides/([^/]*)/enriching-events/user-feedback/", - "destination": "/platforms/$1/guides/$2/user-feedback/" - }, - { - "source": "/platforms/([^/]*)/enriching-events/user-feedback/", - "destination": "/platforms/$1/user-feedback/" - }, - { - "source": "/product/metrics/(.*)", - "destination": "/product/explore/metrics/$1" - }, - { - "source": "/product/profiling/(.*)", - "destination": "/product/explore/profiling/$1" - }, - { - "source": "/product/discover-queries/(.*)", - "destination": "/product/explore/discover-queries/$1" - }, - { - "source": "/product/session-replay/(.*)", - "destination": "/product/explore/session-replay/$1" - }, - { - "source": "/platforms/javascript/best-practices/browser-extensions/", - "destination": "/platforms/javascript/best-practices/shared-environments/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/best-practices/browser-extensions/", - "destination": "/platforms/javascript/guides/$1/best-practices/shared-environments/" - }, - { - "source": "/platforms/javascript/guides/([^/]*)/configuration/integrations/trycatch/", - "destination": "/platforms/javascript/configuration/integrations/browserapierrors/" - } - ] -} diff --git a/skip-build.sh b/skip-build.sh index 785beecdf8149..49dfbc783f63d 100755 --- a/skip-build.sh +++ b/skip-build.sh @@ -7,12 +7,15 @@ # - https://vercel.com/docs/projects/overview#ignored-build-step # - https://vercel.com/guides/how-do-i-use-the-ignored-build-step-field-on-vercel +# diff status for develop-docs + docs content dev_docs_diff_status=$(git diff HEAD^ HEAD --quiet -- develop-docs; echo $?) docs_diff_status=$(git diff HEAD^ HEAD --quiet -- docs includes platform-includes ; echo $?) -app_diff_status=$(git diff HEAD^ HEAD --quiet -- src app public ; echo $?) + +# have changes occurred outside of the content directories +non_content_diff_status=$(git diff HEAD^ HEAD --name-only | grep -vE '^(docs/|platform-includes/|includes/|develop-docs/)' | wc -l) # always build on changes in non-content related directories -if [[ $app_diff_status -eq 1 ]] ; then +if [[ $non_content_diff_status -gt 0 ]] ; then exit 1 fi diff --git a/src/components/search/index.tsx b/src/components/search/index.tsx index dd6d0e0a5c6d0..c69bf5c55538a 100644 --- a/src/components/search/index.tsx +++ b/src/components/search/index.tsx @@ -55,7 +55,7 @@ const developerDocsSites: SentryGlobalSearchConfig = [ 'blog', ]; -const sdkDocsSites: SentryGlobalSearchConfig = [ +const userDocsSites: SentryGlobalSearchConfig = [ { site: 'docs', pathBias: true, @@ -66,7 +66,7 @@ const sdkDocsSites: SentryGlobalSearchConfig = [ 'develop', 'blog', ]; -const config = isDeveloperDocs ? developerDocsSites : sdkDocsSites; +const config = isDeveloperDocs ? developerDocsSites : userDocsSites; const search = new SentryGlobalSearch(config); function relativizeUrl(url: string) { diff --git a/base-vercel.json b/vercel.json similarity index 100% rename from base-vercel.json rename to vercel.json