Skip to content

test: Add package build configuration tests - #2116

Merged
kinyoklion merged 14 commits into
mainfrom
devin/1792689914-package-config-tests
Oct 27, 2026
Merged

kinyoklion merged 14 commits into
mainfrom
devin/1792689914-package-config-tests

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Adds a CI workflow that packs every released package and tests the tarballs in fresh Yarn consumer projects, under many build configurations and in the Cloudflare and Vercel runtimes. Results are compared against a checked-in baseline. Follows #2115.

  • New workflow package-configs: one job builds and packs all released packages, then 7 parallel jobs run the suites against the tarballs. Runs on PRs and pushes to main/feat/** (markdown-only changes skipped), nightly, and on manual dispatch.
  • Suites: types (tsc for every entrypoint under node10, node16/nodenext CJS and ESM, bundler, preserve; TS 5.0.4, 5.9.3, 6.0.3; strict, skipLibCheck: false), attw, runtime (Node require/import, esbuild node/browser/neutral), cloudflare (workerd through wrangler dev with local KV), vercel (Next.js edge route and middleware, Turbopack and webpack).
  • Pass/fail: any difference from scripts/package-config-tests/baseline/*.json fails the job. A case that was ok and now fails is reported as a regression. An intended change needs --update and a committed baseline diff.
  • For review: the trigger runs on every PR because it builds the whole repo. It could be narrowed to paths that affect packaging.
Implementation details

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

#2113, #2115.

Describe the solution you've provided

  • scripts/package-config-tests/run.js <suite>: runs one suite (pack, types[:<ts version>], attw, runtime, cloudflare, vercel) and compares the results with baseline/<suite>.json. Use --update to accept new results. <work>/<suite>-details.json has the error output for each failing case.
  • Consumer projects install the tarballs with Yarn. Every tarball is also a resolutions entry, so packages that depend on each other resolve to the local builds. Direct tool versions (TypeScript, @types/node, React, esbuild, ATTW, wrangler, Next.js, @vercel/edge-config, ...) are pinned so that results stay stable.
  • Dependency cooldown: each consumer project gets a .yarnrc.yml built from fixtures/consumer.yarnrc.yml (static settings) plus npmMinimalAgeGate (3 days) and npmPreapprovedPackages from the repository's Yarn config, so external dependencies, transitive ones included, go through the same quarantine as the monorepo's own installs. The LaunchDarkly tarballs are local files and are not age-gated. The @bytecodealliance/jco TypeScript resolution is copied from the root package.json. Yarn doesn't install peer dependencies, so the installer adds any missing required peers and reinstalls, as npm would.
  • Each baseline case is ok or a short failure value: TypeScript error codes, ATTW problem kinds, or fail. Full messages go only into the details file, so unrelated wording changes don't fail the job.
  • Cloudflare: each Worker is seeded with flag data in local KV, started with wrangler dev, and must return value: true for sample-feature. Each Worker also runs wrangler deploy --dry-run. The four Workers are: a TypeScript Worker, the OpenFeature provider, a Worker using CommonJS require, and one prebuilt with tsup as in packages/sdk/cloudflare/example.
  • Vercel: a Next.js 16 app is built with Turbopack and with webpack and served with next start. The edge route and the middleware must both evaluate the flag. The real @vercel/edge-config client reads from a local mock of the Edge Config item API, since CI has no Vercel store.
  • Known limitations are in the baseline as non-ok values. Examples: node10 has no subpath support, react-native-client-sdk/jest/react-native are ESM-only (TS1479 for node16 CJS), Node-only packages fail browser/neutral bundles, edge SDKs don't load in plain Node, and fastly-server-sdk needs fastly:* types.

Validation

  • Packs of fix: Resolve types under node16/nodenext module resolution #2115's branch: every suite matches the baseline on a second run, so the results are deterministic.
  • Packs of main: the suites fail as they should. The Cloudflare cjs-require Worker is reported as a regression (it doesn't start on main). attw and runtime report the differences that fix: Resolve types under node16/nodenext module resolution #2115 fixed.
  • CI on this PR: every suite passes against the same baseline that was generated locally, so results don't depend on the machine. Wall time is about 10 min: pack 2.5 min, types:* 5.5–8 min each, the other suites under 1 min each.

Describe alternatives you've considered

  • Adding the suite as a yarn workspace: rejected. It would pull wrangler/Next.js into the monorepo lockfile and test workspace links instead of the published tarballs.
  • A Fastly (Viceroy) and Akamai runtime suite: not included yet. Those can be added as further suites.

Additional context

Found while running the suite: server-sdk-ai-langchain gives TS1479 for node16 CommonJS consumers. It is recorded in the baseline as an existing limitation.

Also found after moving to Yarn: cloudflare-server-sdk's bundle requires semver/functions/parse.js without declaring semver. It only loaded when another package's semver 7 got hoisted. Fixed in #2115.

Link to Devin session: https://app.devin.ai/sessions/6455af0ee31c4e5fbfd20c108731cfa7
Open in Devin Desktop: https://app.devin.ai/desktop/session/6455af0ee31c4e5fbfd20c108731cfa7?variant=devin
Requested by: @kinyoklion

devin-ai-integration Bot and others added 4 commits October 22, 2026 16:21
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
…-native, cloudflare and jest packages

Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

ts-jest 29.4.15 resolves test imports with the tsconfig's moduleResolution
(nodenext), so the extensionless '../src/index' import no longer resolves.

Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1792689914-package-config-tests branch from a9b4178 to 45fbfc5 Compare October 23, 2026 16:08
@kinyoklion
kinyoklion marked this pull request as ready for review October 23, 2026 16:38
@kinyoklion
kinyoklion requested a review from a team as a code owner October 23, 2026 16:38
devin-ai-integration Bot and others added 5 commits October 23, 2026 16:53
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
…minimum-age gate

Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Comment thread .github/workflows/package-configs.yml Outdated
paths-ignore:
- '**.md'
pull_request:
branches: [main, 'feat/**', 'devin/1792686117-node16-types']

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.

nit: should remove the temporary branch once the fix is merged

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.

Agreed. It only lives in commit c025e7a so that the workflow runs on this stacked PR. I'll drop that commit once #2115 merges and this PR is retargeted to main.

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.

Will wait until first PR merged before approving this one.

Comment thread scripts/package-config-tests/lib.js Outdated
Co-Authored-By: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
Base automatically changed from devin/1792686117-node16-types to main October 26, 2026 18:11
kinyoklion added a commit that referenced this pull request Oct 26, 2026
Fixes TypeScript type resolution under `moduleResolution:
node16`/`nodenext` for `@launchdarkly/node-client-sdk`, its common
packages, and the sibling packages with the same packaging problems.

**Related issues**

Fixes #2113

- `node-client-sdk`, `electron-client-sdk`, `react-sdk`,
`vue-client-sdk`, `client-testing-plugin`, `cloudflare-server-sdk`,
`openfeature-node-server`, `openfeature-cloudflare-server`: `exports`
now gives each condition its own declarations (`import` → ESM `.d.ts`,
`require` → `.d.cts` / CJS `.d.ts`). Before, CJS consumers were
type-checked against the ESM declarations (TS1479, "Masquerading as
ESM").
- `js-sdk-common`, `js-client-sdk-common`, `js-server-sdk-common-edge`,
`vercel-server-sdk`, `react-native-client-sdk`, `jest`: a new post-build
step, `scripts/add-esm-declaration-extensions.js`, adds explicit `.js` /
`/index.js` to relative imports in emitted ESM `.d.ts` files (TS2834,
"Internal resolution error"). JS output is unchanged.
- `@launchdarkly/jest`: removed the `./react` export. `src/react`
doesn't exist, so it never resolved (types or runtime) in any published
version.
- Main-vs-PR regression matrix over every released package: 0
regressions (details below).

**Requirements**

- [ ] I have added test coverage for new or changed functionality
- [x] I have followed the repository's [pull request submission
guidelines](../blob/main/CONTRIBUTING.md#submitting-pull-requests)
- [x] I have validated my changes against all supported platform
versions

<details>
<summary>Implementation details</summary>

**Describe the solution you've provided**

Per-package changes beyond the two mechanisms above:
- `cloudflare-server-sdk`: the CJS rollup build now also emits
declarations into `dist/cjs`, `exports` maps `require` to them, and the
build writes `dist/cjs/package.json` with `"type": "commonjs"`. Before,
the package is `"type": "module"`, so Node treated `dist/cjs/index.js`
as ESM: `require('@launchdarkly/cloudflare-server-sdk')` returned no
exports on Node 24. It now returns the real exports.
- `openfeature-node-server` / `openfeature-cloudflare-server`: switched
from a separate `tsc --emitDeclarationOnly` (one ESM-flavoured `.d.ts`
for both conditions) to tsup `dts: true`, which emits `index.d.ts` +
`index.d.cts`.
- `js-server-sdk-common-edge` / `vercel-server-sdk`: the rewrite runs
inside `scripts/build-package.sh` on `dist/esm`.

**Regression matrix (main `578bdebbf2` vs this branch)**

Every package in `.release-please-manifest.json` was `yarn pack`ed from
both trees and installed into a fresh npm consumer project.

- `tsc` consumer per package entrypoint (`import * as m from '<pkg>'`) ×
`node10`, `node16` CJS/ESM, `nodenext` CJS/ESM, `bundler`, `module:
preserve` × TypeScript 5.0.4, 5.9.3 and 6.0.3, with `strict` and
`skipLibCheck: false` (700 cases): 0 regressions, 198 improved, the rest
unchanged. Every package except `react-native-client-sdk` and `jest` is
now 0 errors in all node16/nodenext/bundler modes on TS 5.9/6.0. Errors
left over are the same on main: TS 6's node10 deprecation (TS5107),
`fastly:kv-store` types, and the test project not having `@types/jest`.
- `@arethetypeswrong/cli` (node10, node16 CJS/ESM, bundler): no new
problems on any package. 17 problems fixed. Remaining: node10 can't read
subpath `exports` (`react-sdk`, `client-testing-plugin`, `jest`, same as
before), and `react-native-client-sdk` / `jest/react-native` CJS → ESM.
Those packages only ship ESM, so TS1479 for a node16 CJS consumer is
accurate.
- Runtime, Node 24: `require` and `import` of every entrypoint, plus
esbuild bundles (esm/cjs × node/browser/neutral). Results match main
everywhere except `cloudflare-server-sdk` `require`, which is now fixed
(see above).
- Root `yarn build` passes. Unit tests, lint and `oxfmt --check` pass
for every changed workspace.

The original repro from the issue (TS 5.9.3): published 4.3.0 gives
68–69 errors under node16/nodenext for both `index.ts` and `index.mts`.
With this PR it gives 0.

**Describe alternatives you've considered**

- **Bundling the ESM declarations** (tsup `--dts-only`): breaks
declaration emit downstream. `js-client-sdk-common` can't name internal
`js-sdk-common` types such as `DiagnosticInitEvent` (TS4061/TS4094).
- **Adding `.js` extensions in source**: about 570 relative imports in
the common packages alone, plus Jest `moduleNameMapper` changes and a
lint rule.
- **Moving the common packages to tsup**: changes `dist` layout,
size-check paths and JS output for every SDK.

**Edge runtime validation** (packed `main` vs PR builds):

- Cloudflare: Workers for `cloudflare-server-sdk` (TS, tsup prebuild and
a CommonJS `require` entry) and `openfeature-cloudflare-server`, run
with `wrangler dev` (workerd), wrangler 4.152.0 and 3.114.17,
`nodejs_compat`, flag data in local KV. Each Worker initialized and
returned the expected `FALLTHROUGH` / `true` evaluation. The ESM
`wrangler deploy --dry-run` bundles are byte-identical between `main`
and the PR. The `require` Worker fails to start on `main`
(`ReferenceError: exports is not defined` in `dist/cjs/index.js`) and
works on the PR.
- Vercel: Next.js 16.4.2 app with an edge route handler and edge
middleware using `@vercel/edge-config` 1.5.1, pointed at a local Edge
Config mock. `next build` (Turbopack and `--webpack`) plus `next start`:
both routes evaluate correctly on `main` and the PR.

**Additional context**

The rewrite script fails the build if a relative specifier doesn't
resolve to a `.d.ts` file or an `index.d.ts` directory, so a broken
rewrite can't ship silently.

`sdk/akamai-base` unit tests started failing on `main` with `TS2307:
Cannot find module '../src/index'` after ts-jest 29.4.15 (released
2026-10-15), which now resolves test imports with the tsconfig's
`moduleResolution: nodenext`. `jest.config.json` now tells ts-jest to
use `moduleResolution: node` for tests; the build config is unchanged.

`cloudflare-server-sdk` now declares `semver` (7.5.4, the same as
`js-server-sdk-common`). Its rollup bundle inlines the js-core packages
but leaves `semver` external, so `dist/*/index.js` requires
`semver/functions/parse.js`. The package didn't declare it, so whether
the require resolved depended on the package manager hoisting another
package's semver 7. The Yarn-based package-config tests in #2116 caught
it failing to load.

Contract-test steps intermittently fail with `Unable to find a release
matching 'v2'` / `'v3'`. That comes from the sdk-test-harness
downloader's release lookup, not from the SDK; the latest run passed
every contract-test job.

</details>

Link to Devin session:
https://app.devin.ai/sessions/6455af0ee31c4e5fbfd20c108731cfa7
Open in Devin Desktop:
https://app.devin.ai/desktop/session/6455af0ee31c4e5fbfd20c108731cfa7?variant=devin
Requested by: @kinyoklion

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 31476 bytes
Compressed size limit: 31500
Uncompressed size: 149622 bytes

@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 34140 bytes
Compressed size limit: 35000
Uncompressed size: 122071 bytes

@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 25998 bytes
Compressed size limit: 44000
Uncompressed size: 167978 bytes

@kinyoklion
kinyoklion merged commit c00f2a9 into main Oct 27, 2026
65 checks passed
@kinyoklion
kinyoklion deleted the devin/1792689914-package-config-tests branch October 27, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants