Skip to content

[codex] fix downstream Bazel package consumption#89

Merged
Jesssullivan merged 1 commit into
mainfrom
codex/consumer-bazel-package-srcs
May 3, 2026
Merged

[codex] fix downstream Bazel package consumption#89
Jesssullivan merged 1 commit into
mainfrom
codex/consumer-bazel-package-srcs

Conversation

@Jesssullivan
Copy link
Copy Markdown
Owner

Summary

  • bump @tummycrypt/scheduling-kit metadata to 0.7.6
  • make the Bazel //:pkg Svelte package action safe when kit is consumed as an external Bzlmod module
  • add a wrapper that packages from a declared source tree in a writable temp project instead of relying on main-workspace-relative src
  • refresh generated package/release docs and AGENTS package-authority truth

Root Cause

bazel build @tummycrypt_scheduling_kit//:pkg from a downstream registry consumer failed because the Svelte package action assumed src existed relative to the main workspace/action cwd. After fixing that, the action also needed a writable .svelte-kit mirror because external module inputs are read-only inside the sandbox.

Validation

  • pnpm docs:generate
  • pnpm check:release-metadata
  • pnpm exec prettier --check AGENTS.md scripts/svelte-package-bazel-wrapper.mjs
  • git diff --check
  • npm exec --yes @bazel/bazelisk -- build //:pkg //:typecheck
  • downstream Bzlmod smoke: temp consumer built @tummycrypt_scheduling_kit//:pkg and @tummycrypt_scheduling_bridge//:pkg via the local tinyland registry with --override_module=tummycrypt_scheduling_kit=/private/tmp/scheduling-kit-consumer-bazel

@Jesssullivan Jesssullivan marked this pull request as ready for review May 3, 2026 00:35
@Jesssullivan Jesssullivan merged commit 6e90b73 into main May 3, 2026
6 checks passed
@Jesssullivan Jesssullivan deleted the codex/consumer-bazel-package-srcs branch May 3, 2026 00:36
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 3, 2026

Greptile Summary

