SDK-613: upgrade Next.js examples to 16.3.4 and add example test coverage - #135
devtools-agent[bot] wants to merge 5 commits into
Conversation
The two Next.js examples were pinned to next@14.2.15, which is what the Dependabot alert on this repo flags. Move both to next@15.5.25 (latest fully-patched 15.x); `npm audit` no longer reports any advisory against Next.js itself in either example. 15.x rather than 16.x: Next 16 requires node ^20.9 || >=22, which would break the node 18 and node 21 legs of the CI matrix, and it removes `next lint`, which both examples still use. Alongside the bump: - react/react-dom and their types move to 19, matching what Next 15's App Router expects; @rollbar/react already declares 19.x support. - Add `outputFileTracingRoot` to both next configs so Next 15 stops inferring the repo root as the workspace root (multiple lockfiles). - Add `target: ES2017` to the app-router tsconfig, as Next 15 requires for top-level await. Test coverage for the upgrade — both examples now run jest via `next/jest`, so the suites exercise the real SWC/Next transform: - pages router: `_app` renders the page with a Rollbar instance in context, and a throwing page renders the ErrorBoundary fallback and reports through `rollbar.critical` with the configured message, extra and callback; the home page renders (covers next/font/local and next/image under Next 15). - app router: the async `RootLayout` server component wraps the document in the Rollbar Provider, `next_error_handler/error.tsx` reports the error via `useRollbar` and resets, and the `ErrorBoundary` page renders. Wired up as `npm run test:examples` (skips examples without a `test:ci` script) and run as a new CI step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Follow-up to the 15.5.25 bump: go all the way to the current Next.js major. `npm audit` in both examples now reports nothing against `next` at all (the transitive `postcss` advisories 15.x carried are gone too). Next 16 requires node >= 20.9, so the node 18 leg of the CI matrix is removed; node 22 is added so the matrix still covers three versions. Next 16 also removes `next lint`, and `eslint-config-next@16` is flat-config only and needs ESLint >= 9. So both examples: - replace `.eslintrc.json` with `eslint.config.mjs` re-exporting `eslint-config-next/core-web-vitals` (which already carries the TypeScript setup and the .next/out/build ignores), - move eslint 8 -> 9, and - change their `lint` script from `next lint` to `eslint .`. ESLint is pinned to ^9 rather than ^10 deliberately: eslint-config-next 16 pulls eslint-plugin-react, eslint-plugin-import and eslint-plugin-jsx-a11y, none of which declare ESLint 10 support yet, so ^10 only installs behind three ERESOLVE peer overrides. The root `lint:examples` script still works unchanged -- ESLint 9 still accepts `--ext` -- and both examples lint clean via either invocation. tsconfig `jsx` moves from `preserve` to `react-jsx`, which Next 16 mandates, and the app-router example picks up the `.next/dev/types` include. Verified: both examples build (Turbopack), lint clean, and all six example tests added for this upgrade still pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The `Install` step (`npm run install:all -- ci`) failed on all three CI
legs:
npm error `npm ci` can only install packages when your package.json
and package-lock.json ... are in sync.
npm error Invalid: lock file's @rollbar/react@1.0.0+7da6e313 does
not satisfy @rollbar/react@1.0.0+d49a5d31
The two lockfiles regenerated for the Next 16 bump recorded
`@rollbar/react` as a *copied* dependency:
"node_modules/@rollbar/react": {
"version": "1.0.0+7da6e313",
"resolved": "file:.yalc/@rollbar/react", ...
That happens under npm 9, whose default for `install-links` is `true`
(npm 10 reverted it to `false`). In copy mode npm pins the version of
the `file:` dependency -- and `install-all.js` publishes the package
with `yalc publish --sig`, so that version carries a build signature
that differs on every machine. Any such lockfile can only ever be
installed on the box that generated it.
Regenerated both with npm 10 / `install-links=false`, which restores
the link form the other examples and `main` already use:
"node_modules/@rollbar/react": {
"resolved": ".yalc/@rollbar/react",
"link": true
The signature now only appears on the `.yalc/@rollbar/react` entry,
which `npm ci` does not verify -- confirmed by rewriting the local
signature to a bogus value and re-running `npm ci`, which succeeds
(main's lockfiles have carried a stale `0.12.0-beta+5817c339` there for
several releases for the same reason).
No dependency versions change. Verified after reinstalling both
examples in link mode: `npm ci`, `eslint .`, `next build` and all six
example tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ions
The new node 22 CI leg failed at the library build:
> rollup --config
[!] SyntaxError: Unexpected identifier 'assert'
`rollup.config.mjs` read the version/entry paths from package.json via
`import pkg from './package.json' assert { type: 'json' }`. Node 22
removed the `assert` import-attribute syntax (V8 kept only `with`), so
the config no longer parses there. Nothing in the library itself is
affected -- only this build config, and only on node >= 22.
Switched to `createRequire(import.meta.url)('./package.json')` rather
than `with { type: 'json' }`: `with` only exists from node 20.10 (and
18.20) on, whereas `createRequire` parses and runs on every version,
so nobody's local node breaks either way.
Verified by running the full CI sequence locally on node 22.23.2 with
npm 10.9.9 -- the exact pair the failing leg uses: `install:all -- ci`,
`lint`, `lint:examples`, `build:all` (all four examples) and both test
suites pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brianr
left a comment
There was a problem hiding this comment.
Two CI concerns to address before merging:
Addresses both review comments on the CI workflow. `continue-on-error: true` sat on the `build` job, so every matrix leg could fail while the run still reported success -- the reason the `npm ci` breakage in this branch showed up as a green run. Removed it, so a regression in `Lint`, `Build`, `Test` or the new `Test examples` step now fails CI. `strategy.fail-fast: false` takes its place, which is what the original setting was presumably reaching for: every runtime still reports instead of being cancelled by the first failure. Node 21 has been end-of-life since June 2024, so that slot becomes node 24 (paired with npm 11, the version it bundles). The matrix is now node 20 -- the floor Next.js 16 supports, and what the examples pin -- plus the two maintained LTS lines, 22 and 24. Verified: the full CI sequence (`install:all -- ci`, `lint`, `lint:examples`, `build:all` across all four examples, `test`, `test:examples`) passes locally on node 24.21.0 with npm 11, as it already does on 22.23.2 with npm 10. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rollbar-circleci-machine
left a comment
There was a problem hiding this comment.
AI Agent Review (openai, openai-astra)
What this PR does
Upgrades both Next.js examples from 14.2.15 → 16.3.4 (React 18 → 19, ESLint 8 → 9 flat config), adds Jest + Testing Library specs to each, wires a new test:examples script into CI, drops continue-on-error from the build matrix (replacing it with fail-fast: false), and swaps rollup's import … assert { type: 'json' } for createRequire.
Verified
- The CI comment's rationale checks out:
next@16.3.4declaresengines.node: ">=20.9.0"(examples/nextjs/package-lock.json:7813-7815), so node 20 is a correct floor and dropping 18/21 is right. - Removing
continue-on-error: trueand addingfail-fast: falseis exactly the combination that makes every matrix leg report and fails the run. - The
createRequire(import.meta.url)('./package.json')swap inrollup.config.mjs:15is correct for an.mjsconfig (Rollup imports.mjsconfigs natively, soimport.meta.urlis the real file path). - Test assertions line up with the code they exercise:
ErrorBoundary.componentDidCatchcallsrollbar[level](logMessage, error, data, callback)(src/error-boundary.js:41-53), which matchesapp.test.tsx's 4-argcriticalexpectation includingexpect.objectContaining({ more: 'data' })from_app.tsx:16;ResetPagereally does render "Something went wrong!" / "Try again" (examples/nextjs-approuter/src/components/ResetPage.tsx:6-7). - Both example lockfiles' root
packages[""]blocks match theirpackage.json(sonpm ciinscripts/install-all.js:26stays in sync), andprop-types@15.8.1— a peer dep of@rollbar/reactused byProvider/ErrorBoundary— is present in both. npm run --if-present test:ciis valid npm arg ordering, and neither CRA example definestest:ci, so they are skipped rather than hanging in watch mode.
Findings
Three below: one that likely reddens the Lint examples step, plus two lower-severity test-hygiene/coverage notes.
Other notes (not filed as findings)
rollup.config.mjs:80drops the trailing comma afterentryFileNames. It makes that block match its sibling at line 89, and lint-action's defaultprettier_extensionsdoesn't includemjs, so nothing will complain — but it's unrelated diff noise, and prettier 3.2.5's defaulttrailingComma: "all"would put it back.- With import assertions gone from
rollup.config.mjs, theimportAssertionsbabel-parser override at.eslintrc.json:25-32is now dead config (that file isn't in this diff). - The two examples diverge in how they absorb Next 16's generated TS artifacts: the app-router one adds
.next/dev/types/**/*.tstoinclude, the pages one instead gainsimport "./.next/types/routes.d.ts"in a committednext-env.d.ts(whichexamples/nextjs-approuter/.gitignore:36treats as generated). Both are Next-generated; worth knowing they'll churn on the nextnext build. - I did not audit the ~15k lines of lockfile churn beyond the root package blocks and the pins cited above.
| import { Provider as RollbarProvider } from '@rollbar/react'; | ||
|
|
||
| import RootLayout from '@/app/layout'; | ||
| import { clientConfig } from '@/rollbar'; |
There was a problem hiding this comment.
Low: Importing @/rollbar here builds a real Rollbar client: examples/nextjs-approuter/src/rollbar.ts:14-17 calls new Rollbar({ accessToken: process.env.ROLLBAR_SERVER_TOKEN, ...baseConfig }) at module scope, with captureUncaught: true and captureUnhandledRejections: true (lines 4-5). That defeats the isolation fake-rollbar.ts:12-13 explicitly promises ("tests never build a real client or touch the network"), and installs process/window-level handlers inside the jsdom run with an undefined access token. The pages-router suite already guards against exactly this with jest.mock('rollbar') (examples/nextjs/src/__tests__/app.test.tsx:8-10); the app-router suite should do the same. Automocking is safe for this test — clientConfig stays a plain object, so the toBe(clientConfig) identity assertion on line 11 is unaffected.
| import { clientConfig } from '@/rollbar'; | |
| import { clientConfig } from '@/rollbar'; | |
| // `@/rollbar` builds a server-side Rollbar instance at import time. | |
| jest.mock('rollbar'); |
SDK-613 — upgrade the Next.js examples off the vulnerable
next@14.2.15Both Next.js examples (
examples/nextjs, pages router, andexamples/nextjs-approuter, app router) were pinned tonext@14.2.15, which is what the Dependabot alert on this repo flags. This moves both tonext@16.3.4, the current major.npm auditin both examples now reports nothing againstnext— and the transitivepostcssadvisories that 15.x still carried are gone too.Framework / runtime moves
react,react-domand their@typesmove to 19, which is what Next 15+ App Router expects.@rollbar/reactalready declares 19.x support in its peer range, so no library change is needed.node: 18leg of the CI matrix is removed andnode: 22added, keeping three versions covered.outputFileTracingRootadded to both next configs so Next stops inferring the repo root as the workspace root (this repo has multiple lockfiles).jsxmovespreserve→react-jsx(mandated by Next 16); the app-router example also picks up the.next/dev/typesinclude andtarget: ES2017for top-level await.Lint plumbing
Next 16 removes
next lint, andeslint-config-next@16is flat-config-only and needs ESLint >= 9. So in both examples:.eslintrc.json→eslint.config.mjsre-exportingeslint-config-next/core-web-vitals(which already carries the TypeScript setup and the.next/out/buildignores),^8→^9,lintscript becomeseslint ..ESLint is pinned to
^9rather than^10deliberately:eslint-config-next@16pullseslint-plugin-react,eslint-plugin-importandeslint-plugin-jsx-a11y, none of which declare ESLint 10 support yet, so^10only installs behind threeERESOLVEpeer overrides. The rootlint:examplesscript keeps working unchanged — ESLint 9 still accepts--ext— and both examples lint clean via either invocation.Test coverage for the upgrade
An examples bump with no assertions is easy to get subtly wrong, so both examples now run jest through
next/jest, meaning the suites exercise the real SWC/Next transform rather than a hand-rolled babel config:_apprenders the page with a Rollbar instance in context; a throwing page renders theErrorBoundaryfallback and reports throughrollbar.criticalwith the configured message, extra and callback; the home page renders (which coversnext/font/localandnext/imageunder the new major).RootLayoutserver component wraps the document in the RollbarProvider;next_error_handler/error.tsxreports viauseRollbarand resets; theErrorBoundarypage renders.Wired up as
npm run test:examplesat the root (reusing the existingscripts/foreach-example.ts, skipping examples with notest:ciscript) plus atest:all, and run as a new Test examples step in CI.Verification
Both examples build (Turbopack), lint clean, and all six new example tests pass. Library source is untouched — this PR only moves the examples and CI.
🤖 Generated with Claude Code