@invarn/cibuild 1.4.9 → 1.5.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAkBxD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,4HAA4H;IAC5H,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sHAAsH;IACtH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAUrD,CAAC;AAgDF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YAsGzF,iBAAiB;CA+HhC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YAuKzF,iBAAiB;CAqHhC"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAkBxD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,4HAA4H;IAC5H,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sHAAsH;IACtH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAUrD,CAAC;AAgDF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YAsGzF,iBAAiB;CA+HhC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YA4JzF,iBAAiB;CA0GhC"}
@@ -386,20 +386,9 @@ export class CachePushStepExecutor extends BaseStepExecutor {
386
386
  commands.push(' echo "Paths to cache:"');
387
387
  commands.push(' printf " %s\\n" "${PATHS_TO_CACHE[@]}"');
388
388
  }
389
- // Acquire lock with shlock
390
- commands.push(' LOCK_FILE="$CACHE_FILE.lock"');
391
- commands.push(' __ci_lock_tries=0');
392
- commands.push(' while ! shlock -f "$LOCK_FILE" -p $$; do');
393
- commands.push(' __ci_lock_tries=$((__ci_lock_tries + 1))');
394
- commands.push(' if [ "$__ci_lock_tries" -ge 30 ]; then');
395
- commands.push(' echo "Warning: cache push lock timeout, skipping"');
396
- commands.push(' rm -f "$LOCK_FILE"');
397
- commands.push(' exit 0');
398
- commands.push(' fi');
399
- commands.push(' sleep 1');
400
- commands.push(' done');
389
+ // Atomic write: .tmp + rename. No lock needed — runs are serialized per runner,
390
+ // and cross-writer races resolve to last-writer-wins without corruption.
401
391
  commands.push(' tar -cf - "${PATHS_TO_CACHE[@]}" 2>/dev/null | zstd -3 > "$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE" || true');
402
- commands.push(' rm -f "$LOCK_FILE"');
403
392
  commands.push(' if [ -f "$CACHE_FILE" ]; then');
404
393
  commands.push(' echo "Cache created successfully"');
405
394
  if (isDebugMode) {
@@ -493,21 +482,10 @@ export class CachePushStepExecutor extends BaseStepExecutor {
493
482
  commands.push(' echo "Cache already up to date for key: $CACHE_KEY"');
494
483
  commands.push('elif [ ${#PATHS_TO_CACHE[@]} -gt 0 ]; then');
495
484
  commands.push(' echo "Caching ${#PATHS_TO_CACHE[@]} path(s)..."');
496
- // Acquire lock with shlock (macOS-native, stale-lock safe via PID check)
497
- commands.push(' LOCK_FILE="$CACHE_FILE.lock"');
498
- commands.push(' __ci_lock_tries=0');
499
- commands.push(' while ! shlock -f "$LOCK_FILE" -p $$; do');
500
- commands.push(' __ci_lock_tries=$((__ci_lock_tries + 1))');
501
- commands.push(' if [ "$__ci_lock_tries" -ge 30 ]; then');
502
- commands.push(' echo "Warning: cache push lock timeout, skipping"');
503
- commands.push(' rm -f "$LOCK_FILE"');
504
- commands.push(' exit 0');
505
- commands.push(' fi');
506
- commands.push(' sleep 1');
507
- commands.push(' done');
508
- // Atomic write: compress to .tmp, then mv (peers never see half-written files)
485
+ // Atomic write: compress to .tmp, then mv. No lock needed runs are
486
+ // serialized per runner and cross-writer races resolve to last-writer-wins
487
+ // without corruption. shlock was flaky on the virtiofs cache mount.
509
488
  commands.push(' tar -cf - "${PATHS_TO_CACHE[@]}" 2>/dev/null | zstd -3 > "$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE" || true');
510
- commands.push(' rm -f "$LOCK_FILE"');
511
489
  commands.push(' if [ -f "$CACHE_FILE" ]; then');
512
490
  commands.push(' echo "Cache created successfully"');
513
491
  if (isDebugMode) {
@@ -310,21 +310,18 @@ describe('Step Implementations', () => {
310
310
  const executor = new CachePushStepExecutor();
311
311
  await expect(executor.execute({ technology: 'unknown' }, {}, testConfig)).rejects.toThrow("Unknown cache technology 'unknown'");
312
312
  });
313
- test('should use shlock locking for preset push', async () => {
313
+ test('should not use shlock (flaky on virtiofs cache mount) for preset push', async () => {
314
314
  const executor = new CachePushStepExecutor();
315
315
  const result = await executor.execute({ technology: 'cocoapods' }, {}, testConfig);
316
- expect(result.script).toContain('shlock -f "$LOCK_FILE" -p $$');
317
- expect(result.script).toContain('LOCK_FILE="$CACHE_FILE.lock"');
318
- expect(result.script).toContain('rm -f "$LOCK_FILE"');
319
- // Lock timeout after 30 retries
320
- expect(result.script).toContain('__ci_lock_tries');
321
- expect(result.script).toContain('-ge 30');
322
- });
323
- test('should use shlock locking for manual cache_key push', async () => {
316
+ expect(result.script).not.toContain('shlock');
317
+ expect(result.script).not.toContain('LOCK_FILE');
318
+ expect(result.script).not.toContain('__ci_lock_tries');
319
+ });
320
+ test('should not use shlock for manual cache_key push', async () => {
324
321
  const executor = new CachePushStepExecutor();
325
322
  const result = await executor.execute({ cache_key: 'my-key', cache_paths: ['build'] }, {}, testConfig);
326
- expect(result.script).toContain('shlock -f "$LOCK_FILE" -p $$');
327
- expect(result.script).toContain('rm -f "$LOCK_FILE"');
323
+ expect(result.script).not.toContain('shlock');
324
+ expect(result.script).not.toContain('LOCK_FILE');
328
325
  });
329
326
  test('should use atomic write (tmp + mv) for preset push', async () => {
330
327
  const executor = new CachePushStepExecutor();
@@ -332,6 +329,12 @@ describe('Step Implementations', () => {
332
329
  expect(result.script).toContain('> "$CACHE_FILE.tmp"');
333
330
  expect(result.script).toContain('mv "$CACHE_FILE.tmp" "$CACHE_FILE"');
334
331
  });
332
+ test('should use atomic write (tmp + mv) for manual cache_key push', async () => {
333
+ const executor = new CachePushStepExecutor();
334
+ const result = await executor.execute({ cache_key: 'my-key', cache_paths: ['build'] }, {}, testConfig);
335
+ expect(result.script).toContain('> "$CACHE_FILE.tmp"');
336
+ expect(result.script).toContain('mv "$CACHE_FILE.tmp" "$CACHE_FILE"');
337
+ });
335
338
  });
336
339
  describe('XcodeBuildStepExecutor', () => {
337
340
  test('should generate xcodebuild script', async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "1.4.9",
3
+ "version": "1.5.0",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",