@brutalsystems/dray 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/core/buildArgs.js +25 -13
- package/src/core/engine.js +1 -1
package/README.md
CHANGED
|
@@ -57,7 +57,9 @@ Global flags: `--dry-run` (print the plan, run nothing), `--allow-dirty`
|
|
|
57
57
|
"dockerfile": "Dockerfile", "context": ".",
|
|
58
58
|
// optional: rebuild a cached deps layer when lockfiles change
|
|
59
59
|
"depsImage": { "dockerfile": "Dockerfile.deps", "tag": "app:deps", "rebuildOn": ["uv.lock"] },
|
|
60
|
-
// optional: inject --build-arg from an env file (e.g. VITE_* from .env.production)
|
|
60
|
+
// optional: inject --build-arg from an env file (e.g. VITE_* from .env.production),
|
|
61
|
+
// or from a sops-encrypted file decrypted in memory at build time (no plaintext on disk):
|
|
62
|
+
// "buildArgs": { "sopsEnvFile": "secrets.env", "prefix": "VITE_" }
|
|
61
63
|
"buildArgs": { "envFile": ".env.production", "prefix": "VITE_" } },
|
|
62
64
|
// image from another repo (cloned to a tmp dir, built, pushed):
|
|
63
65
|
{ "name": "svc", "ecr": "svc", "source": { "git": "https://github.com/org/svc", "ref": "main" } }
|
package/package.json
CHANGED
package/src/core/buildArgs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fs = require('node:fs'); const path = require('node:path');
|
|
2
|
+
let _run = require('../primitives/exec').run; function _withRun(fn) { _run = fn; }
|
|
2
3
|
|
|
3
4
|
function stripQuotes(v) {
|
|
4
5
|
const t = v.trim();
|
|
@@ -8,27 +9,38 @@ function stripQuotes(v) {
|
|
|
8
9
|
return t;
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
// Parse dotenv-style text into ["KEY=VALUE", ...], filtered by `prefix`.
|
|
13
|
+
function parseEnvLines(text, prefix) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const line of text.split('\n')) {
|
|
16
|
+
const m = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
17
|
+
if (!m) continue;
|
|
18
|
+
const [, k, v] = m;
|
|
19
|
+
if (prefix && !k.startsWith(prefix)) continue;
|
|
20
|
+
out.push(`${k}=${stripQuotes(v)}`);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
// Returns ["KEY=VALUE", ...] for `docker build --build-arg`. An image may set
|
|
12
|
-
// `buildArgs: { envFile, prefix }` to inject vars from
|
|
13
|
-
// from .env.production),
|
|
14
|
-
|
|
26
|
+
// `buildArgs: { envFile, prefix }` to inject vars from a plaintext env file
|
|
27
|
+
// (e.g. VITE_* from .env.production), `buildArgs: { sopsEnvFile, prefix }` to
|
|
28
|
+
// inject them from a sops-encrypted file decrypted in memory at build time (no
|
|
29
|
+
// plaintext on disk), and/or `buildArgs.values: { K: V }` for explicit pairs.
|
|
30
|
+
async function resolveBuildArgs(image, cwd, { dryRun = false } = {}) {
|
|
15
31
|
const cfg = image && image.buildArgs;
|
|
16
32
|
if (!cfg) return [];
|
|
17
33
|
const out = [];
|
|
18
34
|
if (cfg.envFile) {
|
|
19
35
|
const p = path.join(cwd, cfg.envFile);
|
|
20
|
-
if (fs.existsSync(p))
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (cfg.prefix && !k.startsWith(cfg.prefix)) continue;
|
|
26
|
-
out.push(`${k}=${stripQuotes(v)}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
36
|
+
if (fs.existsSync(p)) out.push(...parseEnvLines(fs.readFileSync(p, 'utf8'), cfg.prefix));
|
|
37
|
+
}
|
|
38
|
+
if (cfg.sopsEnvFile) {
|
|
39
|
+
const { stdout } = await _run('sops', ['-d', '--output-type', 'dotenv', cfg.sopsEnvFile], { cwd, capture: true, dryRun });
|
|
40
|
+
out.push(...parseEnvLines(stdout || '', cfg.prefix));
|
|
29
41
|
}
|
|
30
42
|
for (const [k, v] of Object.entries(cfg.values || {})) out.push(`${k}=${v}`);
|
|
31
43
|
return out;
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
module.exports = { resolveBuildArgs };
|
|
46
|
+
module.exports = { resolveBuildArgs, _withRun };
|
package/src/core/engine.js
CHANGED
|
@@ -39,7 +39,7 @@ async function execute(steps, { dryRun = false, allowDirty = false, deps } = {})
|
|
|
39
39
|
if (u._clone && !clones.includes(u._clone)) clones.push(u._clone);
|
|
40
40
|
const cwd = u._clone ? u._clone.dir : u.repoPath;
|
|
41
41
|
if (step.kind === 'deps') { if (d.depsCache.needsDepsRebuild(u.image, cwd, u.repo)) await d.docker.buildDeps(u.image, cwd, dryRun); }
|
|
42
|
-
else if (step.kind === 'build') await d.docker.buildImage({ ecrUri: u.repoUri, sha, dockerfile: u.image.dockerfile, context: u.image.context || '.', platform: u.defaults.platform, cwd, dryRun, buildArgs: d.buildArgs.resolveBuildArgs(u.image, cwd) });
|
|
42
|
+
else if (step.kind === 'build') await d.docker.buildImage({ ecrUri: u.repoUri, sha, dockerfile: u.image.dockerfile, context: u.image.context || '.', platform: u.defaults.platform, cwd, dryRun, buildArgs: await d.buildArgs.resolveBuildArgs(u.image, cwd, { dryRun }) });
|
|
43
43
|
else if (step.kind === 'push') {
|
|
44
44
|
if (!loggedIn) { await d.docker.ecrLogin({ account: u.defaults.account, region: u.defaults.region, profile: u.defaults.profile, dryRun }); await d.docker.ensureRepo({ ecr: u.image.ecr, account: u.defaults.account, region: u.defaults.region, profile: u.defaults.profile, dryRun }); loggedIn = true; }
|
|
45
45
|
await d.docker.pushImage({ ecrUri: u.repoUri, sha, dryRun });
|