Skip to content

feat(build): port scripts/build.mts to shared build-pipeline orchestrator#1265

Open
John-David Dalton (jdalton) wants to merge 3 commits intomainfrom
jdd/build-pipeline-port
Open

feat(build): port scripts/build.mts to shared build-pipeline orchestrator#1265
John-David Dalton (jdalton) wants to merge 3 commits intomainfrom
jdd/build-pipeline-port

Conversation

@jdalton
Copy link
Copy Markdown
Contributor

@jdalton John-David Dalton (jdalton) commented Apr 23, 2026

Summary

Fifth copy of the shared build-pipeline orchestrator that socket-btm, ultrathink, socket-tui, and sdxgen already use. API surface (manifest-of-stages, --force/--clean/--clean-stage/--from-stage/--cache-key CLI, checkpoint JSONs under build/<mode>/) is identical to the other four repos.

socket-cli doesn't build wasm — it consumes pre-built wasm + node binaries from socket-btm. The orchestrator is build-type-agnostic; the module name reflects the machine, not one category of consumer.

What landed

  • packages/build-infra/lib/ additions: build-pipeline.mts, checkpoint-manager.mts, constants.mts, external-tools-schema.{mts,json}, platform-mappings.mts, version-helpers.mts. Coexist with the existing esbuild/platform-targets/github-releases helpers — no touching pre-existing files.
  • constants.mts: socket-cli's own checkpoint chain (CLI → SEA → FINALIZED).
  • build-pipeline.mts: adds skip?: (ctx) => boolean dynamic skip predicate (socket-cli's SEA stage needs it — only runs on --force/--prod). skipInDev stays for fleet parity.
  • scripts/build.mts: replaces runSmartBuild's procedural loop with runPipelineCli. Existing buildPackage / buildCurrentPlatformSea helpers wrap as stage workers; dispatch paths for --platforms / --targets / --target unchanged.
  • Platform pinned to 'universal' via resolvePlatformArch so the cache key stays stable across runner OSes (bundled CLI JS is universal).
  • Checkpoints at build/<mode>/checkpoints/ matching socket-tui + sdxgen.

Drive-by changes

  • Bump @socketsecurity/lib catalog pin 5.21 → 5.24. 5.21's /errors subpath shipped CJS without named-export interop, so import { errorMessage } from '@socketsecurity/lib/errors' failed under Node's ESM-to-CJS resolver. 5.24 ships the interop (already in use by socket-tui, ultrathink, sdxgen).
  • Add @sinclair/typebox to catalog (required by external-tools-schema.mts).

Test plan

  • pnpm build completes in 16s, CLI Package builds, SEA correctly skipped
  • pnpm build on cached tree: 0.0s, all stages skipped via checkpoint JSON
  • pnpm build --help / --target / --platforms paths unchanged
  • pnpm build --cache-key emits v<node>-universal-<mode>-<hash>-<pkgver>
  • pnpm build --clean-stage=<name> surgically reruns from that stage on
  • Repo lint passes

Note

Medium Risk
Moderate risk because it replaces the default build orchestration and caching behavior; issues could cause builds to skip incorrectly or clean/rebuild unexpectedly across stages.

Overview
Replaces scripts/build.mts’s procedural “smart build” flow with a declarative runPipelineCli pipeline, adding stage checkpoints (cli, sea, finalized) plus support for --clean, --clean-stage, --from-stage, and --cache-key (with a fixed platformArch of universal).

Adds new build-infra modules for the orchestrator (build-pipeline.mts), checkpoint hashing/markers (checkpoint-manager.mts), platform/libc mapping helpers, version helpers, and external-tools.json validation (TypeBox schema), and exports them from packages/build-infra/package.json.

Updates dependencies to include @sinclair/typebox and bumps @socketsecurity/lib to 5.24.0 in the workspace/lockfile.

Reviewed by Cursor Bugbot for commit 7ac5366. Configure here.

…ator

Fifth copy of the shared build-pipeline system (socket-btm + ultrathink +
socket-tui + sdxgen all use it). API surface is identical across repos —
manifest-of-stages, --force/--clean/--clean-stage/--from-stage/
--cache-key CLI, checkpoint JSONs under build/<mode>/.

What landed
- packages/build-infra/lib: adds checkpoint-manager, constants,
  external-tools-schema, platform-mappings, version-helpers,
  build-pipeline alongside the existing esbuild/platform-targets/
  github-releases helpers. Coexists — no touching the pre-existing files.
- constants.mts: socket-cli's own checkpoint chain
  (CLI → SEA → FINALIZED). No wasm verbs — socket-cli consumes pre-built
  wasm + node binaries from socket-btm; same orchestrator drives a pure
  JS build, the module name 'build-pipeline' reflects that.
- build-pipeline.mts: add `skip?: (ctx) => boolean` dynamic skip
  predicate. skipInDev stays for fleet parity; skip is for dynamic
  conditions like socket-cli's SEA stage (only runs on --force/--prod).
- scripts/build.mts: replace runSmartBuild's procedural loop with a
  runPipelineCli call. Existing buildPackage/buildCurrentPlatformSea
  helpers are wrapped as stage workers; the existing BUILD_PACKAGES
  signature system still runs inside buildPackage's body, complementing
  the orchestrator's own cache-hash layer (the two aren't fighting —
  one works on file-glob inputs, the other on content hashes of
  sourcePaths + platform metadata).
