Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15x 15x 15x 15x 15x 15x 4x 4x 4x 4x 4x 4x 11x 15x 7x 7x 4x 4x 4x 4x 4x 4x 4x 3x 3x 4x 2x 2x 2x 2x 2x 2x 2x 2x 4x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 15x 1x | /**
* Executor Factory
*
* Selects the appropriate executor (Docker or Native) based on
* configuration, job requirements, and system capabilities.
*/
import { Executor } from './types.js';
import { NativeExecutor } from './nativeExecutor.js';
import { NativeExecutionConfig } from '../config/types.js';
export interface ExecutorFactoryConfig {
mode: 'docker' | 'native' | 'auto';
nativeConfig?: NativeExecutionConfig;
dockerAvailable?: boolean;
jobRequirements?: {
requiredOS?: string;
executionMode?: string;
};
}
/**
* Marker class representing the Docker executor type.
* The actual Docker executor implementation lives in docker.ts / jobExecutor.ts.
* This stub is used for factory selection only, avoiding a hard dependency on dockerode.
*/
export class DockerExecutorStub implements Executor {
readonly type = 'docker' as const;
async validate(): Promise<{ valid: boolean; errors: string[] }> {
return { valid: true, errors: [] };
}
async execute(): Promise<never> {
throw new Error(
'DockerExecutorStub.execute() should not be called directly. ' +
'Use the full DockerManager-based JobExecutor for Docker execution.'
);
}
async cleanup(): Promise<void> {
// no-op
}
}
export class ExecutorFactory {
/**
* Create the appropriate executor for a job.
*
* Selection logic:
* 1. If job explicitly requests 'native' -> NativeExecutor
* 2. If job explicitly requests 'docker' -> DockerExecutorStub
* 3. If mode is 'auto':
* a. If job requires macOS-only tools (xcode, ios) -> NativeExecutor
* b. If Docker is available -> DockerExecutorStub
* c. Else -> NativeExecutor (fallback)
*/
static create(config: ExecutorFactoryConfig): Executor {
const { mode, nativeConfig, dockerAvailable, jobRequirements } = config;
// Check if job explicitly requests an execution mode
const jobMode = jobRequirements?.executionMode;
if (jobMode === 'native' || mode === 'native') {
return new NativeExecutor({
allowedPaths: nativeConfig?.allowedPaths,
userIsolation: nativeConfig?.userIsolation,
sandboxProfile: nativeConfig?.sandboxProfile,
});
}
if (jobMode === 'docker' || mode === 'docker') {
return new DockerExecutorStub();
}
// Auto mode: inspect job requirements
if (mode === 'auto') {
// macOS-only tools require native execution
const requiredOS = jobRequirements?.requiredOS?.toLowerCase() ?? '';
if (
requiredOS === 'macos' ||
requiredOS === 'darwin' ||
requiredOS === 'ios'
) {
return new NativeExecutor({
allowedPaths: nativeConfig?.allowedPaths,
userIsolation: nativeConfig?.userIsolation,
sandboxProfile: nativeConfig?.sandboxProfile,
});
}
// Prefer Docker when available
if (dockerAvailable !== false) {
return new DockerExecutorStub();
}
// Fallback to native
return new NativeExecutor({
allowedPaths: nativeConfig?.allowedPaths,
userIsolation: nativeConfig?.userIsolation,
sandboxProfile: nativeConfig?.sandboxProfile,
});
}
// Default: Docker
return new DockerExecutorStub();
}
}
|