@invarn/cibuild 2.4.2 → 2.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -52,12 +52,6 @@ export interface TrimDims {
52
52
  export interface TrimHelperInvocation {
53
53
  cmd: string;
54
54
  args: string[];
55
- /** Child environment override. Set only for the pkg self-exec, where the
56
- * node-invoke sentinel (PKG_EXECPATH) must be stripped so the re-executed ci
57
- * binary runs its baked cli entrypoint (dispatching `fidelity-trim`) instead
58
- * of re-entering Node-emulation and treating it as a script path. Absent for
59
- * the other homes, which spawn with the inherited environment unchanged. */
60
- env?: Record<string, string>;
61
55
  }
62
56
  /**
63
57
  * The platform-neutral helpers embedded in the trim-stage script.
@@ -1 +1 @@
1
- {"version":3,"file":"render-post-processor.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/render-post-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,EAAE,MA6HtC,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5C,iFAAiF;AACjF,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;iFAI6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAAC;IAC3D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1F;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,CAAC,EAAE;IACpD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,sBAAsB,CASzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAqBhD"}
1
+ {"version":3,"file":"render-post-processor.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/render-post-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAiItC,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5C,iFAAiF;AACjF,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAAC;IAC3D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1F;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,CAAC,EAAE;IACpD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,sBAAsB,CASzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAqBhD"}
@@ -76,10 +76,15 @@ function parseTrimDims(stdout) {
76
76
  // generated script. Three homes, in order:
77
77
  // 1. CIBUILD_CLI_JS -- an explicit JS entrypoint (preview harnesses, tests),
78
78
  // run under the same node executing this script.
79
- // 2. The pkg-built ci binary re-executing itself -- the production runner
80
- // path, where this script runs under the pkg bootstrap and
81
- // process.execPath IS the ci binary.
82
- // 3. A ci on PATH (brew/npm installs).
79
+ // 2. process.execPath re-executing the pkg binary. NOTE: gated on process.pkg,
80
+ // which is NOT set under pkg Node-emulation (pkg's bootstrap defines it only
81
+ // AFTER its node-invoke early return), so on the runner this branch does not
82
+ // fire -- the generated script runs as 'node the-script' in Node-emulation.
83
+ // 3. A ci on PATH (brew/npm installs) -- the ACTUAL production runner path,
84
+ // precisely because process.pkg is undefined under Node-emulation.
85
+ // Whichever home resolves, runTrimHelper strips PKG_EXECPATH from the child env
86
+ // so the spawned pkg binary dispatches the subcommand instead of re-entering
87
+ // Node-emulation. See runTrimHelper.
83
88
  function trimHelperInvocation(args) {
84
89
  if (process.env.CIBUILD_CLI_JS) {
85
90
  return {
@@ -88,22 +93,7 @@ function trimHelperInvocation(args) {
88
93
  };
89
94
  }
90
95
  if (process.pkg) {
91
- // The runner spawns this script as 'node <script>', which the pkg binary
92
- // intercepts and runs in Node-emulation mode -- so process.env carries
93
- // pkg's node-invoke sentinel (PKG_EXECPATH). Re-execing process.execPath
94
- // with it still set makes the child ci binary ALSO enter Node-emulation and
95
- // treat 'fidelity-trim' as a main-module script path (Cannot find module
96
- // '<cwd>/fidelity-trim'), never reaching the subcommand dispatch -- so the
97
- // trim silently fails and untrimmed renders ship. Strip PKG_EXECPATH from
98
- // the child env so the re-exec runs the baked cli entrypoint, which routes
99
- // 'fidelity-trim' to the in-binary helper (with bundled pngjs).
100
- var invocation = { cmd: process.execPath, args: ['fidelity-trim'].concat(args) };
101
- if (process.env.PKG_EXECPATH !== undefined) {
102
- var appEnv = Object.assign({}, process.env);
103
- delete appEnv.PKG_EXECPATH;
104
- invocation.env = appEnv;
105
- }
106
- return invocation;
96
+ return { cmd: process.execPath, args: ['fidelity-trim'].concat(args) };
107
97
  }
108
98
  return { cmd: 'ci', args: ['fidelity-trim'].concat(args) };
109
99
  }
@@ -112,9 +102,23 @@ function trimHelperInvocation(args) {
112
102
  // stdout line, and exit codes are the retired CoreGraphics helper's contract).
113
103
  function runTrimHelper(args) {
114
104
  var invocation = trimHelperInvocation(args);
115
- var options = { encoding: 'utf-8', maxBuffer: 16 * 1024 * 1024 };
116
- if (invocation.env !== undefined) options.env = invocation.env;
117
- var result = cp.spawnSync(invocation.cmd, invocation.args, options);
105
+ // This script runs under the pkg binary in Node-emulation mode (the runner
106
+ // spawns it as 'node <script>'), so process.env carries pkg's node-invoke
107
+ // sentinel PKG_EXECPATH. Every home above spawns the pkg binary (process.execPath
108
+ // or a 'ci' resolved on PATH); a child that inherits PKG_EXECPATH re-enters
109
+ // Node-emulation and treats 'fidelity-trim' as a main-module script path
110
+ // ("Cannot find module '<cwd>/fidelity-trim'") instead of dispatching the
111
+ // subcommand -- so the trim silently no-ops and untrimmed renders ship. Strip
112
+ // PKG_EXECPATH from the child env so the binary runs its baked cli entrypoint
113
+ // (verified: 'env -u PKG_EXECPATH ci fidelity-trim' dispatches; inheriting
114
+ // PKG_INVOKE_NODEJS reproduces the crash).
115
+ var childEnv = Object.assign({}, process.env);
116
+ delete childEnv.PKG_EXECPATH;
117
+ var result = cp.spawnSync(invocation.cmd, invocation.args, {
118
+ encoding: 'utf-8',
119
+ maxBuffer: 16 * 1024 * 1024,
120
+ env: childEnv,
121
+ });
118
122
  if (result.stdout) process.stdout.write(result.stdout);
119
123
  if (result.stderr) process.stderr.write(result.stderr);
120
124
  if (result.error) {
@@ -97,31 +97,21 @@ describe('trim stage — helper invocation resolution', () => {
97
97
  args: ['fidelity-trim', 'in.png', 'out.png'],
98
98
  });
99
99
  });
100
- // The production runner spawns the render step as `node <script>`, which the
101
- // pkg-built ci binary intercepts and runs in Node-emulation mode — so the
102
- // running script's process.env carries pkg's node-invoke sentinel
103
- // (PKG_EXECPATH). If the trim re-exec inherits it, the child ci binary ALSO
104
- // enters Node-emulation and treats 'fidelity-trim' as a main-module script
105
- // path ("Cannot find module '<cwd>/fidelity-trim'") instead of dispatching
106
- // the subcommand the exact failure observed in production, which silently
107
- // ships untrimmed renders. The re-exec must clear PKG_EXECPATH so the binary
108
- // runs its baked cli entrypoint.
109
- test('under pkg node-emulation the re-exec clears PKG_EXECPATH so the binary runs its app entrypoint', () => {
110
- const { trimHelperInvocation } = internalsWith({
111
- env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS', PATH: '/usr/bin:/bin' },
112
- pkg: {},
113
- execPath: '/opt/homebrew/bin/ci',
114
- });
115
- const invocation = trimHelperInvocation(['in.png', 'out.png']);
116
- expect(invocation.cmd).toBe('/opt/homebrew/bin/ci');
117
- expect(invocation.args).toEqual(['fidelity-trim', 'in.png', 'out.png']);
118
- // A child env is supplied with the node-invoke sentinel removed, but the
119
- // rest of the environment (PATH, etc.) preserved.
120
- expect(invocation.env).toBeDefined();
121
- expect(invocation.env?.PKG_EXECPATH).toBeUndefined();
122
- expect(invocation.env?.PATH).toBe('/usr/bin:/bin');
123
- });
124
- test('runTrimHelper spawns the pkg re-exec with a PKG_EXECPATH-cleared env', () => {
100
+ // Production path + the load-bearing fix. The runner spawns the render step as
101
+ // `node <script>`, which the pkg-built ci binary runs in Node-emulation mode.
102
+ // In that mode pkg's bootstrap returns BEFORE it defines process.pkg, so
103
+ // process.pkg is UNDEFINED here and the resolution above lands on `ci` on PATH
104
+ // (NOT the process.pkg self-exec branch). The script's env still carries pkg's
105
+ // node-invoke sentinel (PKG_EXECPATH=PKG_INVOKE_NODEJS); whichever home is
106
+ // spawned is the pkg binary, and a child that inherits PKG_EXECPATH re-enters
107
+ // Node-emulation and treats 'fidelity-trim' as a main-module script path
108
+ // ("Cannot find module '<cwd>/fidelity-trim'") instead of dispatching the
109
+ // subcommand the exact production failure, which silently ships untrimmed
110
+ // renders. runTrimHelper must strip PKG_EXECPATH from the child env
111
+ // regardless of which home resolved, so the binary runs its baked cli
112
+ // entrypoint. (Verified out-of-band: `env -u PKG_EXECPATH ci fidelity-trim`
113
+ // dispatches; inheriting PKG_INVOKE_NODEJS reproduces the crash.)
114
+ test('runTrimHelper strips PKG_EXECPATH from the child env so the ci re-exec dispatches', () => {
125
115
  const calls = [];
126
116
  const fakeCp = {
127
117
  spawnSync: (...args) => {
@@ -132,9 +122,9 @@ describe('trim stage — helper invocation resolution', () => {
132
122
  const { runTrimHelper } = getPostProcessorInternals({
133
123
  cp: fakeCp,
134
124
  processRef: {
135
- env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS', FOO: 'bar' },
136
- pkg: {},
137
- execPath: '/opt/homebrew/bin/ci',
125
+ // Node-emulation shape: the sentinel is set but process.pkg is NOT.
126
+ env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS', PATH: '/usr/bin:/bin', FOO: 'bar' },
127
+ execPath: '/usr/local/bin/node',
138
128
  stdout: { write: () => true },
139
129
  stderr: { write: () => true },
140
130
  },
@@ -142,9 +132,12 @@ describe('trim stage — helper invocation resolution', () => {
142
132
  runTrimHelper(['in.png', 'out.png']);
143
133
  expect(calls).toHaveLength(1);
144
134
  const [cmd, , options] = calls[0];
145
- expect(cmd).toBe('/opt/homebrew/bin/ci');
135
+ // process.pkg undefined → resolves to `ci` on PATH (the real runner path).
136
+ expect(cmd).toBe('ci');
137
+ // The child env must have the node-invoke sentinel removed, the rest kept.
146
138
  expect(options.env).toBeDefined();
147
139
  expect(options.env?.PKG_EXECPATH).toBeUndefined();
140
+ expect(options.env?.PATH).toBe('/usr/bin:/bin');
148
141
  expect(options.env?.FOO).toBe('bar');
149
142
  });
150
143
  test('runTrimHelper reports a spawn error as status 127 with the message appended', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.4.2",
3
+ "version": "2.4.3",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",