From 9f2a54a8f67020fb283855967fc853bc592ce42d Mon Sep 17 00:00:00 2001 From: Sucukdeluxe <259325684+Sucukdeluxe@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:03:44 +0200 Subject: [PATCH] fix(ci): canonicalize 8.3 short paths in publish-lock diagnostics matching assertLockedTargetFailure compared the rename paths from the product publish-lock diagnostic against the expected output file with path.resolve only. On runners whose temporary directory surfaces as a Windows 8.3 short path the smoke passes a short-path output file while the product logs canonical long paths, so a correct atomic publish lock diagnostic was rejected and the cutter media matrix failed. sameResolvedPath now canonicalizes both sides through the existing resolveCanonicalPath helper with a resolve fallback, covered by a ShortPath contract test. --- scripts/smoke-test-cutter-media-matrix.js | 12 +++++++++-- .../smoke-test-cutter-media-matrix.test.js | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/scripts/smoke-test-cutter-media-matrix.js b/scripts/smoke-test-cutter-media-matrix.js index 27caf36..b55fa78 100644 --- a/scripts/smoke-test-cutter-media-matrix.js +++ b/scripts/smoke-test-cutter-media-matrix.js @@ -665,10 +665,18 @@ function analyzeExport(environment, runtime, definition, source) { }; } +function canonicalComparablePath(candidatePath) { + try { + return resolveCanonicalPath(candidatePath); + } catch { + return path.resolve(candidatePath); + } +} + function sameResolvedPath(left, right) { if (typeof left !== 'string' || typeof right !== 'string') return false; - const resolvedLeft = path.resolve(left); - const resolvedRight = path.resolve(right); + const resolvedLeft = canonicalComparablePath(left); + const resolvedRight = canonicalComparablePath(right); return process.platform === 'win32' ? resolvedLeft.toLowerCase() === resolvedRight.toLowerCase() : resolvedLeft === resolvedRight; diff --git a/scripts/smoke-test-cutter-media-matrix.test.js b/scripts/smoke-test-cutter-media-matrix.test.js index 7c57b97..069ff44 100644 --- a/scripts/smoke-test-cutter-media-matrix.test.js +++ b/scripts/smoke-test-cutter-media-matrix.test.js @@ -458,6 +458,27 @@ test('runner lifecycle still restores and cleans up when bounded app close fails assert.equal(fs.existsSync(environment.rootDir), false); }); +test('locked target accepts canonical long-path diagnostics for a short-path output file', { skip: process.platform !== 'win32' }, (t) => { + const environment = createEnvironment(); + t.after(() => fs.rmSync(environment.rootDir, { recursive: true, force: true })); + const longRoot = fs.realpathSync.native(environment.rootDir); + const shortRoot = getWindowsShortPath(environment.rootDir); + if (!shortRoot || shortRoot.toLowerCase() === longRoot.toLowerCase()) { + t.skip('8.3 short names are unavailable'); + return; + } + const outputFile = path.join(shortRoot, 'result.mp4'); + const before = '[2026-08-13T00:00:00.000Z] startup'; + const after = `${before}\n[2026-08-13T00:00:01.000Z] video-editor-export-failed | Error: EBUSY: resource busy or locked, rename '${path.join(longRoot, '.result.tvm-edit.mp4')}' -> '${path.join(longRoot, 'result.mp4')}'`; + assert.doesNotThrow(() => assertLockedTargetFailure({ + result: { success: false, outputName: null }, + debugBefore: before, + debugAfter: after, + outputFile, + runtimeIssues: [] + })); +}); + test('locked target requires a resolved production publish failure with a Windows lock diagnostic', () => { const before = '[2026-08-13T00:00:00.000Z] startup'; const outputFile = 'C:\\media\\result.mp4';