From 9adbba16a1877ae182cc857ffbe3c12e8aabe026 Mon Sep 17 00:00:00 2001 From: Jeremy Lee Date: Mon, 15 Jun 2026 14:55:12 -0400 Subject: [PATCH 1/2] fix: inject NEXT_PUBLIC_FUNKIT_API_KEY in CI builds; guard FunkitCheckout against a missing key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The funkit checkout host is mounted globally in _app, and FunkitProvider's validateFunkitConfig throws 'Invalid funkitConfig: Missing apiKey.' on an empty apiKey. The CI build pipeline never injected NEXT_PUBLIC_FUNKIT_API_KEY, so every cypress smoke build crashed the whole app on load (all markets) — the dashboard toggle and supply modal never rendered. - Inject NEXT_PUBLIC_FUNKIT_API_KEY (from the new FUNKIT_API_KEY repo secret) through the build composite action and every workflow that builds the app (build-test-deploy, build-test-deploy-dev, build-fork, build_staging). - Guard FunkitCheckout: render null when funkitConfig.apiKey is empty, so a missing/misconfigured key can never white-screen the app again — Supply falls back to the native modal via the existing beginFunSupply()->false path. - Revert the temporary DebugCrashBoundary (#3017) used to pinpoint this. Requires the FUNKIT_API_KEY secret to be added to the repo for funkit to be functional (publishable client-side key); without it the app degrades to native supply rather than crashing. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/actions/build/action.yml | 5 + .github/workflows/build-fork.yml | 1 + .github/workflows/build-test-deploy-dev.yml | 1 + .github/workflows/build-test-deploy.yml | 2 + pages/_app.page.tsx | 105 +++++++++--------- src/components/DebugCrashBoundary.tsx | 53 --------- .../FunCheckout/FunkitCheckout.tsx | 12 ++ 7 files changed, 71 insertions(+), 108 deletions(-) delete mode 100644 src/components/DebugCrashBoundary.tsx diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 93e8489148..b5b71f8599 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -45,6 +45,10 @@ inputs: description: enables cypress required: false default: 'true' + NEXT_PUBLIC_FUNKIT_API_KEY: + description: funkit checkout API key (publishable, client-side). Without it the funkit checkout host stays unmounted. + required: false + default: '' runs: using: 'composite' @@ -89,3 +93,4 @@ runs: NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: '${{ inputs.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID }}' NEXT_PUBLIC_NARVAL_CLIENT_ID: '${{ inputs.NEXT_PUBLIC_NARVAL_CLIENT_ID }}' NEXT_PUBLIC_IS_CYPRESS_ENABLED: '${{ inputs.NEXT_PUBLIC_IS_CYPRESS_ENABLED }}' + NEXT_PUBLIC_FUNKIT_API_KEY: '${{ inputs.NEXT_PUBLIC_FUNKIT_API_KEY }}' diff --git a/.github/workflows/build-fork.yml b/.github/workflows/build-fork.yml index 359a27a289..badfed4fde 100644 --- a/.github/workflows/build-fork.yml +++ b/.github/workflows/build-fork.yml @@ -22,6 +22,7 @@ jobs: uses: ./.github/actions/build with: NEXT_PUBLIC_ENV: 'prod' + NEXT_PUBLIC_FUNKIT_API_KEY: ${{ secrets.FUNKIT_API_KEY }} - name: Upload artifacts uses: ./.github/actions/upload-artifacts diff --git a/.github/workflows/build-test-deploy-dev.yml b/.github/workflows/build-test-deploy-dev.yml index 0c01ef439e..2858cc2168 100644 --- a/.github/workflows/build-test-deploy-dev.yml +++ b/.github/workflows/build-test-deploy-dev.yml @@ -39,6 +39,7 @@ jobs: NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} NEXT_PUBLIC_NARVAL_CLIENT_ID: ${{ secrets.NEXT_PUBLIC_NARVAL_CLIENT_ID }} NEXT_PUBLIC_IS_CYPRESS_ENABLED: ${{ matrix.build.cypress_enabled }} + NEXT_PUBLIC_FUNKIT_API_KEY: ${{ secrets.FUNKIT_API_KEY }} - name: Upload artifacts uses: ./.github/actions/upload-artifacts diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index afa9fcd468..a4ecd0d1be 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -39,6 +39,7 @@ jobs: NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} NEXT_PUBLIC_NARVAL_CLIENT_ID: ${{ secrets.NEXT_PUBLIC_NARVAL_CLIENT_ID }} NEXT_PUBLIC_IS_CYPRESS_ENABLED: ${{ matrix.build.cypress_enabled }} + NEXT_PUBLIC_FUNKIT_API_KEY: ${{ secrets.FUNKIT_API_KEY }} - name: Upload artifacts uses: ./.github/actions/upload-artifacts @@ -58,6 +59,7 @@ jobs: uses: ./.github/actions/build with: NEXT_PUBLIC_ENV: 'staging' + NEXT_PUBLIC_FUNKIT_API_KEY: ${{ secrets.FUNKIT_API_KEY }} - name: Upload artifacts uses: ./.github/actions/upload-artifacts diff --git a/pages/_app.page.tsx b/pages/_app.page.tsx index 83df00cbe1..0d86db1a93 100644 --- a/pages/_app.page.tsx +++ b/pages/_app.page.tsx @@ -16,7 +16,6 @@ import dynamic from 'next/dynamic'; import Head from 'next/head'; import { ReactNode, useEffect, useState } from 'react'; import { AddressBlocked } from 'src/components/AddressBlocked'; -import { DebugCrashBoundary } from 'src/components/DebugCrashBoundary'; import { Meta } from 'src/components/Meta'; import { TransactionEventHandler } from 'src/components/TransactionEventHandler'; import { GasStationProvider } from 'src/components/transactions/GasStation/GasStationProvider'; @@ -162,60 +161,56 @@ export default function MyApp(props: MyAppProps) { imageUrl="https://app.aave.com/aave-com-opengraph.png" /> - - - - - - - - - - - - - - - - - {getLayout()} - - - - - - - - - - - - - - - {/* Swap Modals */} - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + {getLayout()} + + + + + + + + + + + + + + + {/* Swap Modals */} + + + + + + + + + + + + + + + + + + + + ); diff --git a/src/components/DebugCrashBoundary.tsx b/src/components/DebugCrashBoundary.tsx deleted file mode 100644 index 7e7e7bd262..0000000000 --- a/src/components/DebugCrashBoundary.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Component, ErrorInfo, ReactNode } from 'react'; - -/** - * TEMPORARY diagnostic boundary (remove before merge). Catches any render-phase - * crash and surfaces the error + React componentStack — both to the console and - * visibly in the DOM so it's captured in the cypress failure screenshot. Used to - * pinpoint the exact component behind the CI "Application error" white-screen. - */ -export class DebugCrashBoundary extends Component< - { children: ReactNode; label?: string }, - { error: Error | null; componentStack: string } -> { - state = { error: null as Error | null, componentStack: '' }; - - static getDerivedStateFromError(error: Error) { - return { error, componentStack: '' }; - } - - componentDidCatch(error: Error, info: ErrorInfo) { - const label = this.props.label ?? 'app'; - /* eslint-disable no-console */ - console.error(`[DEBUG_CRASH:${label}] message=`, error?.message); - console.error(`[DEBUG_CRASH:${label}] stack=`, error?.stack); - console.error(`[DEBUG_CRASH:${label}] componentStack=`, info?.componentStack); - /* eslint-enable no-console */ - this.setState({ componentStack: info?.componentStack ?? '' }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any).__DEBUG_CRASH__ = { - label, - message: error?.message, - stack: error?.stack, - componentStack: info?.componentStack, - }; - } - - render() { - if (this.state.error) { - return ( -
-          {`DEBUG_CRASH[${this.props.label ?? 'app'}]: ${
-            this.state.error.message
-          }\n\nCOMPONENT STACK:${this.state.componentStack}\n\nERROR STACK:\n${
-            this.state.error.stack
-          }`}
-        
- ); - } - return this.props.children; - } -} diff --git a/src/components/transactions/FunCheckout/FunkitCheckout.tsx b/src/components/transactions/FunCheckout/FunkitCheckout.tsx index ccb0fd71eb..7e2217c607 100644 --- a/src/components/transactions/FunCheckout/FunkitCheckout.tsx +++ b/src/components/transactions/FunCheckout/FunkitCheckout.tsx @@ -132,6 +132,18 @@ function InnerCheckout() { } export function FunkitCheckout() { + // funkit checkout is non-essential and non-functional without an API key + // (NEXT_PUBLIC_FUNKIT_API_KEY). FunkitProvider validates the config on render + // and throws "Invalid funkitConfig: Missing apiKey." on an empty key — and + // because this host is mounted globally in _app, that throw crashes the entire + // app on every page in any environment that doesn't inject the key (CI smoke + // builds, preview builds, local without .env). Render nothing instead: the + // Supply buttons fall back to the native modal because beginFunSupply() returns + // false when the island never registers on the bridge. + if (!funkitConfig.apiKey) { + return null; + } + return ( From d8b1c8333513007f9b14adcc7043c7d5da394410 Mon Sep 17 00:00:00 2001 From: Jeremy Lee Date: Mon, 15 Jun 2026 15:51:38 -0400 Subject: [PATCH 2/2] chore: drop NEXT_PUBLIC_FUNKIT_API_KEY from build-fork.yml build-fork only produces the out_cypress artifact for the fork-cypress flow (test-deploy-fork.yml); it is never deployed to users, and the FunkitCheckout apiKey guard already prevents a crash when the key is absent. The key is only needed in jobs that deploy a human-facing build (build-test-deploy[/dev]). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build-fork.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-fork.yml b/.github/workflows/build-fork.yml index badfed4fde..359a27a289 100644 --- a/.github/workflows/build-fork.yml +++ b/.github/workflows/build-fork.yml @@ -22,7 +22,6 @@ jobs: uses: ./.github/actions/build with: NEXT_PUBLIC_ENV: 'prod' - NEXT_PUBLIC_FUNKIT_API_KEY: ${{ secrets.FUNKIT_API_KEY }} - name: Upload artifacts uses: ./.github/actions/upload-artifacts