This PR bumps @tummycrypt/scheduling-kit to 0.7.6 and fixes downstream Bzlmod consumption of //:pkg by introducing a wrapper script (svelte-package-bazel-wrapper.mjs) that stages source files into a writable temp project before invoking the @sveltejs/package CLI, working around the read-only sandbox constraint on external module inputs.

  • P1workDir is assigned the return value of mkdirSync(..., { recursive: true }), which is string | undefined; if the directory already existed workDir is undefined and the immediately following path.join(workDir, \"src\") throws a cryptic TypeError.
  • P2resolvePackageCli hardcodes the internal src/cli.js path inside @sveltejs/package, which is not a public API guarantee and could silently break on a package update.
  • P2 — The temp directory created by mkdtempSync is not cleaned up when an exception is thrown inside prepareWritableProject (before rmSync on line 174 is reached).

Confidence Score: 3/5

Merge blocked by a P1 in the critical new wrapper path; fix is a one-line change before merging.

One P1 finding (mkdirSync return-value used as workDir, which is undefined when the dir pre-exists) sits on the single new code path this PR introduces. Two P2 concerns (hardcoded internal CLI path, temp-dir leak on exceptions) lower confidence further. All other files (version bumps, generated docs) are consistent and mechanical.

scripts/svelte-package-bazel-wrapper.mjs — the prepareWritableProject function and resolvePackageCli.

Important Files Changed

Filename Overview
scripts/svelte-package-bazel-wrapper.mjs New wrapper script that stages source into a writable temp project before invoking the svelte-package CLI; contains a fragile mkdirSync return-value pattern that sets workDir to undefined if the directory already exists.
BUILD.bazel Replaces direct svelte-package invocation with the new wrapper binary; adds copy_to_directory to strip the src/ prefix correctly; version bumped to 0.7.6 consistently; chdir = "." added to sync and typecheck targets.
MODULE.bazel Version bumped from 0.7.5 to 0.7.6, consistent with BUILD.bazel and package.json.
package.json Version bumped from 0.7.5 to 0.7.6, consistent with MODULE.bazel and BUILD.bazel.
AGENTS.md Operational truth updated: date bumped, published package version corrected, 0.7.6 lane described, new Bzlmod consumer thread added.
docs/generated/package-surface.md Generated doc; version field updated to 0.7.6.
docs/generated/release-metadata.md Generated doc; all three version fields updated to 0.7.6.

Sequence Diagram

sequenceDiagram
    participant Bazel as Bazel (js_run_binary)
    participant Wrapper as svelte-package-bazel-wrapper.mjs
    participant FS as Filesystem (os.tmpdir)
    participant CLI as @sveltejs/package CLI

    Bazel->>Wrapper: spawn with args [-i scheduling_kit_src, -o dist]
    Wrapper->>Wrapper: resolveExistingPath(scheduling_kit_src)
    Wrapper->>FS: mkdtempSync → tempRoot
    Wrapper->>FS: mkdirSync(tempRoot/work) → workDir
    Wrapper->>FS: symlinkSync(scheduling_kit_src → workDir/src)
    Wrapper->>FS: symlinkSync(package.json, svelte.config.js, tsconfig.json)
    Wrapper->>FS: cpSync(.svelte-kit → workDir/.svelte-kit)
    Wrapper->>FS: makeWritable(workDir/.svelte-kit)
    Wrapper->>FS: symlinkSync(node_modules → workDir/node_modules)
    Wrapper->>CLI: spawnSync(node cli.js -i src -o /abs/dist, cwd=workDir)
    CLI-->>Wrapper: exit status
    Wrapper->>FS: rmSync(tempRoot, recursive)
    Wrapper-->>Bazel: exit(status)
Loading

Reviews (1): Last reviewed commit: "fix: make kit Bazel package consumer-saf..." | Re-trigger Greptile

const tempRoot = mkdtempSync(
path.join(os.tmpdir(), "scheduling-kit-package-"),
);
const workDir = mkdirSync(path.join(tempRoot, "work"), { recursive: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 mkdirSync with { recursive: true } returns string | undefined — it returns undefined when the target directory already exists. Assigning its return value to workDir means that on any retry or unusual condition where tempRoot/work somehow pre-exists, path.join(workDir, "src") on the next line throws TypeError: The "path" argument must be of type string. Received undefined. The conventional fix is to build the path first and pass it to mkdirSync as a side-effect only.

Suggested change
const workDir = mkdirSync(path.join(tempRoot, "work"), { recursive: true });
const workDir = path.join(tempRoot, "work");
mkdirSync(workDir, { recursive: true });

Comment on lines +43 to +68
path.join(
packageRoot,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
),
path.join(
originalCwd,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
),
process.env.JS_BINARY__EXECROOT
? path.join(
process.env.JS_BINARY__EXECROOT,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
)
: undefined,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The internal path src/cli.js inside @sveltejs/package is not a public API contract. Future releases of that package could restructure to dist/cli.js or similar, silently breaking this lookup with a confusing "Unable to locate" error. Using the package's bin symlink through node_modules/.bin/svelte-package would be more resilient.

Suggested change
path.join(
packageRoot,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
),
path.join(
originalCwd,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
),
process.env.JS_BINARY__EXECROOT
? path.join(
process.env.JS_BINARY__EXECROOT,
"node_modules",
"@sveltejs",
"package",
"src",
"cli.js",
)
: undefined,
path.join(packageRoot, "node_modules", ".bin", "svelte-package"),
path.join(originalCwd, "node_modules", ".bin", "svelte-package"),
process.env.JS_BINARY__EXECROOT
? path.join(
process.env.JS_BINARY__EXECROOT,
"node_modules",
".bin",
"svelte-package",
)
: undefined,

Comment on lines +100 to +123
function prepareWritableProject(inputDir) {
const tempRoot = mkdtempSync(
path.join(os.tmpdir(), "scheduling-kit-package-"),
);
const workDir = mkdirSync(path.join(tempRoot, "work"), { recursive: true });

linkOrCopy(inputDir, path.join(workDir, "src"));
for (const file of ["package.json", "svelte.config.js", "tsconfig.json"]) {
linkOrCopy(resolveExistingPath(file), path.join(workDir, file));
}

const svelteKitDir = resolveExistingPath(".svelte-kit");
if (existsSync(svelteKitDir)) {
linkOrCopy(svelteKitDir, path.join(workDir, ".svelte-kit"), true);
makeWritable(path.join(workDir, ".svelte-kit"));
}

const nodeModulesDir = resolveExistingPath("node_modules");
if (existsSync(nodeModulesDir)) {
linkOrCopy(nodeModulesDir, path.join(workDir, "node_modules"));
}

return { tempRoot, workDir };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Temp directory leaked on setup exceptions

If prepareWritableProject throws (e.g., symlinkSync fails because a target path already exists, or resolveExistingPath returns a bad path for package.json), tempRoot is never passed back to the caller and rmSync(tempRoot, ...) on line 174 is never reached. Each failed invocation silently accumulates a scheduling-kit-package-* directory under os.tmpdir(). Wrapping the setup and spawn in a try/finally would close this gap.

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.

1 participant