@promigence/sdk 0.1.0-beta.4 → 0.1.0-beta.6
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/dist/cjs/client.d.ts +40 -47
- package/dist/cjs/client.js +19 -187
- package/dist/cjs/context.d.ts +119 -0
- package/dist/cjs/context.js +598 -0
- package/dist/cjs/core.d.ts +1 -1
- package/dist/cjs/core.js +2 -1
- package/dist/cjs/github.d.ts +27 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/models.gen.d.ts +118 -31
- package/dist/cjs/proxy.d.ts +20 -0
- package/dist/cjs/proxy.js +36 -0
- package/dist/cjs/pty.js +2 -3
- package/dist/cjs/sandbox.d.ts +12 -5
- package/dist/cjs/sandbox.js +3 -3
- package/dist/cjs/ssh.js +2 -3
- package/dist/client.d.ts +40 -47
- package/dist/client.js +18 -183
- package/dist/context.d.ts +119 -0
- package/dist/context.js +588 -0
- package/dist/core.d.ts +1 -1
- package/dist/core.js +2 -1
- package/dist/github.d.ts +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models.gen.d.ts +118 -31
- package/dist/proxy.d.ts +20 -0
- package/dist/proxy.js +35 -0
- package/dist/pty.js +2 -3
- package/dist/sandbox.d.ts +12 -5
- package/dist/sandbox.js +3 -3
- package/dist/ssh.js +2 -3
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { inspect } from "node:util";
|
|
4
|
-
import { dirname, join
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
5
|
import { ApiError, AuthError, EnvFailedError, PromigenceError, InvalidArgumentError, NotFoundError, NotReleasedError, NotVerifiedError, RateLimitError, SpendCapError, TimeoutError, UnreachableError, DEFAULT_API_URL, ERRORS_DOCS_URL, FILE_PUT_CHUNK_BYTES, MAX_OUTPUT_BYTES_DEFAULT, VERSION, WAIT_TIMEOUT_MS, PreviewsUnavailableError, exitForCode, previewsOff, withPreviewsFix, } from "./core.js";
|
|
6
6
|
import { BUNDLE_SCHEMA, buildBundle } from "./bundle.js";
|
|
7
7
|
import { keychainReadCached, keychainStore, storeLabel } from "./credstore.js";
|
|
@@ -9,6 +9,7 @@ import { CALLER_HEADER, resolveCaller, userAgentWithCaller } from "./caller.js";
|
|
|
9
9
|
import { connectPty } from "./pty.js";
|
|
10
10
|
import { connectSshTunnel } from "./ssh.js";
|
|
11
11
|
import { H2Response, Http2Transport, http2Allowed } from "./http2.js";
|
|
12
|
+
import { CONTEXT_TAR_PREFIX } from "./context.js";
|
|
12
13
|
import { proxyFetch, proxyFor } from "./proxy.js";
|
|
13
14
|
import { mark, traceBegin, traceEvent } from "./trace.js";
|
|
14
15
|
import { KEYED_CREATES } from "./keyed.gen.js";
|
|
@@ -407,81 +408,6 @@ export function checkImageVersioned(image) {
|
|
|
407
408
|
throw new InvalidArgumentError(`image ${JSON.stringify(ref)} names no tag or digest, so it would be pinned to whatever ${ref}:latest is today`, `Name the version: a tag (${ref}:<version>), ${ref}:latest if you mean the moving tag, or a digest (${ref}@sha256:<64 hex>).`);
|
|
408
409
|
}
|
|
409
410
|
export const CONTEXT_GIT_RE = /^(?:https?:\/\/|ssh:\/\/|git:\/\/|git@)\S+@[0-9a-f]{40}$/i;
|
|
410
|
-
export const CONTEXT_TAR_PREFIX = "tar;base64,";
|
|
411
|
-
export const CONTEXT_SKIP = new Set([".git", "node_modules", "__pycache__", ".venv", ".DS_Store"]);
|
|
412
|
-
export function dockerignoreMatcher(text) {
|
|
413
|
-
const rules = [];
|
|
414
|
-
for (const raw of text.split(/\r?\n/)) {
|
|
415
|
-
let line = raw.trim();
|
|
416
|
-
if (!line || line.startsWith("#"))
|
|
417
|
-
continue;
|
|
418
|
-
const exclusion = line.startsWith("!");
|
|
419
|
-
if (exclusion)
|
|
420
|
-
line = line.slice(1).trim();
|
|
421
|
-
const parts = [];
|
|
422
|
-
for (const seg of line.split("/")) {
|
|
423
|
-
if (seg === "" || seg === ".")
|
|
424
|
-
continue;
|
|
425
|
-
if (seg === "..")
|
|
426
|
-
parts.pop();
|
|
427
|
-
else
|
|
428
|
-
parts.push(seg);
|
|
429
|
-
}
|
|
430
|
-
const pattern = parts.join("/");
|
|
431
|
-
if (!pattern)
|
|
432
|
-
continue;
|
|
433
|
-
let re = "^";
|
|
434
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
435
|
-
const ch = pattern[i];
|
|
436
|
-
if (ch === "*") {
|
|
437
|
-
if (pattern[i + 1] === "*") {
|
|
438
|
-
i++;
|
|
439
|
-
if (pattern[i + 1] === "/")
|
|
440
|
-
i++;
|
|
441
|
-
re += i + 1 >= pattern.length ? ".*" : "(.*/)?";
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
re += "[^/]*";
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
else if (ch === "?") {
|
|
448
|
-
re += "[^/]";
|
|
449
|
-
}
|
|
450
|
-
else if (ch === "\\") {
|
|
451
|
-
re += i + 1 < pattern.length ? `\\${pattern[++i]}` : "\\\\";
|
|
452
|
-
}
|
|
453
|
-
else if (ch === "[" || ch === "]") {
|
|
454
|
-
re += ch;
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
re += /[.+()|{}$]/.test(ch) ? `\\${ch}` : ch;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
try {
|
|
461
|
-
rules.push({ re: new RegExp(`${re}$`), exclusion });
|
|
462
|
-
}
|
|
463
|
-
catch {
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
if (rules.length === 0)
|
|
467
|
-
return undefined;
|
|
468
|
-
const ignored = (rel) => {
|
|
469
|
-
const dirs = rel.split("/");
|
|
470
|
-
let matched = false;
|
|
471
|
-
for (const r of rules) {
|
|
472
|
-
if (r.exclusion !== matched)
|
|
473
|
-
continue;
|
|
474
|
-
let hit = r.re.test(rel);
|
|
475
|
-
for (let i = 1; !hit && i < dirs.length; i++)
|
|
476
|
-
hit = r.re.test(dirs.slice(0, i).join("/"));
|
|
477
|
-
if (hit)
|
|
478
|
-
matched = !r.exclusion;
|
|
479
|
-
}
|
|
480
|
-
return matched;
|
|
481
|
-
};
|
|
482
|
-
return { ignored, exceptions: rules.some((r) => r.exclusion) };
|
|
483
|
-
}
|
|
484
|
-
export const CONTEXT_MAX_BYTES = 8 * 1024 * 1024;
|
|
485
411
|
export function repoUrlCredential(url) {
|
|
486
412
|
const u = url.trim();
|
|
487
413
|
const sep = u.indexOf("://");
|
|
@@ -531,112 +457,6 @@ export function checkDockerfileContext(context) {
|
|
|
531
457
|
throw new InvalidArgumentError(`dockerfile.context must be a git URL pinned to a full 40-character sha, got ${JSON.stringify(context)}`, "A branch or a tag is not a pin: pass URL@<40-char sha> (git rev-parse HEAD), or pack a local " +
|
|
532
458
|
"directory with packContext('./app').");
|
|
533
459
|
}
|
|
534
|
-
export function packContext(dir, opts = {}) {
|
|
535
|
-
const max = opts.maxBytes ?? CONTEXT_MAX_BYTES;
|
|
536
|
-
const keep = new Set([".dockerignore", ...(opts.keep ?? [])]);
|
|
537
|
-
const collect = (ignore) => {
|
|
538
|
-
const entries = [];
|
|
539
|
-
let total = 0;
|
|
540
|
-
const walk = (abs, rel) => {
|
|
541
|
-
for (const name of readdirSync(abs).sort()) {
|
|
542
|
-
if (CONTEXT_SKIP.has(name))
|
|
543
|
-
continue;
|
|
544
|
-
const childAbs = join(abs, name);
|
|
545
|
-
const childRel = rel ? `${rel}/${name}` : name;
|
|
546
|
-
const st = lstatSync(childAbs);
|
|
547
|
-
const dropped = ignore !== undefined && !keep.has(childRel) && ignore.ignored(childRel);
|
|
548
|
-
if (st.isDirectory()) {
|
|
549
|
-
if (dropped && !ignore.exceptions)
|
|
550
|
-
continue;
|
|
551
|
-
if (!walk(childAbs, childRel))
|
|
552
|
-
return false;
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (dropped)
|
|
556
|
-
continue;
|
|
557
|
-
if (st.isSymbolicLink()) {
|
|
558
|
-
entries.push({ path: childRel, mode: 0o777, body: Buffer.alloc(0), link: readlinkSync(childAbs) });
|
|
559
|
-
continue;
|
|
560
|
-
}
|
|
561
|
-
if (!st.isFile())
|
|
562
|
-
continue;
|
|
563
|
-
total += st.size;
|
|
564
|
-
if (total > max)
|
|
565
|
-
return false;
|
|
566
|
-
entries.push({ path: childRel, mode: st.mode & 0o111 ? 0o755 : 0o644, body: readFileSync(childAbs) });
|
|
567
|
-
}
|
|
568
|
-
return true;
|
|
569
|
-
};
|
|
570
|
-
return walk(dir, "") ? entries : undefined;
|
|
571
|
-
};
|
|
572
|
-
let entries = collect();
|
|
573
|
-
if (entries === undefined) {
|
|
574
|
-
let ignore;
|
|
575
|
-
try {
|
|
576
|
-
ignore = dockerignoreMatcher(readFileSync(join(dir, ".dockerignore"), "utf8"));
|
|
577
|
-
}
|
|
578
|
-
catch {
|
|
579
|
-
ignore = undefined;
|
|
580
|
-
}
|
|
581
|
-
if (ignore !== undefined)
|
|
582
|
-
entries = collect(ignore);
|
|
583
|
-
if (entries === undefined) {
|
|
584
|
-
throw new InvalidArgumentError(`the build context is over ${max} bytes${ignore ? " even without what its .dockerignore excludes" : ""}`, `${ignore ? "Exclude more in .dockerignore" : "Add a .dockerignore"}, point --context at a smaller directory, or pass a git URL pinned to a full 40-character sha.`);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
if (entries.length === 0) {
|
|
588
|
-
throw new InvalidArgumentError(`the build context ${JSON.stringify(dir)} is empty`, "Point --context at the directory holding your Dockerfile.");
|
|
589
|
-
}
|
|
590
|
-
return CONTEXT_TAR_PREFIX + tarOf(entries).toString("base64");
|
|
591
|
-
}
|
|
592
|
-
export function contextRelative(contextDir, dockerfilePath) {
|
|
593
|
-
const rel = relative(contextDir, dockerfilePath).split(sep).join("/");
|
|
594
|
-
if (!rel || rel.startsWith("..")) {
|
|
595
|
-
throw new InvalidArgumentError(`${JSON.stringify(dockerfilePath)} is not inside the context ${JSON.stringify(contextDir)}`, "Pass --context DIR with the Dockerfile underneath it.");
|
|
596
|
-
}
|
|
597
|
-
return rel;
|
|
598
|
-
}
|
|
599
|
-
function tarOf(entries) {
|
|
600
|
-
const out = [];
|
|
601
|
-
for (const e of [...entries].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))) {
|
|
602
|
-
const head = Buffer.alloc(512);
|
|
603
|
-
let name = e.path;
|
|
604
|
-
let prefix = "";
|
|
605
|
-
if (Buffer.byteLength(name) > 100) {
|
|
606
|
-
const cut = name.lastIndexOf("/", name.length - 100);
|
|
607
|
-
if (cut <= 0 || Buffer.byteLength(name.slice(cut + 1)) > 100 || Buffer.byteLength(name.slice(0, cut)) > 155) {
|
|
608
|
-
throw new InvalidArgumentError(`the path ${JSON.stringify(e.path)} is too long for a build context`, "Shorten the path or pass a git URL pinned to a full 40-character sha.");
|
|
609
|
-
}
|
|
610
|
-
prefix = name.slice(0, cut);
|
|
611
|
-
name = name.slice(cut + 1);
|
|
612
|
-
}
|
|
613
|
-
const put = (s, at, len) => { head.write(s.slice(0, len), at, len, "utf8"); };
|
|
614
|
-
const oct = (n, at, len) => { put(n.toString(8).padStart(len - 1, "0") + "\0", at, len); };
|
|
615
|
-
put(name, 0, 100);
|
|
616
|
-
oct(e.mode, 100, 8);
|
|
617
|
-
oct(0, 108, 8);
|
|
618
|
-
oct(0, 116, 8);
|
|
619
|
-
oct(e.link === undefined ? e.body.length : 0, 124, 12);
|
|
620
|
-
oct(0, 136, 12);
|
|
621
|
-
head.write(" ", 148, 8, "utf8");
|
|
622
|
-
head.write(e.link === undefined ? "0" : "2", 156, 1, "utf8");
|
|
623
|
-
if (e.link !== undefined)
|
|
624
|
-
put(e.link, 157, 100);
|
|
625
|
-
head.write("ustar\0", 257, 6, "binary");
|
|
626
|
-
head.write("00", 263, 2, "utf8");
|
|
627
|
-
put(prefix, 345, 155);
|
|
628
|
-
let sum = 0;
|
|
629
|
-
for (const b of head)
|
|
630
|
-
sum += b;
|
|
631
|
-
put(sum.toString(8).padStart(6, "0") + "\0 ", 148, 8);
|
|
632
|
-
out.push(head);
|
|
633
|
-
if (e.link === undefined && e.body.length > 0) {
|
|
634
|
-
out.push(e.body, Buffer.alloc((512 - (e.body.length % 512)) % 512));
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
out.push(Buffer.alloc(1024));
|
|
638
|
-
return Buffer.concat(out);
|
|
639
|
-
}
|
|
640
460
|
function sourcesBody(sources) {
|
|
641
461
|
if (sources.length > MAX_SOURCES) {
|
|
642
462
|
throw new InvalidArgumentError(`snapshots.create takes at most ${MAX_SOURCES} extra sources, got ${sources.length}`, "An environment assembled from more repositories than that is cheaper to build once as " +
|
|
@@ -684,6 +504,9 @@ export function snapshotCreateBody(opts) {
|
|
|
684
504
|
let body;
|
|
685
505
|
const github = typeof o.repo === "string"
|
|
686
506
|
&& (o.repo.trim().startsWith(GITHUB_REPO_PREFIX) || o.repo.trim().startsWith(GITLAB_REPO_PREFIX));
|
|
507
|
+
if (o.env !== undefined && Object.keys(o.env).length && forms[0] === "repo") {
|
|
508
|
+
throw new InvalidArgumentError("snapshots.create env is for an image or a Dockerfile", "A repository snapshot sets its environment in its setup steps, or pass env on each command.");
|
|
509
|
+
}
|
|
687
510
|
if (!github && (o.ref !== undefined || o.from !== undefined || o.track)) {
|
|
688
511
|
throw new InvalidArgumentError("snapshots.create ref, from and track are for a connected repository (repo: 'github:owner/name' or 'gitlab:group/project')", "Pass { repo: 'github:your-org/app', ref: 'main' }, or drop them for this form.");
|
|
689
512
|
}
|
|
@@ -739,6 +562,8 @@ export function snapshotCreateBody(opts) {
|
|
|
739
562
|
body["tier"] = o.tier;
|
|
740
563
|
if (o.registrySecret)
|
|
741
564
|
body["registry_secret"] = o.registrySecret;
|
|
565
|
+
if (o.env !== undefined && Object.keys(o.env).length)
|
|
566
|
+
body["env"] = { ...o.env };
|
|
742
567
|
}
|
|
743
568
|
if (o.alias)
|
|
744
569
|
body["alias"] = o.alias;
|
|
@@ -1485,6 +1310,11 @@ export class PromigenceClient {
|
|
|
1485
1310
|
github = {
|
|
1486
1311
|
status: () => this.request({ method: "GET", path: "/integrations/github" }),
|
|
1487
1312
|
connect: () => this.request({ method: "POST", path: "/integrations/github/connect", body: {} }),
|
|
1313
|
+
ticket: () => this.request({ method: "POST", path: "/integrations/github/requests", body: {} }),
|
|
1314
|
+
request: (requestId) => this.request({
|
|
1315
|
+
method: "GET",
|
|
1316
|
+
path: `/integrations/github/requests/${encodeURIComponent(requestId)}`,
|
|
1317
|
+
}),
|
|
1488
1318
|
disconnect: (installationId) => this.request({
|
|
1489
1319
|
method: "DELETE",
|
|
1490
1320
|
path: `/integrations/github/installations/${encodeURIComponent(String(installationId))}`,
|
|
@@ -1503,6 +1333,11 @@ export class PromigenceClient {
|
|
|
1503
1333
|
gitlab = {
|
|
1504
1334
|
status: () => this.request({ method: "GET", path: "/integrations/gitlab" }),
|
|
1505
1335
|
connect: () => this.request({ method: "POST", path: "/integrations/gitlab/connect", body: {} }),
|
|
1336
|
+
ticket: () => this.request({ method: "POST", path: "/integrations/gitlab/requests", body: {} }),
|
|
1337
|
+
request: (requestId) => this.request({
|
|
1338
|
+
method: "GET",
|
|
1339
|
+
path: `/integrations/gitlab/requests/${encodeURIComponent(requestId)}`,
|
|
1340
|
+
}),
|
|
1506
1341
|
disconnect: (connectionId) => this.request({
|
|
1507
1342
|
method: "DELETE",
|
|
1508
1343
|
path: `/integrations/gitlab/connections/${encodeURIComponent(connectionId)}`,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A local directory as a Dockerfile build context: what `packContext` sends, decided before
|
|
3
|
+
* anything leaves this machine.
|
|
4
|
+
*
|
|
5
|
+
* - **`.dockerignore` is applied here, always**, with the rules `docker build` uses: Go glob syntax
|
|
6
|
+
* plus `**`, `!` to bring a path back, the last matching line wins, a matched directory takes
|
|
7
|
+
* everything under it, and paths are read from the context root. A file the `.dockerignore`
|
|
8
|
+
* excludes is never uploaded. `<Dockerfile>.dockerignore` beside the Dockerfile is read instead
|
|
9
|
+
* of the root `.dockerignore` when it exists, as `docker build` does. The Dockerfile and the
|
|
10
|
+
* ignore files themselves are always sent, whatever a pattern says.
|
|
11
|
+
* - **`.git` is never sent** unless the `.dockerignore` has the line `!.git`: git history can hold
|
|
12
|
+
* credentials long deleted from the tree.
|
|
13
|
+
* - **Without a `.dockerignore`**, `node_modules`, `__pycache__`, `.venv` and `.DS_Store` are left
|
|
14
|
+
* out too, and a note says so; with one, only what it lists is left out.
|
|
15
|
+
* - Empty directories and permission bits travel as they are on disk; a set-user-ID or
|
|
16
|
+
* set-group-ID bit is cleared, with a note.
|
|
17
|
+
* - Files that look like credentials (`.env`, private keys, cloud credentials, ...) are refused,
|
|
18
|
+
* by name, unless `allowSecrets` says otherwise. The check goes by file name: it is
|
|
19
|
+
* best-effort and cannot see what a file holds, so look over the list (`listContext`) before
|
|
20
|
+
* you send a directory.
|
|
21
|
+
* - Symbolic links travel as links, never as the file they point at.
|
|
22
|
+
*/
|
|
23
|
+
/** The prefix a packed directory travels under in `dockerfile.context`. */
|
|
24
|
+
export declare const CONTEXT_TAR_PREFIX = "tar;base64,";
|
|
25
|
+
/** The largest context accepted, counted in file bytes after `.dockerignore`. */
|
|
26
|
+
export declare const CONTEXT_MAX_BYTES: number;
|
|
27
|
+
/**
|
|
28
|
+
* Names left out when the context has no `.dockerignore`. With one, the `.dockerignore` alone
|
|
29
|
+
* decides, except for `.git` (sent only when it says `!.git`).
|
|
30
|
+
*/
|
|
31
|
+
export declare const CONTEXT_SKIP: Set<string>;
|
|
32
|
+
/** The patterns of one ignore file, compiled. */
|
|
33
|
+
export interface DockerIgnore {
|
|
34
|
+
/** The ignore file these came from (`.dockerignore` or `<Dockerfile>.dockerignore`). */
|
|
35
|
+
readonly file: string;
|
|
36
|
+
/** The patterns as the build holds them, in file order: cleaned, an exception keeping its `!`. */
|
|
37
|
+
readonly patterns: readonly string[];
|
|
38
|
+
/** Whether any line is a `!` exception. */
|
|
39
|
+
readonly exceptions: boolean;
|
|
40
|
+
/** Whether a line says `!.git`, which is what sends `.git`. */
|
|
41
|
+
readonly sendsGit: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Is `path` (relative to the context root, `/`-separated) left out? The last pattern that
|
|
44
|
+
* matches it, or one of the directories above it, decides.
|
|
45
|
+
*/
|
|
46
|
+
ignored(path: string): boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read an ignore file the way `docker build` reads it: a UTF-8 BOM is dropped; a line starting
|
|
50
|
+
* with `#` is a comment; each line is trimmed; `!` starts an exception; each pattern is cleaned
|
|
51
|
+
* (`a//b/../c` is `a/c`) and a leading `/` is dropped. A line the build cannot read (a lone `!`,
|
|
52
|
+
* an unclosed `[`, a trailing `\`) makes the build refuse the whole file, so it is refused here,
|
|
53
|
+
* naming the line, before anything is sent.
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseDockerignore(text: string, file?: string): DockerIgnore;
|
|
56
|
+
/**
|
|
57
|
+
* A `.dockerignore`'s patterns as a predicate, or `undefined` for a file with no patterns. Refuses
|
|
58
|
+
* a file the build could not read. Kept for code written against 0.1; `parseDockerignore` is the
|
|
59
|
+
* full reader.
|
|
60
|
+
*/
|
|
61
|
+
export declare function dockerignoreMatcher(text: string): {
|
|
62
|
+
ignored: (rel: string) => boolean;
|
|
63
|
+
exceptions: boolean;
|
|
64
|
+
} | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Does this path look like a credential (`.env`, a private key, cloud or registry credentials, a
|
|
67
|
+
* token file, ...)? By name only: best-effort, it cannot see what a file holds. Templates such as
|
|
68
|
+
* `.env.example` are not.
|
|
69
|
+
*/
|
|
70
|
+
export declare function secretLike(path: string): boolean;
|
|
71
|
+
/** What a build context is packed from and sent with. */
|
|
72
|
+
export interface ContextOptions {
|
|
73
|
+
/**
|
|
74
|
+
* The Dockerfile's path inside the context, `/`-separated (default `Dockerfile`). It is always
|
|
75
|
+
* sent, and `<it>.dockerignore`, when present, is read instead of the root `.dockerignore`.
|
|
76
|
+
*/
|
|
77
|
+
dockerfile?: string;
|
|
78
|
+
/** More paths inside the context to send whatever `.dockerignore` says. */
|
|
79
|
+
keep?: readonly string[];
|
|
80
|
+
/** Refuse a context whose files add up to more than this many bytes (default `CONTEXT_MAX_BYTES`). */
|
|
81
|
+
maxBytes?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Send files that look like credentials. Default `false`: they are refused, by name, and
|
|
84
|
+
* nothing is sent.
|
|
85
|
+
*/
|
|
86
|
+
allowSecrets?: boolean;
|
|
87
|
+
/** Called with each note: what was left out by default, or changed on the way. */
|
|
88
|
+
onNote?: (note: string) => void;
|
|
89
|
+
}
|
|
90
|
+
/** What a build context would hold, before anything is sent. */
|
|
91
|
+
export interface ContextListing {
|
|
92
|
+
/** Every path that would be sent, sorted; a directory's ends in `/`. */
|
|
93
|
+
paths: string[];
|
|
94
|
+
/** How many of them are files or links. */
|
|
95
|
+
files: number;
|
|
96
|
+
/** The files' bytes. */
|
|
97
|
+
bytes: number;
|
|
98
|
+
/** What was left out by default or changed on the way, one sentence each. */
|
|
99
|
+
notes: string[];
|
|
100
|
+
/** The paths that would be sent and look like credentials. */
|
|
101
|
+
secrets: string[];
|
|
102
|
+
/** The ignore file applied, or `null` when there is none. */
|
|
103
|
+
ignoreFile: string | null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* What `packContext(dir, opts)` would send, without sending or packing anything: every path, the
|
|
107
|
+
* notes, and the files that look like credentials. Refuses only what `packContext` cannot read
|
|
108
|
+
* (an ignore file the build would refuse).
|
|
109
|
+
*/
|
|
110
|
+
export declare function listContext(dir: string, opts?: ContextOptions): ContextListing;
|
|
111
|
+
/**
|
|
112
|
+
* Pack a directory into the string `dockerfile.context` takes. What is sent is decided here (see
|
|
113
|
+
* the module notes): files the `.dockerignore` excludes, and `.git`, are never uploaded; files
|
|
114
|
+
* that look like credentials are refused unless `allowSecrets`; a context over `maxBytes` after
|
|
115
|
+
* `.dockerignore` is refused. The same tree packs to the same snapshot whichever SDK packs it.
|
|
116
|
+
*/
|
|
117
|
+
export declare function packContext(dir: string, opts?: ContextOptions): string;
|
|
118
|
+
/** The Dockerfile's path as the context sees it, for `dockerfile.path`. */
|
|
119
|
+
export declare function contextRelative(contextDir: string, dockerfilePath: string): string;
|