UNPKG

@travetto/pack

Version:

Code packing utilities

119 lines (103 loc) 4.74 kB
import path from 'node:path'; import { RuntimeIndex } from '@travetto/runtime'; import { CliCommand, CliFlag, CliUtil, CliValidationError } from '@travetto/cli'; import { Ignore, Required } from '@travetto/schema'; import { DockerPackOperation } from './bin/docker-operation.ts'; import { BasePackCommand, PackOperationShape } from './pack.base'; import { DockerPackConfig } from '../src/types.ts'; const NODE_MAJOR = process.version.match(/\d+/)?.[0] ?? '22'; /** * Standard docker support for pack */ @CliCommand({ with: { module: true } }) export class PackDockerCommand extends BasePackCommand { @CliFlag({ desc: 'Docker Factory source', short: 'df', envVars: ['PACK_DOCKER_FACTORY'] }) dockerFactory = '@travetto/pack/support/pack.dockerfile.ts'; @CliFlag({ desc: 'Docker Image to extend', short: 'di', envVars: ['PACK_DOCKER_IMAGE'] }) dockerImage = `node:${NODE_MAJOR}-alpine`; @CliFlag({ desc: 'Docker Image Name', short: 'dn', envVars: ['PACK_DOCKER_IMAGE'] }) @Required(false) dockerName: string; @CliFlag({ desc: 'Docker Runtime user', short: 'ru', name: 'runtime-user', envVars: ['PACK_DOCKER_RUNTIME_USER'] }) dockerRuntimeUserSrc?: string; @CliFlag({ desc: 'Docker Runtime Packages', short: 'rp', name: 'runtime-package', envVars: ['PACK_DOCKER_RUNTIME_PACKAGES'] }) dockerRuntimePackages: string[] = []; @CliFlag({ desc: 'Docker Image Port', short: 'dp', envVars: ['PACK_DOCKER_PORT'] }) dockerPort: number[] = []; // Publish flags @CliFlag({ desc: 'Docker Stage Only', short: 'ds', envVars: ['PACK_DOCKER_STAGE'] }) dockerStageOnly: boolean = false; @CliFlag({ desc: 'Docker Image Tag', short: 'dt', envVars: ['PACK_DOCKER_TAGS'] }) dockerTag: string[] = ['latest']; @CliFlag({ desc: 'Docker Push Tags', short: 'dx', envVars: ['PACK_DOCKER_PUSH'] }) dockerPush = false; @CliFlag({ desc: 'Docker Build Platform', short: 'db', envVars: ['PACK_DOCKER_BUILD_PLATFORM'] }) dockerBuildPlatform?: string; @CliFlag({ desc: 'Docker Registry', short: 'dr', envVars: ['PACK_DOCKER_REGISTRY'] }) dockerRegistry?: string; @Ignore() dockerRuntime: DockerPackConfig['dockerRuntime']; @Ignore() appFolder = 'app'; @Ignore() defaultUser = this.appFolder; @Ignore() defaultUserId = 2000; async validate(): Promise<CliValidationError[] | undefined> { const errs: CliValidationError[] = []; if (this.dockerPort?.length) { for (let i = 0; i < this.dockerPort.length; i++) { if (this.dockerPort[i] < 1) { errs.push({ source: 'flag', message: `dockerPort[${i}] is less than (1)` }); } else if (this.dockerPort[i] > 65536) { errs.push({ source: 'flag', message: `dockerPort[${i}] is greater than (65536)` }); } } } return errs; } preMain(): void { if (this.dockerFactory.startsWith('.')) { this.dockerFactory = RuntimeIndex.getFromSource(path.resolve(this.dockerFactory))?.import ?? this.dockerFactory; } this.dockerName ??= CliUtil.getSimpleModuleName('<module>', this.module || undefined); // Finalize user/group and ids const [userOrUid, groupOrGid = userOrUid] = (this.dockerRuntimeUserSrc ?? '').split(':'); const groupIsNum = /^\d+$/.test(groupOrGid); const userIsNum = /^\d+$/.test(userOrUid); const uid = userIsNum ? +userOrUid : this.defaultUserId; const gid = groupIsNum ? +groupOrGid : this.defaultUserId; const group = (!groupIsNum ? groupOrGid : undefined) || this.defaultUser; const user = (!userIsNum ? userOrUid : undefined) || this.defaultUser; this.dockerRuntime = { user, uid, group, gid, folder: `/${this.appFolder}`, packages: this.dockerRuntimePackages }; if (this.dockerStageOnly) { if (this.dockerRegistry) { console.warn('Docker Registry is currently ignored due to --docker-build being false'); } if (this.dockerBuildPlatform) { console.warn('Docker Build Platform is currently ignored due to --docker-build being false'); } if (this.dockerPush) { console.warn('Docker Push is currently ignored due to --docker-build being false'); } if (this.dockerTag) { console.warn('Docker Tag is currently ignored due to --docker-build being false'); } } } preHelp(): void { this.dockerName = CliUtil.getSimpleModuleName('<module>'); } getOperations(): PackOperationShape<this>[] { return [ ...super.getOperations(), DockerPackOperation.pullDockerBaseImage, DockerPackOperation.detectDockerImageOs, DockerPackOperation.writeDockerFile, ...this.dockerStageOnly ? [] : [ DockerPackOperation.buildDockerContainer, DockerPackOperation.pushDockerContainer ] ]; } }