- Dispatch paths unchanged: --platforms / --targets / --target still
  route to runParallelBuilds / runSequentialBuilds / runTargetedBuild
  (the orchestrator only replaces the default smart-build path).
- Platform pinned to 'universal' via resolvePlatformArch so the cache
  key stays stable across runner OSes (bundled CLI JS is universal).
- Checkpoints at build/<mode>/checkpoints/ matching socket-tui + sdxgen.

Bump @socketsecurity/lib catalog pin 5.21 → 5.24. 5.21's /errors
subpath shipped CJS without named-export interop, so `import
{ errorMessage } from '@socketsecurity/lib/errors'` failed under
Node's ESM-to-CJS resolver. 5.24 ships the interop (already in use
by socket-tui, ultrathink, socket-sdxgen).

Also: add @sinclair/typebox to catalog (needed by
external-tools-schema.mts).

Verified locally: `pnpm build` completes in 16s, CLI Package builds,
SEA correctly skipped (skip predicate), FINALIZED writes checkpoint.
Cached rerun: 0.0s. --help / --target / --platforms paths unchanged.
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 23, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​sinclair/​typebox@​0.34.4910010010090100
Updatednpm/​@​socketsecurity/​lib@​5.21.0 ⏵ 5.24.0100100100100100

View full report

@socket-security-staging
Copy link
Copy Markdown

socket-security-staging Bot commented Apr 23, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​sinclair/​typebox@​0.34.498710010090100
Updatednpm/​@​socketsecurity/​lib@​5.21.0 ⏵ 5.24.088 -11100100100100

View full report

@socket-security-staging
Copy link
Copy Markdown

socket-security-staging Bot commented Apr 23, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @sinclair/typebox is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: packages/build-infra/package.jsonnpm/@sinclair/typebox@0.34.49

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity-Staging ignore npm/@sinclair/typebox@0.34.49. You can also ignore all packages with @SocketSecurity-Staging ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @socketsecurity/lib is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package.jsonnpm/@socketsecurity/lib@5.24.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity-Staging ignore npm/@socketsecurity/lib@5.24.0. You can also ignore all packages with @SocketSecurity-Staging ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Comment thread packages/build-infra/lib/build-pipeline.mts Outdated
Comment thread packages/build-infra/lib/constants.mts
Comment thread packages/build-infra/lib/build-pipeline.mts
- loadExternalTools() now inspects validateExternalTools's return value.
  The function returns { ok, errors? } per its own JSDoc; the previous
  call discarded it, so malformed external-tools.json silently passed
  through. Throw on validation failure with the formatted issue list.
- validateCheckpointChain error message now enumerates Object.values
  (the actual checkpoint strings like 'cli', 'finalized') instead of
  Object.keys (the enum accessors like CLI, FINALIZED) so suggestions
  match what callers actually pass.
- runPipelineCli no longer logs the thrown error before re-throwing —
  callers already have a top-level catch that formats the failure, so
  we were showing the same message twice. Exit code is still set here
  so a consumer that forgets the catch still fails the process.

Reported on PR #1265.
@jdalton
Copy link
Copy Markdown
Contributor Author

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7ac5366. Configure here.

Comment thread scripts/build.mts
}
return {}
},
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SEA stage missing CLI output dependency causes stale builds

Medium Severity

The SEA stage declares no sourcePaths, so its checkpoint hash only covers external-tools.json and root package.json (added by runStage). It doesn't include the CLI output file (cliOutputPath) that the SEA binary is built from. In --prod mode (the CI default via getCI()), where --force is not set, the SEA skip predicate allows it to run — but shouldRun finds its checkpoint hash unchanged after a CLI rebuild and skips it. The result is a stale SEA binary built from a previous CLI output. Adding sourcePaths: [cliOutputPath] to the SEA stage definition would fix this.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7ac5366. Configure here.

Cursor bugbot flagged the SEA stage as missing sourcePaths: its
checkpoint hash only covered external-tools.json + root package.json
(the two package-wide inputs runStage always adds). If CLI rebuilt
but those files didn't change, shouldRun would find the SEA
checkpoint hash unchanged and skip SEA — leaving a stale binary
built from the previous dist/index.js.

Add cliOutputPath to the SEA stage's sourcePaths so any CLI rebuild
invalidates the SEA checkpoint and forces a rebuild of the binary.

The other two findings on this PR (validateCheckpointChain wording,
runPipelineCli double-log) were cursor re-flagging issues already
fixed in commit 7ac5366 — current code uses Object.values and no
longer logs in runPipelineCli.
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