From b94f44d8f46eedf4126e86e1f46195c1a1036f26 Mon Sep 17 00:00:00 2001 From: Scott Mebberson <74628+smebberson@users.noreply.github.com> Date: Mon, 14 Sep 2026 16:18:48 +0930 Subject: [PATCH] Add Docker build secrets support --- bin/c-d-build.js | 48 +++++++++++++++++++++++++++++++++++++++--------- bin/lib/c-kc.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/bin/c-d-build.js b/bin/c-d-build.js index 6506172..72c8faa 100644 --- a/bin/c-d-build.js +++ b/bin/c-d-build.js @@ -8,6 +8,7 @@ const { loadConfig, newline, reportError } = require('./lib/c'); const { flagBuildArgs, formatBuildArgs, + formatBuildSecrets, validateBuildArgs, } = require('./lib/c-kc'); @@ -72,9 +73,34 @@ return loadConfig('docker.locations').then((locations) => { const tag = opts.tag ? opts.tag : 'latest'; const name = opts.name ? opts.name : location; - let cmd = `DOCKER_SCAN_SUGGEST=false docker build -t ${name}:${tag}${formatBuildArgs( + // Extract and set environment variables for build secrets + const buildSecrets = dockerLocation.buildSecrets || {}; + const secretEnvVars = {}; + + if (typeof buildSecrets === 'object' && buildSecrets !== null) { + Object.keys(buildSecrets).forEach((key) => { + const secretValue = + typeof buildSecrets[key] === 'function' + ? buildSecrets[key]() + : buildSecrets[key]; + + if (secretValue) { + // Trim any whitespace/newlines from the secret value + secretEnvVars[key] = String(secretValue).trim(); + } + }); + } + + // Set environment variables in process.env for the docker build + Object.keys(secretEnvVars).forEach((key) => { + process.env[key] = secretEnvVars[key]; + }); + + let cmd = `DOCKER_BUILDKIT=1 DOCKER_SCAN_SUGGEST=false docker build -t ${name}:${tag}${formatBuildArgs( dockerLocation.buildArgs - )}${formatBuildArgs(buildArgs)} -f ${file}`; + )}${formatBuildSecrets(dockerLocation.buildSecrets)}${formatBuildArgs( + buildArgs + )} -f ${file}`; if (useTar) { cmd = `tar -chz -C ${locationPath} . | ${cmd} -`; @@ -84,13 +110,17 @@ return loadConfig('docker.locations').then((locations) => { cmd = `${cmd} ${locationPath}`; } - exec(cmd, { silent: program.R }, (err, stdout, stderr) => { - if (err !== 0) { - return reportError(stderr, false, true); - } + exec( + cmd, + { silent: program.R, env: { ...process.env } }, + (err, stdout, stderr) => { + if (err !== 0) { + return reportError(stderr, false, true); + } - if (program.R) { - process.stdout.write(`${tag}${newline(opts.name)}`); + if (program.R) { + process.stdout.write(`${tag}${newline(opts.name)}`); + } } - }); + ); }); diff --git a/bin/lib/c-kc.js b/bin/lib/c-kc.js index 8190294..55081f4 100644 --- a/bin/lib/c-kc.js +++ b/bin/lib/c-kc.js @@ -85,6 +85,41 @@ const formatBuildArgs = (args) => { return ''; }; +const formatBuildSecrets = (secrets) => { + if (Array.isArray(secrets)) { + return secrets.length > 0 ? `${leftSpace(secrets.join(' '))}` : ''; + } + + if (typeof secrets === 'object' && secrets !== null) { + const keys = Object.keys(secrets); + + if (keys.length) { + return `${leftSpace( + keys + .map((key) => { + const secretId = key.toLowerCase().replace(/-/g, '_'); + const secretValue = + typeof secrets[key] === 'function' + ? secrets[key]() + : secrets[key]; + + // If secretValue is provided, use it as env var name, otherwise use the key + const envVarName = + typeof secretValue === 'string' && + secretValue.startsWith('$') + ? secretValue.slice(1) + : key; + + return `--secret id=${secretId},env=${envVarName}`; + }) + .join(' ') + )}`; + } + } + + return ''; +}; + /** * Pad a string with a left space, if the string has a length. * @param {String} str A string to pad with a left space. @@ -180,6 +215,7 @@ module.exports = { ensureServiceFilesExist, flagBuildArgs, formatBuildArgs, + formatBuildSecrets, renderServicesTemplates, setLocalsForServices, validateBuildArgs,