test(ql3): harden local console trial on Docker Desktop

This commit is contained in:
whyour
2026-09-02 13:35:13 +08:00
parent 1b223ff2ad
commit a1b21443ba
2 changed files with 276 additions and 33 deletions
@@ -4,13 +4,107 @@ const assert = require('node:assert/strict');
const test = require('node:test');
const {
applicationEphemeralFilesystemArguments,
applicationNetworkArguments,
consoleSurfaceContract,
dockerDesktopMetadataRetryable,
trialTemporaryBaseDirectory,
trialVolumeArguments,
} = require('../../scripts/ql3-local-alpha-trial-kit-live-contract.cjs');
const DIGEST = 'a'.repeat(64);
const RUN_ID = '019f8680-143d-7000-8000-000000000051';
const ATTEMPT_ID = '019f8680-143d-7000-8000-000000000052';
test('uses the Docker Desktop durable temporary volume on macOS', () => {
assert.equal(
trialTemporaryBaseDirectory('darwin', '/private/var/folders/user/T'),
'/private/tmp',
);
assert.equal(
trialTemporaryBaseDirectory('linux', '/tmp/runner'),
'/tmp/runner',
);
});
test('mounts the trial parent so the private deployment root remains a child', () => {
assert.deepEqual(trialVolumeArguments({ mountRoot: '/tmp/trial-parent' }), [
'--volume',
'/tmp/trial-parent:/var/lib',
]);
});
test('retries only observed Docker Desktop metadata propagation failures', () => {
assert.equal(
dockerDesktopMetadataRetryable(
'{"code":"LOCAL_OWNER_PEPPER_UNAVAILABLE"}',
'darwin',
),
true,
);
assert.equal(
dockerDesktopMetadataRetryable(
'{"code":"LOCAL_OWNER_SECRET_DELIVERY_FAILED"}',
'darwin',
),
true,
);
assert.equal(
dockerDesktopMetadataRetryable(
'{"code":"QL3_LOCAL_SETUP_CONFIGURATION_INVALID"}',
'darwin',
),
true,
);
assert.equal(
dockerDesktopMetadataRetryable(
'{"code":"LOCAL_OWNER_CONSOLE_CONFIGURATION_INVALID"}',
'linux',
),
false,
);
assert.equal(
dockerDesktopMetadataRetryable(
'{"code":"LOCAL_OWNER_CLI_CONFIGURATION_INVALID"}',
'darwin',
),
false,
);
});
test('uses a loopback-published relay only for Docker Desktop Console trials', () => {
assert.deepEqual(applicationNetworkArguments('console', 'darwin'), [
'--network',
'bridge',
'--publish',
'127.0.0.1:5700:5701',
]);
assert.deepEqual(applicationNetworkArguments('console', 'linux'), [
'--network',
'host',
]);
assert.deepEqual(applicationNetworkArguments('headless', 'darwin'), [
'--network',
'none',
]);
});
test('uses bounded native filesystems for Darwin trial receipts and artifacts', () => {
assert.deepEqual(
applicationEphemeralFilesystemArguments({ uid: 501, gid: 20 }, 'darwin'),
[
'--tmpfs',
'/var/lib/qinglong3/receipts:rw,nosuid,nodev,noexec,size=4m,mode=0700,uid=501,gid=20',
'--tmpfs',
'/var/lib/qinglong3/artifacts:rw,nosuid,nodev,noexec,size=80m,mode=0700,uid=501,gid=20',
],
);
assert.deepEqual(
applicationEphemeralFilesystemArguments({ uid: 1000, gid: 1000 }, 'linux'),
[],
);
});
function surfaceResponse(status) {
return {
status,
@@ -18,7 +112,7 @@ function surfaceResponse(status) {
};
}
function fixture(startStatus) {
function fixture(startStatus, firstLogStatus = 'pending') {
let runReads = 0;
let logReads = 0;
const calls = [];
@@ -55,6 +149,9 @@ function fixture(startStatus) {
}
if (pathname.includes('/log?')) {
logReads += 1;
if (logReads === 1 && firstLogStatus === 'unavailable') {
return { status: 503, body: { code: 'artifact_unavailable' } };
}
return logReads === 1
? { status: 202, body: { status: 'pending' } }
: {
@@ -73,6 +170,22 @@ function fixture(startStatus) {
};
}
test('bounds Docker Desktop artifact propagation as a pending log state', async () => {
const { adapters } = fixture('accepted', 'unavailable');
adapters.platform = 'darwin';
const result = await consoleSurfaceContract({}, adapters);
assert.equal(result.firstAutomation.logMarkerObserved, true);
});
test('keeps artifact unavailable terminal on Linux', async () => {
const { adapters } = fixture('accepted', 'unavailable');
adapters.platform = 'linux';
await assert.rejects(
consoleSurfaceContract({}, adapters),
/starter Run log became unavailable: status=503, code=artifact_unavailable/,
);
});
for (const startStatus of ['accepted', 'existing']) {
test(`proves one ${startStatus} fenced Run after the log becomes available`, async () => {
const { adapters, calls } = fixture(startStatus);