@nx/docker
Version:
115 lines (114 loc) • 4.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LARGE_BUFFER = void 0;
exports.default = dockerReleasePublish;
const devkit_1 = require("@nx/devkit");
const internal_1 = require("@nx/devkit/internal");
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const version_utils_1 = require("../../release/version-utils");
exports.LARGE_BUFFER = 1024 * 1000000;
async function dockerReleasePublish(schema, context) {
const projectConfig = context.projectGraph.nodes[context.projectName];
const options = await normalizeOptions(projectConfig, schema);
if (!options.dryRun) {
const digest = await dockerPush(options.imageReference, options.quiet);
devkit_1.logger.log(`Successfully pushed ${options.imageReference}${options.quiet ? `. Digest: ${digest}` : ''}`);
}
else {
devkit_1.logger.log(`Docker Image ${options.imageReference} was not pushed as --dry-run is enabled.`);
}
return {
success: true,
};
}
async function normalizeOptions(projectConfig, schema) {
return {
quiet: schema.quiet ?? false,
imageReference: await findImageReference(projectConfig, schema),
dryRun: process.env.NX_DRY_RUN === 'true' || schema.dryRun || false,
};
}
async function findImageReference(projectConfig, schema) {
let imageRef = readVersionFromFile(projectConfig.data.root);
if (imageRef) {
if (await checkDockerImageExistsLocally(imageRef)) {
return imageRef;
}
throw new Error(`Could not find Docker Image ${imageRef}. Did you run 'nx release version'?`);
}
}
function readVersionFromFile(projectRoot) {
const versionFilePath = (0, version_utils_1.getDockerVersionPath)(devkit_1.workspaceRoot, projectRoot);
if (!(0, fs_1.existsSync)(versionFilePath)) {
throw new Error(`Could not find ${versionFilePath} file. Did you run 'nx release version'?`);
}
const version = (0, fs_1.readFileSync)(versionFilePath, { encoding: 'utf8' });
return version.trim();
}
async function checkDockerImageExistsLocally(imageRef) {
try {
return await new Promise((res) => {
// If the ref starts with 'docker.io/', then we need to strip it since it is the default value and Docker CLI will not find it.
const normalizedImageRef = imageRef.startsWith('docker.io/')
? imageRef.split('docker.io/')[1]
: imageRef;
const childProcess = (0, child_process_1.exec)(`docker images --filter "reference=${normalizedImageRef}" --quiet`, { encoding: 'utf8', windowsHide: true });
let result = '';
childProcess.stdout?.on('data', (data) => {
result += data;
});
childProcess.stderr?.on('data', (data) => {
console.error(data);
});
childProcess.on('error', (error) => {
console.error('Docker command failed:', error);
res(false);
});
childProcess.on('exit', () => {
res(result.trim().length > 0);
});
});
}
catch {
return false;
}
}
async function dockerPush(imageReference, quiet) {
try {
return await new Promise((res, rej) => {
const childProcess = (0, child_process_1.exec)(`docker push ${imageReference}${quiet ? ' --quiet' : ''}`, {
encoding: 'utf8',
maxBuffer: exports.LARGE_BUFFER,
windowsHide: true,
});
let result = '';
childProcess.stdout?.on('data', (data) => {
result += data;
if (!quiet) {
console.log(data);
}
});
childProcess.stderr?.on('data', (data) => {
console.error(data);
});
childProcess.on('error', (error) => {
rej(error);
});
childProcess.on('exit', (code, signal) => {
if (code === null)
code = (0, internal_1.signalToCode)(signal);
if (code === 0) {
res(result.trim());
}
else {
rej(new Error(`Docker push failed with exit code ${code}`));
}
});
});
}
catch (e) {
devkit_1.logger.error(`Failed to push ${imageReference}`);
throw e;
}
}