@alchemy.run/archil 0.0.0 → 2.0.0-beta.86
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/LICENSE +201 -0
- package/README.md +57 -4
- package/lib/AWS/S3Disk.d.ts +68 -0
- package/lib/AWS/S3Disk.d.ts.map +1 -0
- package/lib/AWS/S3Disk.js +100 -0
- package/lib/AWS/S3Disk.js.map +1 -0
- package/lib/AWS/index.d.ts +2 -0
- package/lib/AWS/index.d.ts.map +1 -0
- package/lib/AWS/index.js +2 -0
- package/lib/AWS/index.js.map +1 -0
- package/lib/ApiToken.d.ts +63 -0
- package/lib/ApiToken.d.ts.map +1 -0
- package/lib/ApiToken.js +121 -0
- package/lib/ApiToken.js.map +1 -0
- package/lib/ArchilBindings.d.ts +65 -0
- package/lib/ArchilBindings.d.ts.map +1 -0
- package/lib/ArchilBindings.js +128 -0
- package/lib/ArchilBindings.js.map +1 -0
- package/lib/AuthProvider.d.ts +40 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +87 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/Bootstrap.d.ts +8 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +27 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/Branch.d.ts +101 -0
- package/lib/Branch.d.ts.map +1 -0
- package/lib/Branch.js +117 -0
- package/lib/Branch.js.map +1 -0
- package/lib/BranchDisk.d.ts +42 -0
- package/lib/BranchDisk.d.ts.map +1 -0
- package/lib/BranchDisk.js +14 -0
- package/lib/BranchDisk.js.map +1 -0
- package/lib/Checkpoint.d.ts +78 -0
- package/lib/Checkpoint.d.ts.map +1 -0
- package/lib/Checkpoint.js +95 -0
- package/lib/Checkpoint.js.map +1 -0
- package/lib/Clients.d.ts +369 -0
- package/lib/Clients.d.ts.map +1 -0
- package/lib/Clients.js +334 -0
- package/lib/Clients.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +69 -0
- package/lib/ConnectSandbox.d.ts.map +1 -0
- package/lib/ConnectSandbox.js +21 -0
- package/lib/ConnectSandbox.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/CreateDisk.d.ts +90 -0
- package/lib/CreateDisk.d.ts.map +1 -0
- package/lib/CreateDisk.js +47 -0
- package/lib/CreateDisk.js.map +1 -0
- package/lib/CreateImage.d.ts +42 -0
- package/lib/CreateImage.d.ts.map +1 -0
- package/lib/CreateImage.js +19 -0
- package/lib/CreateImage.js.map +1 -0
- package/lib/CreateSandbox.d.ts +104 -0
- package/lib/CreateSandbox.d.ts.map +1 -0
- package/lib/CreateSandbox.js +98 -0
- package/lib/CreateSandbox.js.map +1 -0
- package/lib/Credentials.d.ts +44 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +57 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Disk.d.ts +283 -0
- package/lib/Disk.d.ts.map +1 -0
- package/lib/Disk.js +294 -0
- package/lib/Disk.js.map +1 -0
- package/lib/DiskObjectsHttp.d.ts +20 -0
- package/lib/DiskObjectsHttp.d.ts.map +1 -0
- package/lib/DiskObjectsHttp.js +51 -0
- package/lib/DiskObjectsHttp.js.map +1 -0
- package/lib/DiskUser.d.ts +189 -0
- package/lib/DiskUser.d.ts.map +1 -0
- package/lib/DiskUser.js +243 -0
- package/lib/DiskUser.js.map +1 -0
- package/lib/ExecDisk.d.ts +57 -0
- package/lib/ExecDisk.d.ts.map +1 -0
- package/lib/ExecDisk.js +3 -0
- package/lib/ExecDisk.js.map +1 -0
- package/lib/ExecDiskHttp.d.ts +5 -0
- package/lib/ExecDiskHttp.d.ts.map +1 -0
- package/lib/ExecDiskHttp.js +18 -0
- package/lib/ExecDiskHttp.js.map +1 -0
- package/lib/ExecDisks.d.ts +54 -0
- package/lib/ExecDisks.d.ts.map +1 -0
- package/lib/ExecDisks.js +37 -0
- package/lib/ExecDisks.js.map +1 -0
- package/lib/Image.d.ts +188 -0
- package/lib/Image.d.ts.map +1 -0
- package/lib/Image.js +191 -0
- package/lib/Image.js.map +1 -0
- package/lib/InferEnv.d.ts +26 -0
- package/lib/InferEnv.d.ts.map +1 -0
- package/lib/InferEnv.js +1 -0
- package/lib/InferEnv.js.map +1 -0
- package/lib/MountDisk.d.ts +190 -0
- package/lib/MountDisk.d.ts.map +1 -0
- package/lib/MountDisk.js +227 -0
- package/lib/MountDisk.js.map +1 -0
- package/lib/Providers.d.ts +25 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +48 -0
- package/lib/Providers.js.map +1 -0
- package/lib/ReadDisk.d.ts +55 -0
- package/lib/ReadDisk.d.ts.map +1 -0
- package/lib/ReadDisk.js +3 -0
- package/lib/ReadDisk.js.map +1 -0
- package/lib/ReadWriteDisk.d.ts +26 -0
- package/lib/ReadWriteDisk.d.ts.map +1 -0
- package/lib/ReadWriteDisk.js +3 -0
- package/lib/ReadWriteDisk.js.map +1 -0
- package/lib/Sandbox.d.ts +507 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +729 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxOptions.d.ts +185 -0
- package/lib/SandboxOptions.d.ts.map +1 -0
- package/lib/SandboxOptions.js +102 -0
- package/lib/SandboxOptions.js.map +1 -0
- package/lib/SandboxPortToken.d.ts +64 -0
- package/lib/SandboxPortToken.d.ts.map +1 -0
- package/lib/SandboxPortToken.js +77 -0
- package/lib/SandboxPortToken.js.map +1 -0
- package/lib/WriteDisk.d.ts +37 -0
- package/lib/WriteDisk.d.ts.map +1 -0
- package/lib/WriteDisk.js +3 -0
- package/lib/WriteDisk.js.map +1 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +28 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/DeployerKey.d.ts +21 -0
- package/lib/internal/DeployerKey.d.ts.map +1 -0
- package/lib/internal/DeployerKey.js +34 -0
- package/lib/internal/DeployerKey.js.map +1 -0
- package/lib/internal/archil.d.ts +87 -0
- package/lib/internal/archil.d.ts.map +1 -0
- package/lib/internal/archil.js +154 -0
- package/lib/internal/archil.js.map +1 -0
- package/lib/internal/hosted.d.ts +90 -0
- package/lib/internal/hosted.d.ts.map +1 -0
- package/lib/internal/hosted.js +291 -0
- package/lib/internal/hosted.js.map +1 -0
- package/package.json +79 -3
- package/src/AWS/S3Disk.ts +125 -0
- package/src/AWS/index.ts +1 -0
- package/src/ApiToken.ts +168 -0
- package/src/ArchilBindings.ts +179 -0
- package/src/AuthProvider.ts +122 -0
- package/src/Bootstrap.ts +54 -0
- package/src/Branch.ts +199 -0
- package/src/BranchDisk.ts +57 -0
- package/src/Checkpoint.ts +145 -0
- package/src/Clients.ts +954 -0
- package/src/ConnectSandbox.ts +91 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateDisk.ts +165 -0
- package/src/CreateImage.ts +73 -0
- package/src/CreateSandbox.ts +258 -0
- package/src/Credentials.ts +101 -0
- package/src/Disk.ts +468 -0
- package/src/DiskObjectsHttp.ts +64 -0
- package/src/DiskUser.ts +369 -0
- package/src/ExecDisk.ts +62 -0
- package/src/ExecDiskHttp.ts +25 -0
- package/src/ExecDisks.ts +100 -0
- package/src/Image.ts +316 -0
- package/src/InferEnv.ts +27 -0
- package/src/MountDisk.ts +466 -0
- package/src/Providers.ts +75 -0
- package/src/ReadDisk.ts +61 -0
- package/src/ReadWriteDisk.ts +31 -0
- package/src/Sandbox.ts +1064 -0
- package/src/SandboxOptions.ts +230 -0
- package/src/SandboxPortToken.ts +125 -0
- package/src/WriteDisk.ts +42 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +59 -0
- package/src/internal/DeployerKey.ts +63 -0
- package/src/internal/archil.ts +273 -0
- package/src/internal/hosted.ts +402 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import type { ExecResult } from "./Clients.ts";
|
|
7
|
+
/** One disk in a multi-disk exec. */
|
|
8
|
+
export interface ExecDisksMount {
|
|
9
|
+
/** Disk id (`dsk-…`). */
|
|
10
|
+
disk: string;
|
|
11
|
+
/** Mount this subdirectory of the disk instead of its root. */
|
|
12
|
+
subdirectory?: string;
|
|
13
|
+
/** Mount without write access. */
|
|
14
|
+
readOnly?: boolean;
|
|
15
|
+
/** Write without the disk's root delegation, so other writers can mount it too. */
|
|
16
|
+
conditional?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ExecDisksClient {
|
|
19
|
+
/**
|
|
20
|
+
* Run a shell command in a fresh microVM with several disks mounted.
|
|
21
|
+
* Keys are paths under `/mnt/archil`; values are disk ids or mounts.
|
|
22
|
+
*/
|
|
23
|
+
exec(request: {
|
|
24
|
+
readonly disks: Record<string, string | ExecDisksMount>;
|
|
25
|
+
readonly command: string;
|
|
26
|
+
}): Effect.Effect<ExecResult, archil.ExecError, RuntimeContext>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Run one serverless command against several disks at once, e.g. read a
|
|
30
|
+
* shared dataset and write into a user's own disk in the same call. Disks
|
|
31
|
+
* are named at run time, so it works with disks created per user.
|
|
32
|
+
*
|
|
33
|
+
* ### Running Across Disks
|
|
34
|
+
* **Example:** Copy a dataset into a user's disk
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const exec = yield* Archil.ExecDisks();
|
|
37
|
+
* const result = yield* exec.exec({
|
|
38
|
+
* disks: {
|
|
39
|
+
* data: { disk: datasetId, readOnly: true },
|
|
40
|
+
* home: userDisk.diskId,
|
|
41
|
+
* },
|
|
42
|
+
* command: "cp -r /mnt/archil/data/samples /mnt/archil/home/",
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @binding
|
|
47
|
+
* @product Disk
|
|
48
|
+
*/
|
|
49
|
+
export interface ExecDisks extends Binding.Service<ExecDisks, "Archil.ExecDisks", () => Effect.Effect<ExecDisksClient>> {
|
|
50
|
+
}
|
|
51
|
+
export declare const ExecDisks: ExecDisks;
|
|
52
|
+
/** {@link ExecDisks} over Archil's HTTP API, usable from any host. */
|
|
53
|
+
export declare const ExecDisksHttp: Layer.Layer<ExecDisks, never, never>;
|
|
54
|
+
//# sourceMappingURL=ExecDisks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecDisks.d.ts","sources":["../src/ExecDisks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,IAAI,CAAC,OAAO,EAAE;QACZ,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC;QACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,SAAU,SAAQ,OAAO,CAAC,OAAO,CAChD,SAAS,EACT,kBAAkB,EAClB,MAAM,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CACrC;CAAG;AAEJ,eAAO,MAAM,SAAS,WAAiD,CAAC;AAExE,sEAAsE;AACtE,eAAO,MAAM,aAAa,sCAsCzB,CAAC"}
|
package/lib/ExecDisks.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { ApiAccess } from "./ArchilBindings.js";
|
|
6
|
+
export const ExecDisks = Binding.Service("Archil.ExecDisks");
|
|
7
|
+
/** {@link ExecDisks} over Archil's HTTP API, usable from any host. */
|
|
8
|
+
export const ExecDisksHttp = Layer.effect(ExecDisks, Effect.gen(function* () {
|
|
9
|
+
const access = yield* ApiAccess;
|
|
10
|
+
return Effect.fn(function* () {
|
|
11
|
+
const authorize = yield* access();
|
|
12
|
+
return {
|
|
13
|
+
exec: (request) => authorize(archil
|
|
14
|
+
.exec({
|
|
15
|
+
command: request.command,
|
|
16
|
+
disks: Object.fromEntries(Object.entries(request.disks).map(([path, mount]) => [
|
|
17
|
+
path,
|
|
18
|
+
typeof mount === "string"
|
|
19
|
+
? mount
|
|
20
|
+
: {
|
|
21
|
+
disk: mount.disk,
|
|
22
|
+
subdirectory: mount.subdirectory,
|
|
23
|
+
readOnly: mount.readOnly,
|
|
24
|
+
conditional: mount.conditional,
|
|
25
|
+
},
|
|
26
|
+
])),
|
|
27
|
+
})
|
|
28
|
+
.pipe(Effect.map(({ data }) => ({
|
|
29
|
+
exitCode: data.exitCode,
|
|
30
|
+
stdout: data.stdout,
|
|
31
|
+
stderr: data.stderr,
|
|
32
|
+
timing: data.timing,
|
|
33
|
+
})))),
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}));
|
|
37
|
+
//# sourceMappingURL=ExecDisks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecDisks.js","sources":["../src/ExecDisks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAqDhD,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAY,kBAAkB,CAAC,CAAC;AAExE,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CACvC,SAAS,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC;QACxB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO;YACL,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAChB,SAAS,CACP,MAAM;iBACH,IAAI,CAAC;gBACJ,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,KAAK,EAAE,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;oBACnD,IAAI;oBACJ,OAAO,KAAK,KAAK,QAAQ;wBACvB,CAAC,CAAC,KAAK;wBACP,CAAC,CAAC;4BACE,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,YAAY,EAAE,KAAK,CAAC,YAAY;4BAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;4BACxB,WAAW,EAAE,KAAK,CAAC,WAAW;yBAC/B;iBACN,CAAC,CACH;aACF,CAAC;iBACD,IAAI,CACH,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBACxB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC,CACJ,CACJ;SACsB,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
package/lib/Image.d.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as BuildPlan from "@alchemy.run/docker/BuildPlan";
|
|
2
|
+
import type { InlineDockerfile } from "@alchemy.run/docker/Dockerfile";
|
|
3
|
+
import type { DockerfileBuild } from "@alchemy.run/docker/ImageSource";
|
|
4
|
+
import type { ImageRegistry } from "@alchemy.run/docker/Registry";
|
|
5
|
+
import * as archil from "@distilled.cloud/archil";
|
|
6
|
+
import * as Provider from "alchemy/Provider";
|
|
7
|
+
import { Resource } from "alchemy/Resource";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import type { Providers } from "./Providers.ts";
|
|
10
|
+
export interface ImageProps {
|
|
11
|
+
/**
|
|
12
|
+
* Linux OCI image reference with a `linux/amd64` manifest, e.g.
|
|
13
|
+
* `ghcr.io/acme/agent:1`. Docker shorthand and tags are accepted.
|
|
14
|
+
* Exclusive with `dockerfile` and `context`. Changing it builds a new
|
|
15
|
+
* image.
|
|
16
|
+
*/
|
|
17
|
+
image?: string;
|
|
18
|
+
/**
|
|
19
|
+
* A Dockerfile path (relative to the cwd) or `Dockerfile.inline` content.
|
|
20
|
+
* Archil has no builder of its own: Alchemy builds it with your local
|
|
21
|
+
* Docker and pushes it to `push.repository`, and Archil pulls it from
|
|
22
|
+
* there.
|
|
23
|
+
*/
|
|
24
|
+
dockerfile?: string | InlineDockerfile;
|
|
25
|
+
/** Build context for a `dockerfile` path. */
|
|
26
|
+
context?: string;
|
|
27
|
+
/** Docker build args and BuildKit secrets for a `dockerfile` image. */
|
|
28
|
+
build?: DockerfileBuild;
|
|
29
|
+
/**
|
|
30
|
+
* Credentials for a private registry. Archil uses them to pull this
|
|
31
|
+
* image only and doesn't store them.
|
|
32
|
+
*/
|
|
33
|
+
registry?: ImageRegistry;
|
|
34
|
+
/**
|
|
35
|
+
* Where a Dockerfile image is pushed for Archil to pull: a repository
|
|
36
|
+
* (no tag; the build's hash is the tag) and credentials that can push to
|
|
37
|
+
* it and pull from it. Required for `dockerfile` images.
|
|
38
|
+
*/
|
|
39
|
+
push?: ImagePush;
|
|
40
|
+
}
|
|
41
|
+
/** A registry repository Alchemy pushes built images to, for Archil to pull. */
|
|
42
|
+
export interface ImagePush {
|
|
43
|
+
/** Repository without a tag, e.g. `ghcr.io/acme/agent`. */
|
|
44
|
+
repository: string;
|
|
45
|
+
/** Credentials that can push to and pull from the repository. */
|
|
46
|
+
credentials: ImageRegistry;
|
|
47
|
+
}
|
|
48
|
+
export interface ImageAttributes {
|
|
49
|
+
/** Image id (64 hex characters); pass it as a sandbox's `image`. */
|
|
50
|
+
imageId: string;
|
|
51
|
+
/** The reference the image was built from. */
|
|
52
|
+
source: string;
|
|
53
|
+
/** The fully qualified reference Archil resolved, e.g. `docker.io/library/node:24`. */
|
|
54
|
+
canonicalSource: string | undefined;
|
|
55
|
+
/** Digest of the image sandboxes boot. */
|
|
56
|
+
digest: string | undefined;
|
|
57
|
+
/** Whether the image came from a private registry. */
|
|
58
|
+
private: boolean;
|
|
59
|
+
/** Hash of the build plan the image came from. */
|
|
60
|
+
hash: string;
|
|
61
|
+
}
|
|
62
|
+
export type Image = Resource<"Archil.Image", ImageProps, ImageAttributes, never, Providers, ImageLookup>;
|
|
63
|
+
/**
|
|
64
|
+
* Props for {@link Image.lookup}: find an image this stack
|
|
65
|
+
* doesn't manage by its id.
|
|
66
|
+
*/
|
|
67
|
+
export interface ImageLookup {
|
|
68
|
+
/** Archil image id. */
|
|
69
|
+
imageId: string;
|
|
70
|
+
}
|
|
71
|
+
declare const ImageRequiresBuild_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
72
|
+
readonly _tag: "Archil.ImageRequiresBuild";
|
|
73
|
+
} & Readonly<A>;
|
|
74
|
+
/**
|
|
75
|
+
* The image needs instructions run on top of its base, and Archil only
|
|
76
|
+
* pulls finished images.
|
|
77
|
+
*/
|
|
78
|
+
export declare class ImageRequiresBuild extends ImageRequiresBuild_base<{
|
|
79
|
+
readonly message: string;
|
|
80
|
+
}> {
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A sandbox image. Archil pulls it from a public or private registry and
|
|
84
|
+
* sandboxes boot its current digest. Public images can also be used
|
|
85
|
+
* directly as a sandbox's `baseImage`; build an `Image` for a private one,
|
|
86
|
+
* or to pin the digest every sandbox boots.
|
|
87
|
+
*
|
|
88
|
+
* Props follow `@alchemy.run/docker`'s image source, like every Alchemy
|
|
89
|
+
* image resource. Archil has no builder, so a Dockerfile is built with
|
|
90
|
+
* your local Docker and pushed to `push.repository`, and Archil pulls it
|
|
91
|
+
* from there.
|
|
92
|
+
*
|
|
93
|
+
* Archil has no API to delete an image, so destroying the resource only
|
|
94
|
+
* removes it from Alchemy's state.
|
|
95
|
+
* @see https://docs.archil.com/api-reference/images/build-image
|
|
96
|
+
*
|
|
97
|
+
* ### Building an Image
|
|
98
|
+
* **Example:** From a public image
|
|
99
|
+
* ```typescript
|
|
100
|
+
* export const Base = Archil.Image("Base", { image: "node:24-bookworm" });
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* **Example:** From a private registry
|
|
104
|
+
* ```typescript
|
|
105
|
+
* export const Agent = Archil.Image("Agent", {
|
|
106
|
+
* image: "ghcr.io/acme/agent:1",
|
|
107
|
+
* registry: {
|
|
108
|
+
* server: "ghcr.io",
|
|
109
|
+
* username: "acme-bot",
|
|
110
|
+
* password: Alchemy.Secret("GHCR_TOKEN"),
|
|
111
|
+
* },
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* **Example:** Build a Dockerfile and push it for Archil to pull
|
|
116
|
+
* ```typescript
|
|
117
|
+
* export const Agent = Archil.Image("Agent", {
|
|
118
|
+
* dockerfile: "./agent/Dockerfile",
|
|
119
|
+
* context: "./agent",
|
|
120
|
+
* push: {
|
|
121
|
+
* repository: "ghcr.io/acme/agent",
|
|
122
|
+
* credentials: { server: "ghcr.io", username: "acme-bot", password: Alchemy.Secret("GHCR_TOKEN") },
|
|
123
|
+
* },
|
|
124
|
+
* });
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* ### Booting Sandboxes from an Image
|
|
128
|
+
* **Example:** Sandboxes created at run time
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const sandboxes = yield* Archil.CreateSandbox(Agent);
|
|
131
|
+
* const sandbox = yield* sandboxes.create({ name: "task-1" });
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* ### Looking up an existing image
|
|
135
|
+
* `Image.lookup` references an image Alchemy doesn't manage (created in
|
|
136
|
+
* the Archil console or by another stack). It is read during plan/deploy,
|
|
137
|
+
* never created, updated or deleted.
|
|
138
|
+
* `hash` is empty: the image wasn't built by this stack.
|
|
139
|
+
*
|
|
140
|
+
* **Example:** Reference an existing image
|
|
141
|
+
* ```typescript
|
|
142
|
+
* const base = Archil.Image.lookup({ imageId: "img_123" });
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @resource
|
|
146
|
+
* @product Image
|
|
147
|
+
*/
|
|
148
|
+
export declare const Image: import("alchemy").ResourceClass<Image>;
|
|
149
|
+
/** What Archil's image service can build: nothing beyond pulling a reference. */
|
|
150
|
+
export declare const capabilities: BuildPlan.Capabilities;
|
|
151
|
+
/** Map an image response to attributes. */
|
|
152
|
+
export declare const toImageAttributes: (image: archil.Image, hash: string, source?: string) => ImageAttributes;
|
|
153
|
+
/** Plan an image source for Archil. */
|
|
154
|
+
export declare const planImage: (props: ImageProps) => Effect.Effect<{
|
|
155
|
+
hash: string;
|
|
156
|
+
platform: string;
|
|
157
|
+
dockerfile: import("@alchemy.run/docker/DockerfileParser").ParsedDockerfile;
|
|
158
|
+
base: string;
|
|
159
|
+
pull: ImageRegistry | undefined;
|
|
160
|
+
instructions: readonly import("@alchemy.run/docker/DockerfileParser").Instruction[];
|
|
161
|
+
files: BuildPlan.ContextFile[];
|
|
162
|
+
args: Record<string, string>;
|
|
163
|
+
secrets: Record<string, import("effect/Redacted").Redacted<string>>;
|
|
164
|
+
warnings: string[];
|
|
165
|
+
}, import("@alchemy.run/docker/BuildHash").BuildHashInvalidProps | BuildPlan.BuildPlanError | import("alchemy/Bundle/Bundle").BundleError | import("@alchemy.run/docker/DockerfileParser").DockerfileSyntaxError | import("effect/PlatformError").PlatformError | BuildPlan.UnsupportedDockerfile, import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
|
|
166
|
+
/**
|
|
167
|
+
* The reference Archil can pull for a plan: its base, when the plan adds
|
|
168
|
+
* nothing on top of it.
|
|
169
|
+
*/
|
|
170
|
+
export declare const pullableSource: (plan: BuildPlan.BuildPlan) => Effect.Effect<string, never, never> | Effect.Effect<never, ImageRequiresBuild, never>;
|
|
171
|
+
/** Ask Archil to pull a reference and wait until the image is ready. */
|
|
172
|
+
export declare const pullImage: (source: string, registry: ImageRegistry | undefined, hash: string) => Effect.Effect<ImageAttributes, import("./index.ts").ArchilFailed | import("./index.ts").ArchilNotReady | archil.ArchilParseError | archil.BadGateway | import("@distilled.cloud/core/errors").BadRequest | archil.BadRequest | archil.ConfigError | import("@distilled.cloud/core/errors").Conflict | import("@distilled.cloud/core/errors").Forbidden | archil.GatewayTimeout | import("effect/http/HttpClientError").HttpClientError | archil.InternalServerError | import("@distilled.cloud/core/protocol-http").InvalidInput | archil.Locked | archil.NoCapacity | archil.NotEnabled | import("@distilled.cloud/core/errors").NotFound | archil.NotFound | import("@distilled.cloud/core/sdk-error").SdkError | archil.ServiceUnavailable | archil.TooManyRequests | archil.Unauthorized | archil.UnknownArchilError | archil.UnprocessableEntity, archil.ArchilOpContext>;
|
|
173
|
+
/**
|
|
174
|
+
* The reference Archil pulls for a plan: its base when the plan adds
|
|
175
|
+
* nothing, else the plan built locally and pushed to `push`.
|
|
176
|
+
*/
|
|
177
|
+
export declare const publishPlan: (plan: BuildPlan.BuildPlan, push: ImagePush | undefined) => Effect.Effect<{
|
|
178
|
+
source: string;
|
|
179
|
+
credentials: undefined;
|
|
180
|
+
} | {
|
|
181
|
+
source: string;
|
|
182
|
+
credentials: ImageRegistry;
|
|
183
|
+
}, ImageRequiresBuild | import("@alchemy.run/docker/RegistryError").DockerImagePublicationError, import("@alchemy.run/docker/Docker").Docker | import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
|
|
184
|
+
/** Plan, publish, then pull, an image. */
|
|
185
|
+
export declare const buildImage: (props: ImageProps) => Effect.Effect<ImageAttributes, import("./index.ts").ArchilFailed | import("./index.ts").ArchilNotReady | archil.ArchilParseError | archil.BadGateway | import("@distilled.cloud/core/errors").BadRequest | archil.BadRequest | import("@alchemy.run/docker/BuildHash").BuildHashInvalidProps | BuildPlan.BuildPlanError | import("alchemy/Bundle/Bundle").BundleError | archil.ConfigError | import("@distilled.cloud/core/errors").Conflict | import("@alchemy.run/docker/DockerfileParser").DockerfileSyntaxError | import("@distilled.cloud/core/errors").Forbidden | archil.GatewayTimeout | import("effect/http/HttpClientError").HttpClientError | ImageRequiresBuild | archil.InternalServerError | import("@distilled.cloud/core/protocol-http").InvalidInput | archil.Locked | archil.NoCapacity | archil.NotEnabled | import("@distilled.cloud/core/errors").NotFound | archil.NotFound | import("@distilled.cloud/core/sdk-error").SdkError | archil.ServiceUnavailable | archil.TooManyRequests | archil.Unauthorized | archil.UnknownArchilError | archil.UnprocessableEntity | BuildPlan.UnsupportedDockerfile | import("@alchemy.run/docker/RegistryError").DockerImagePublicationError, import("@alchemy.run/docker/Docker").Docker | import("effect/FileSystem").FileSystem | import("effect/Path").Path | archil.ArchilOpContext>;
|
|
186
|
+
export declare const ImageProvider: () => import("effect/Layer").Layer<Provider.Provider<Image>, never, import("@alchemy.run/docker/Docker").Docker | import("effect/FileSystem").FileSystem | import("effect/Path").Path | archil.ArchilOpContext>;
|
|
187
|
+
export {};
|
|
188
|
+
//# sourceMappingURL=Image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.d.ts","sources":["../src/Image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAElD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACvC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,WAAW,EAAE,aAAa,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,KAAK,GAAG,QAAQ,CAC1B,cAAc,EACd,UAAU,EACV,eAAe,EACf,KAAK,EACL,SAAS,EACT,WAAW,CACZ,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;;;;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,wBAA8C;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,eAAO,MAAM,KAAK,wCAAkC,CAAC;AAErD,iFAAiF;AACjF,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,YAGpC,CAAC;AAEF,2CAA2C;AAC3C,eAAO,MAAM,iBAAiB,UACrB,MAAM,CAAC,KAAK,QACb,MAAM,WACJ,MAAM,KACb,eASD,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,SAAS,UAAW,UAAU;;;;;;;;;;;uWAMxC,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,cAAc,SAAU,SAAS,CAAC,SAAS,0FAOjD,CAAC;AAER,wEAAwE;AACxE,eAAO,MAAM,SAAS,u5BAYpB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;mNAgBtB,CAAC;AAEH,0CAA0C;AAC1C,eAAO,MAAM,UAAU,4yCAIrB,CAAC;AAEH,eAAO,MAAM,aAAa,iNAiEvB,CAAC"}
|
package/lib/Image.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import * as BuildPlan from "@alchemy.run/docker/BuildPlan";
|
|
2
|
+
import * as archil from "@distilled.cloud/archil";
|
|
3
|
+
import { isResolved } from "alchemy/Diff";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { Resource } from "alchemy/Resource";
|
|
6
|
+
import * as Data from "effect/Data";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import { waitForImage } from "./internal/archil.js";
|
|
9
|
+
/**
|
|
10
|
+
* The image needs instructions run on top of its base, and Archil only
|
|
11
|
+
* pulls finished images.
|
|
12
|
+
*/
|
|
13
|
+
export class ImageRequiresBuild extends Data.TaggedError("Archil.ImageRequiresBuild") {
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A sandbox image. Archil pulls it from a public or private registry and
|
|
17
|
+
* sandboxes boot its current digest. Public images can also be used
|
|
18
|
+
* directly as a sandbox's `baseImage`; build an `Image` for a private one,
|
|
19
|
+
* or to pin the digest every sandbox boots.
|
|
20
|
+
*
|
|
21
|
+
* Props follow `@alchemy.run/docker`'s image source, like every Alchemy
|
|
22
|
+
* image resource. Archil has no builder, so a Dockerfile is built with
|
|
23
|
+
* your local Docker and pushed to `push.repository`, and Archil pulls it
|
|
24
|
+
* from there.
|
|
25
|
+
*
|
|
26
|
+
* Archil has no API to delete an image, so destroying the resource only
|
|
27
|
+
* removes it from Alchemy's state.
|
|
28
|
+
* @see https://docs.archil.com/api-reference/images/build-image
|
|
29
|
+
*
|
|
30
|
+
* ### Building an Image
|
|
31
|
+
* **Example:** From a public image
|
|
32
|
+
* ```typescript
|
|
33
|
+
* export const Base = Archil.Image("Base", { image: "node:24-bookworm" });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* **Example:** From a private registry
|
|
37
|
+
* ```typescript
|
|
38
|
+
* export const Agent = Archil.Image("Agent", {
|
|
39
|
+
* image: "ghcr.io/acme/agent:1",
|
|
40
|
+
* registry: {
|
|
41
|
+
* server: "ghcr.io",
|
|
42
|
+
* username: "acme-bot",
|
|
43
|
+
* password: Alchemy.Secret("GHCR_TOKEN"),
|
|
44
|
+
* },
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* **Example:** Build a Dockerfile and push it for Archil to pull
|
|
49
|
+
* ```typescript
|
|
50
|
+
* export const Agent = Archil.Image("Agent", {
|
|
51
|
+
* dockerfile: "./agent/Dockerfile",
|
|
52
|
+
* context: "./agent",
|
|
53
|
+
* push: {
|
|
54
|
+
* repository: "ghcr.io/acme/agent",
|
|
55
|
+
* credentials: { server: "ghcr.io", username: "acme-bot", password: Alchemy.Secret("GHCR_TOKEN") },
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* ### Booting Sandboxes from an Image
|
|
61
|
+
* **Example:** Sandboxes created at run time
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const sandboxes = yield* Archil.CreateSandbox(Agent);
|
|
64
|
+
* const sandbox = yield* sandboxes.create({ name: "task-1" });
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* ### Looking up an existing image
|
|
68
|
+
* `Image.lookup` references an image Alchemy doesn't manage (created in
|
|
69
|
+
* the Archil console or by another stack). It is read during plan/deploy,
|
|
70
|
+
* never created, updated or deleted.
|
|
71
|
+
* `hash` is empty: the image wasn't built by this stack.
|
|
72
|
+
*
|
|
73
|
+
* **Example:** Reference an existing image
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const base = Archil.Image.lookup({ imageId: "img_123" });
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @resource
|
|
79
|
+
* @product Image
|
|
80
|
+
*/
|
|
81
|
+
export const Image = Resource("Archil.Image");
|
|
82
|
+
/** What Archil's image service can build: nothing beyond pulling a reference. */
|
|
83
|
+
export const capabilities = {
|
|
84
|
+
target: "Archil.Image",
|
|
85
|
+
platforms: ["linux/amd64"],
|
|
86
|
+
};
|
|
87
|
+
/** Map an image response to attributes. */
|
|
88
|
+
export const toImageAttributes = (image, hash, source = image.source) => ({
|
|
89
|
+
imageId: image.image_id,
|
|
90
|
+
// Archil may answer with a reference it normalized (or one an earlier
|
|
91
|
+
// build of the same image used), so keep the one that was asked for.
|
|
92
|
+
source,
|
|
93
|
+
canonicalSource: image.canonical_source,
|
|
94
|
+
digest: image.digest,
|
|
95
|
+
private: image.private,
|
|
96
|
+
hash,
|
|
97
|
+
});
|
|
98
|
+
/** Plan an image source for Archil. */
|
|
99
|
+
export const planImage = (props) => BuildPlan.plan(props.image !== undefined
|
|
100
|
+
? { image: props.image }
|
|
101
|
+
: { dockerfile: props.dockerfile, context: props.context, build: props.build }, { capabilities, pull: props.registry });
|
|
102
|
+
/**
|
|
103
|
+
* The reference Archil can pull for a plan: its base, when the plan adds
|
|
104
|
+
* nothing on top of it.
|
|
105
|
+
*/
|
|
106
|
+
export const pullableSource = (plan) => plan.instructions.length === 0 && plan.files.length === 0
|
|
107
|
+
? Effect.succeed(plan.base)
|
|
108
|
+
: Effect.fail(new ImageRequiresBuild({
|
|
109
|
+
message: `Archil.Image pulls finished images; this Dockerfile adds ${plan.instructions.length} instruction(s) on top of ${plan.base}. Set \`push: { repository, credentials }\` so Alchemy can build it and push it there.`,
|
|
110
|
+
}));
|
|
111
|
+
/** Ask Archil to pull a reference and wait until the image is ready. */
|
|
112
|
+
export const pullImage = Effect.fn(function* (source, registry, hash) {
|
|
113
|
+
const { data } = yield* archil.createImage({
|
|
114
|
+
source,
|
|
115
|
+
registry_auth: registry
|
|
116
|
+
? { username: registry.username, password: registry.password }
|
|
117
|
+
: undefined,
|
|
118
|
+
});
|
|
119
|
+
return toImageAttributes(yield* waitForImage(data.image_id), hash, source);
|
|
120
|
+
});
|
|
121
|
+
/**
|
|
122
|
+
* The reference Archil pulls for a plan: its base when the plan adds
|
|
123
|
+
* nothing, else the plan built locally and pushed to `push`.
|
|
124
|
+
*/
|
|
125
|
+
export const publishPlan = Effect.fn(function* (plan, push) {
|
|
126
|
+
if (plan.instructions.length === 0 && plan.files.length === 0) {
|
|
127
|
+
return { source: plan.base, credentials: undefined };
|
|
128
|
+
}
|
|
129
|
+
if (push === undefined) {
|
|
130
|
+
return yield* new ImageRequiresBuild({
|
|
131
|
+
message: `Archil.Image pulls finished images; this Dockerfile adds ${plan.instructions.length} instruction(s) on top of ${plan.base}. Set \`push: { repository, credentials }\` so Alchemy can build it and push it there.`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const { imageRef } = yield* Effect.scoped(BuildPlan.push(plan, { repository: push.repository, push: push.credentials }));
|
|
135
|
+
return { source: imageRef, credentials: push.credentials };
|
|
136
|
+
});
|
|
137
|
+
/** Plan, publish, then pull, an image. */
|
|
138
|
+
export const buildImage = Effect.fn(function* (props) {
|
|
139
|
+
const plan = yield* planImage(props);
|
|
140
|
+
const published = yield* publishPlan(plan, props.push);
|
|
141
|
+
return yield* pullImage(published.source, published.credentials ?? props.registry, plan.hash);
|
|
142
|
+
});
|
|
143
|
+
export const ImageProvider = () => Provider.effect(Image, Effect.gen(function* () {
|
|
144
|
+
return {
|
|
145
|
+
stables: ["imageId"],
|
|
146
|
+
// No delete or list API: nuke can't remove images.
|
|
147
|
+
nuke: { skip: true },
|
|
148
|
+
diff: Effect.fn(function* ({ news, output }) {
|
|
149
|
+
if (!isResolved(news) || output === undefined)
|
|
150
|
+
return undefined;
|
|
151
|
+
// The plan hash covers the reference, the Dockerfile and its context.
|
|
152
|
+
const plan = yield* planImage(news);
|
|
153
|
+
if (plan.hash !== output.hash)
|
|
154
|
+
return { action: "replace" };
|
|
155
|
+
return undefined;
|
|
156
|
+
}),
|
|
157
|
+
lookup: Effect.fn(function* ({ imageId }) {
|
|
158
|
+
return yield* archil.getImage({ image_id: imageId }).pipe(Effect.map(({ data }) => toImageAttributes(data, "")), Effect.catchTag("NotFound", () => Effect.undefined));
|
|
159
|
+
}),
|
|
160
|
+
read: Effect.fn(function* ({ output }) {
|
|
161
|
+
if (!output)
|
|
162
|
+
return undefined;
|
|
163
|
+
return yield* archil.getImage({ image_id: output.imageId }).pipe(Effect.map(({ data }) => toImageAttributes(data, output.hash, output.source)), Effect.catchTag("NotFound", () => Effect.undefined));
|
|
164
|
+
}),
|
|
165
|
+
reconcile: Effect.fn(function* ({ news, output, session }) {
|
|
166
|
+
const plan = yield* planImage(news);
|
|
167
|
+
for (const warning of plan.warnings)
|
|
168
|
+
yield* session.note(warning);
|
|
169
|
+
// Observe — a ready image from the same plan is kept; anything
|
|
170
|
+
// else (missing, failed, interrupted) is requested again.
|
|
171
|
+
if (output && output.hash === plan.hash) {
|
|
172
|
+
const observed = yield* archil.getImage({ image_id: output.imageId }).pipe(Effect.map(({ data }) => data), Effect.catchTag("NotFound", () => Effect.undefined));
|
|
173
|
+
if (observed?.status === "ready")
|
|
174
|
+
return toImageAttributes(observed, plan.hash, output.source);
|
|
175
|
+
if (observed?.status === "building") {
|
|
176
|
+
return toImageAttributes(yield* waitForImage(observed.image_id), plan.hash, output.source);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Ensure
|
|
180
|
+
if (plan.instructions.length > 0 || plan.files.length > 0) {
|
|
181
|
+
yield* session.note(`Building and pushing image to ${news.push?.repository}...`);
|
|
182
|
+
}
|
|
183
|
+
const published = yield* publishPlan(plan, news.push);
|
|
184
|
+
yield* session.note(`Pulling image ${published.source}...`);
|
|
185
|
+
return yield* pullImage(published.source, published.credentials ?? news.registry, plan.hash);
|
|
186
|
+
}),
|
|
187
|
+
// Archil has no image delete API.
|
|
188
|
+
delete: () => Effect.void,
|
|
189
|
+
};
|
|
190
|
+
}));
|
|
191
|
+
//# sourceMappingURL=Image.js.map
|
package/lib/Image.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.js","sources":["../src/Image.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type * as Effect from "effect/Effect";
|
|
2
|
+
/**
|
|
3
|
+
* Typed `env` for the async (non-Effect) program of an `Archil.Sandbox`.
|
|
4
|
+
* A program's environment is process environment variables, so every
|
|
5
|
+
* entry is a `string`: the object the handler receives as its second
|
|
6
|
+
* argument.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* export const Hello = Archil.Sandbox("Hello", {
|
|
11
|
+
* main: "./src/hello.ts",
|
|
12
|
+
* env: { GREETING: "hello" },
|
|
13
|
+
* });
|
|
14
|
+
* export type HelloEnv = Archil.InferEnv<typeof Hello>;
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export type InferEnv<F> = F extends Effect.Effect<infer A, infer _E, infer _R> ? InferEnv<A> : F extends {
|
|
18
|
+
readonly Props: {
|
|
19
|
+
readonly env?: infer E;
|
|
20
|
+
};
|
|
21
|
+
} ? InferEnvRecord<Exclude<E, undefined>> : InferEnvRecord<F>;
|
|
22
|
+
type InferEnvRecord<E> = {
|
|
23
|
+
readonly [K in keyof E]: string;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=InferEnv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InferEnv.d.ts","sources":["../src/InferEnv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IACpB,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,GAChD,QAAQ,CAAC,CAAC,CAAC,GACX,CAAC,SAAS;IAAE,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;CAAE,GACtD,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GACrC,cAAc,CAAC,CAAC,CAAC,CAAC;AAE1B,KAAK,cAAc,CAAC,CAAC,IAAI;IACvB,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;CAChC,CAAC"}
|
package/lib/InferEnv.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=InferEnv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InferEnv.js","sources":["../src/InferEnv.ts"],"names":[],"mappings":""}
|