1- import { isDockerfile } from "@cloudflare/containers-shared " ;
1+ import assert from "assert " ;
22import { type Config } from "../config" ;
3- import { type ContainerApp } from "../config/environment" ;
43import { containersScope } from "../containers" ;
54import { apply } from "../containers/deploy" ;
65import { getDockerPath } from "../environment-variables/misc-variables" ;
@@ -9,50 +8,44 @@ import { logger } from "../logger";
98import { fetchVersion } from "../versions/api" ;
109import { buildAndMaybePush } from "./build" ;
1110import { fillOpenAPIConfiguration } from "./common" ;
12- import type { BuildArgs } from "@cloudflare/containers-shared/src/types" ;
11+ import type { ContainerNormalisedConfig } from "@cloudflare/containers-shared/src/types" ;
1312
1413export async function maybeBuildContainer (
15- containerConfig : ContainerApp ,
14+ containerConfig : ContainerNormalisedConfig ,
1615 /** just the tag component. will be prefixed with the container name */
1716 imageTag : string ,
1817 dryRun : boolean ,
19- pathToDocker : string ,
20- configPath ?: string
21- ) : Promise < { image : string ; imageUpdated : boolean } > {
22- try {
23- if (
24- ! isDockerfile (
25- containerConfig . image ?? containerConfig . configuration ?. image ,
26- configPath
27- )
28- ) {
29- return {
30- image : containerConfig . image ?? containerConfig . configuration ?. image ,
31- // We don't know at this point whether the image was updated or not
32- // but we need to make sure downstream checks if it was updated so
33- // we set this to true.
34- imageUpdated : true ,
35- } ;
36- }
37- } catch ( err ) {
38- if ( err instanceof Error ) {
39- throw new UserError ( err . message ) ;
40- }
41-
42- throw err ;
18+ pathToDocker : string
19+ ) : Promise < { newImageLink : string | undefined } > {
20+ if ( "registry_link" in containerConfig ) {
21+ return {
22+ // We don't know at this point whether the image has changed
23+ // but we need to make sure API checks so
24+ // we always set this to the registry link.
25+ newImageLink : containerConfig . registry_link ,
26+ } ;
4327 }
28+ const imageFullName = containerConfig . name + ":" + imageTag . split ( "-" ) [ 0 ] ;
29+ logger . log ( "Building image" , imageFullName ) ;
4430
45- const options = getBuildArguments ( containerConfig , imageTag ) ;
46- logger . log ( "Building image" , options . tag ) ;
4731 const buildResult = await buildAndMaybePush (
48- options ,
32+ {
33+ tag : imageFullName ,
34+ pathToDockerfile : containerConfig . dockerfile ,
35+ buildContext : containerConfig . image_build_context ,
36+ args : containerConfig . image_vars ,
37+ } ,
4938 pathToDocker ,
5039 ! dryRun ,
51- configPath ,
52- containerConfig
40+ "disk_size" in containerConfig ? containerConfig . disk_size : undefined
5341 ) ;
5442
55- return { image : buildResult . image , imageUpdated : buildResult . pushed } ;
43+ if ( buildResult . pushed ) {
44+ return { newImageLink : buildResult . image } ;
45+ }
46+ // if the image has not changed, it will not have been pushed
47+ // so we don't need to update anything when we apply the container config
48+ return { newImageLink : undefined } ;
5649}
5750
5851export type DeployContainersArgs = {
@@ -65,27 +58,25 @@ export type DeployContainersArgs = {
6558
6659export async function deployContainers (
6760 config : Config ,
68- { versionId, accountId, scriptName, dryRun } : DeployContainersArgs
61+ normalisedContainerConfig : ContainerNormalisedConfig [ ] ,
62+ { versionId, accountId, scriptName } : DeployContainersArgs
6963) {
70- if ( config . containers === undefined ) {
71- return ;
72- }
64+ await fillOpenAPIConfiguration ( config , containersScope ) ;
7365
74- if ( ! dryRun ) {
75- await fillOpenAPIConfiguration ( config , containersScope ) ;
76- }
7766 const pathToDocker = getDockerPath ( ) ;
78- for ( const container of config . containers ) {
79- const version = await fetchVersion (
80- config ,
81- accountId ,
82- scriptName ,
83- versionId
67+ const version = await fetchVersion ( config , accountId , scriptName , versionId ) ;
68+ for ( const container of normalisedContainerConfig ) {
69+ const buildResult = await maybeBuildContainer (
70+ container ,
71+ versionId ,
72+ false ,
73+ pathToDocker
8474 ) ;
8575 const targetDurableObject = version . resources . bindings . find (
8676 ( durableObject ) =>
8777 durableObject . type === "durable_object_namespace" &&
8878 durableObject . class_name === container . class_name &&
79+ // DO cannot be defined in a different script to the container
8980 durableObject . script_name === undefined &&
9081 durableObject . namespace_id !== undefined
9182 ) ;
@@ -96,61 +87,18 @@ export async function deployContainers(
9687 ) ;
9788 }
9889
99- if (
100- targetDurableObject . type !== "durable_object_namespace" ||
101- targetDurableObject . namespace_id === undefined
102- ) {
103- throw new Error ( "unreachable" ) ;
104- }
105-
106- const configuration = {
107- ...config ,
108- containers : [
109- {
110- ...container ,
111- durable_objects : {
112- namespace_id : targetDurableObject . namespace_id ,
113- } ,
114- } ,
115- ] ,
116- } ;
117-
118- const buildResult = await maybeBuildContainer (
119- container ,
120- versionId ,
121- dryRun ,
122- pathToDocker ,
123- config . configPath
90+ assert (
91+ targetDurableObject . type === "durable_object_namespace" &&
92+ targetDurableObject . namespace_id !== undefined
12493 ) ;
125- container . configuration ??= { } ;
126- container . configuration . image = buildResult . image ;
127- container . image = buildResult . image ;
12894
12995 await apply (
13096 {
131- skipDefaults : false ,
132- imageUpdateRequired : buildResult . imageUpdated ,
97+ newImageLink : buildResult . newImageLink ,
98+ durable_object_namespace_id : targetDurableObject . namespace_id ,
13399 } ,
134- configuration
100+ container ,
101+ config
135102 ) ;
136103 }
137104}
138-
139- // TODO: container app config should be normalized by now in config validation
140- // getBuildArguments takes the image from `container.image` or `container.configuration.image`
141- // if the first is not defined. It accepts either a URI or path to a Dockerfile.
142- // It will return options that are usable with the build() method from containers.
143- export function getBuildArguments (
144- container : ContainerApp ,
145- idForImageTag : string
146- ) : BuildArgs {
147- const pathToDockerfile = container . image ?? container . configuration ?. image ;
148- const imageTag = container . name + ":" + idForImageTag . split ( "-" ) [ 0 ] ;
149-
150- return {
151- tag : imageTag ,
152- pathToDockerfile,
153- buildContext : container . image_build_context ,
154- args : container . image_vars ,
155- } ;
156- }
0 commit comments