feat(build): add support for selective builds, platform override and build timeout
This commit is contained in:
@@ -2,7 +2,7 @@ import * as plugins from './tsdocker.plugins.js';
|
||||
import * as paths from './tsdocker.paths.js';
|
||||
import { logger } from './tsdocker.logging.js';
|
||||
import { DockerRegistry } from './classes.dockerregistry.js';
|
||||
import type { IDockerfileOptions, ITsDockerConfig } from './interfaces/index.js';
|
||||
import type { IDockerfileOptions, ITsDockerConfig, IBuildCommandOptions } from './interfaces/index.js';
|
||||
import type { TsDockerManager } from './classes.tsdockermanager.js';
|
||||
import * as fs from 'fs';
|
||||
|
||||
@@ -136,9 +136,12 @@ export class Dockerfile {
|
||||
/**
|
||||
* Builds the corresponding real docker image for each Dockerfile class instance
|
||||
*/
|
||||
public static async buildDockerfiles(sortedArrayArg: Dockerfile[]): Promise<Dockerfile[]> {
|
||||
public static async buildDockerfiles(
|
||||
sortedArrayArg: Dockerfile[],
|
||||
options?: { platform?: string; timeout?: number },
|
||||
): Promise<Dockerfile[]> {
|
||||
for (const dockerfileArg of sortedArrayArg) {
|
||||
await dockerfileArg.build();
|
||||
await dockerfileArg.build(options);
|
||||
}
|
||||
return sortedArrayArg;
|
||||
}
|
||||
@@ -362,15 +365,19 @@ export class Dockerfile {
|
||||
/**
|
||||
* Builds the Dockerfile
|
||||
*/
|
||||
public async build(): Promise<void> {
|
||||
public async build(options?: { platform?: string; timeout?: number }): Promise<void> {
|
||||
logger.log('info', 'now building Dockerfile for ' + this.cleanTag);
|
||||
const buildArgsString = await Dockerfile.getDockerBuildArgs(this.managerRef);
|
||||
const config = this.managerRef.config;
|
||||
const platformOverride = options?.platform;
|
||||
const timeout = options?.timeout;
|
||||
|
||||
let buildCommand: string;
|
||||
|
||||
// Check if multi-platform build is needed
|
||||
if (config.platforms && config.platforms.length > 1) {
|
||||
if (platformOverride) {
|
||||
// Single platform override via buildx
|
||||
buildCommand = `docker buildx build --platform ${platformOverride} --load -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
||||
} else if (config.platforms && config.platforms.length > 1) {
|
||||
// Multi-platform build using buildx
|
||||
const platformString = config.platforms.join(',');
|
||||
buildCommand = `docker buildx build --platform ${platformString} -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
||||
@@ -386,11 +393,27 @@ export class Dockerfile {
|
||||
buildCommand = `docker build --label="version=${versionLabel}" -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
||||
}
|
||||
|
||||
const result = await smartshellInstance.exec(buildCommand);
|
||||
if (result.exitCode !== 0) {
|
||||
logger.log('error', `Build failed for ${this.cleanTag}`);
|
||||
console.log(result.stdout);
|
||||
throw new Error(`Build failed for ${this.cleanTag}`);
|
||||
if (timeout) {
|
||||
// Use streaming execution with timeout
|
||||
const streaming = await smartshellInstance.execStreaming(buildCommand);
|
||||
const timeoutPromise = new Promise<never>((_, reject) => {
|
||||
setTimeout(() => {
|
||||
streaming.childProcess.kill();
|
||||
reject(new Error(`Build timed out after ${timeout}s for ${this.cleanTag}`));
|
||||
}, timeout * 1000);
|
||||
});
|
||||
const result = await Promise.race([streaming.finalPromise, timeoutPromise]);
|
||||
if (result.exitCode !== 0) {
|
||||
logger.log('error', `Build failed for ${this.cleanTag}`);
|
||||
throw new Error(`Build failed for ${this.cleanTag}`);
|
||||
}
|
||||
} else {
|
||||
const result = await smartshellInstance.exec(buildCommand);
|
||||
if (result.exitCode !== 0) {
|
||||
logger.log('error', `Build failed for ${this.cleanTag}`);
|
||||
console.log(result.stdout);
|
||||
throw new Error(`Build failed for ${this.cleanTag}`);
|
||||
}
|
||||
}
|
||||
|
||||
logger.log('ok', `Built ${this.cleanTag}`);
|
||||
|
||||
Reference in New Issue
Block a user