From 7ee248fb751e55699e5b1e9c1566837f69032b87 Mon Sep 17 00:00:00 2001 From: Kris Nye Date: Wed, 24 Jun 2026 14:08:02 -0700 Subject: [PATCH 1/2] fix(ci): extend gate to cover all published downstream packages The CI gate only checked @adobe/data; data-lit's type error introduced in #127 was invisible to CI and reached main undetected. Two jobs now: - data: existing @adobe/data typecheck + lint + test (unchanged) - packages: depends on data; rebuilds @adobe/data for dist/, then builds (tsc -b) and tests all @adobe/data-* packages. data-persistence uses test:node to avoid the Playwright browser requirement in CI. Also fixes the latent data-lit error: useDragTransaction now constrains T extends {} | null to satisfy withFilter's U bound (tightened in #127). Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 44 +++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 631f5f1..21f8bfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,11 +5,11 @@ name: CI # whose `tsc -b` / unit tests were red could still be merged green — exactly # what happened with #114. This gate makes those failures block the merge. # -# Scope: the published core library `@adobe/data`, where the regression class -# occurred. Type-checking uses the project-reference build (`tsc -b`, via the -# package's `typecheck` script, which builds the wasm artifact the source -# imports first). Tests run with SKIP_PERF=1 (`test:ci`) so the gate excludes -# the non-deterministic timing-ratio perf tests and stays reliable. +# Two jobs: +# data — @adobe/data core: typecheck (tsc -b + WASM), lint, unit tests. +# packages — downstream published packages: build (tsc -b) + tests for each. +# Runs after `data` so a core failure surfaces once, not twice. +# @adobe/data is rebuilt here to provide dist/ for downstream tsc. on: pull_request: @@ -49,3 +49,37 @@ jobs: - name: Unit tests run: pnpm --filter @adobe/data run test:ci + + packages: + name: "downstream packages — build, test" + runs-on: ubuntu-latest + needs: [data] + steps: + - uses: actions/checkout@v6 + + - uses: pnpm/action-setup@v6 + with: + version: 9 + + - uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - name: Build @adobe/data (provides dist/ for downstream tsc) + run: pnpm --filter @adobe/data run typecheck + + - name: Build downstream packages (type-check via tsc -b) + run: pnpm --filter '@adobe/data-*' run build + + - name: Test downstream packages + run: | + pnpm --filter @adobe/data-lit \ + --filter @adobe/data-gpu \ + --filter @adobe/data-react \ + --filter @adobe/data-solid \ + --filter @adobe/data-sync \ + run test + pnpm --filter @adobe/data-persistence run test:node From fa58cb77eba5c34a80e2045ccfafe94d07af7340 Mon Sep 17 00:00:00 2001 From: Kris Nye Date: Wed, 24 Jun 2026 16:01:39 -0700 Subject: [PATCH 2/2] fix(data-persistence): open node-fs files with O_RDWR|O_CREAT, not a+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "a+" (append+read) ignores the position argument on writes — every handle.write() lands at EOF regardless of the offset passed. This made writeAt semantically equivalent to appendAt, so all conformance tests that write at a non-zero offset failed. O_RDWR|O_CREAT (read+write, create-if-missing, never truncate) is the correct flag set: positions are honoured on write, the file is created on first open, and existing content is never clobbered. These tests were never run in CI before the packages job was added in this branch, so the bug went undetected since #102. Co-Authored-By: Claude Sonnet 4.6 --- packages/data-persistence/src/node/node-fs-file.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/data-persistence/src/node/node-fs-file.ts b/packages/data-persistence/src/node/node-fs-file.ts index 02ab57e..8bc2b1f 100644 --- a/packages/data-persistence/src/node/node-fs-file.ts +++ b/packages/data-persistence/src/node/node-fs-file.ts @@ -1,6 +1,6 @@ // © 2026 Adobe. MIT License. See /LICENSE for details. -import { promises as fs } from "node:fs"; +import { promises as fs, constants as fsConstants } from "node:fs"; import type { FileHandle } from "node:fs/promises"; import { RandomAccessFile } from "../backend/random-access-file.js"; @@ -9,8 +9,10 @@ import { RandomAccessFile } from "../backend/random-access-file.js"; * already be validated by the surrounding {@link NodeFsBackend}. */ export const createNodeFsFile = async (absPath: string): Promise => { - // Open with read+write, create-if-missing, never truncate. - const handle: FileHandle = await fs.open(absPath, "a+"); + // O_RDWR | O_CREAT: read+write, create-if-missing, never truncate. + // "a+" is wrong here — append mode ignores the position argument on writes, + // which breaks writeAt semantics (every write would land at EOF instead). + const handle: FileHandle = await fs.open(absPath, fsConstants.O_RDWR | fsConstants.O_CREAT, 0o666); let closed = false; const ensureOpen = (): void => {