Skip to content

Commit ffa725f

Browse files
committed
set image ref on create, validate digest
1 parent 07a3988 commit ffa725f

File tree

3 files changed

+30
-32
lines changed

3 files changed

+30
-32
lines changed

apps/webapp/app/v3/services/finalizeDeployment.server.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ export class FinalizeDeploymentService extends BaseService {
6060
throw new ServiceValidationError("Worker deployment is not in DEPLOYING status");
6161
}
6262

63+
const imageDigest = validatedImageDigest(body.imageDigest);
64+
6365
// Link the deployment with the background worker
6466
const finalizedDeployment = await this._prisma.workerDeployment.update({
6567
where: {
@@ -69,9 +71,7 @@ export class FinalizeDeploymentService extends BaseService {
6971
status: "DEPLOYED",
7072
deployedAt: new Date(),
7173
// Only add the digest, if any
72-
imageReference: body.imageDigest
73-
? `${deployment.imageReference}@${body.imageDigest}`
74-
: undefined,
74+
imageReference: imageDigest ? `${deployment.imageReference}@${imageDigest}` : undefined,
7575
},
7676
});
7777

@@ -121,3 +121,16 @@ export class FinalizeDeploymentService extends BaseService {
121121
return finalizedDeployment;
122122
}
123123
}
124+
125+
function validatedImageDigest(imageDigest?: string): string | undefined {
126+
if (!imageDigest) {
127+
return;
128+
}
129+
130+
if (!/^sha256:[a-f0-9]{64}$/.test(imageDigest.trim())) {
131+
logger.error("Invalid image digest", { imageDigest });
132+
return;
133+
}
134+
135+
return imageDigest.trim();
136+
}

apps/webapp/app/v3/services/finalizeDeploymentV2.server.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export class FinalizeDeploymentV2Service extends BaseService {
3434
version: true,
3535
externalBuildData: true,
3636
environment: true,
37+
imageReference: true,
3738
worker: {
3839
select: {
3940
project: true,
@@ -87,13 +88,12 @@ export class FinalizeDeploymentV2Service extends BaseService {
8788
throw new ServiceValidationError("Missing depot token");
8889
}
8990

90-
const digest = body.imageDigest;
91+
// All new deployments will set the image reference at creation time
92+
if (!deployment.imageReference) {
93+
throw new ServiceValidationError("Missing image reference");
94+
}
9195

92-
logger.debug("Pushing image to registry", {
93-
id,
94-
deployment,
95-
digest,
96-
});
96+
logger.debug("Pushing image to registry", { id, deployment, body });
9797

9898
const pushResult = await executePushToRegistry(
9999
{
@@ -112,6 +112,7 @@ export class FinalizeDeploymentV2Service extends BaseService {
112112
version: deployment.version,
113113
environmentSlug: deployment.environment.slug,
114114
projectExternalRef: deployment.worker.project.externalRef,
115+
imageReference: deployment.imageReference,
115116
},
116117
},
117118
writer
@@ -129,11 +130,7 @@ export class FinalizeDeploymentV2Service extends BaseService {
129130
});
130131

131132
const finalizeService = new FinalizeDeploymentService();
132-
133-
const finalizedDeployment = await finalizeService.call(authenticatedEnv, id, {
134-
skipPromotion: body.skipPromotion,
135-
imageDigest: digest,
136-
});
133+
const finalizedDeployment = await finalizeService.call(authenticatedEnv, id, body);
137134

138135
return finalizedDeployment;
139136
}
@@ -155,6 +152,7 @@ type ExecutePushToRegistryOptions = {
155152
version: string;
156153
environmentSlug: string;
157154
projectExternalRef: string;
155+
imageReference: string;
158156
};
159157
};
160158

@@ -180,11 +178,9 @@ async function executePushToRegistry(
180178
password: registry.password,
181179
});
182180

183-
const imageTag = `${registry.host}/${registry.namespace}/${deployment.projectExternalRef}:${deployment.version}.${deployment.environmentSlug}`;
181+
const imageTag = deployment.imageReference;
184182

185183
// Step 2: We need to run the depot push command
186-
// DEPOT_TOKEN="<org token>" DEPOT_PROJECT_ID="<project id>" depot push <build id> -t registry.digitalocean.com/trigger-failover/proj_bzhdaqhlymtuhlrcgbqy:20250124.54.prod
187-
// Step 4: Build and push the image
188184
const childProcess = execDepot(["push", depot.buildId, "-t", imageTag, "--progress", "plain"], {
189185
env: {
190186
NODE_ENV: process.env.NODE_ENV,
@@ -208,10 +204,7 @@ async function executePushToRegistry(
208204
const lines = text.split("\n").filter(Boolean);
209205

210206
errors.push(...lines);
211-
logger.debug(text, {
212-
imageTag,
213-
deployment,
214-
});
207+
logger.debug(text, { deployment });
215208

216209
// Now we can write strings directly
217210
if (writer) {

apps/webapp/app/v3/services/initializeDeployment.server.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,11 @@ export class InitializeDeploymentService extends BaseService {
6868
})
6969
: undefined;
7070

71-
const imageRefParts = [
71+
const imageRef = [
72+
env.DEPLOY_REGISTRY_HOST,
7273
env.DEPLOY_REGISTRY_NAMESPACE,
7374
`${environment.project.externalRef}:${nextVersion}.${environment.slug}`,
74-
];
75-
76-
const isLocalBuild = !externalBuildData;
77-
78-
// Local builds require the registry host to be able to push the image
79-
if (isLocalBuild) {
80-
imageRefParts.unshift(env.DEPLOY_REGISTRY_HOST);
81-
}
82-
83-
const imageRef = imageRefParts.join("/");
75+
].join("/");
8476

8577
logger.debug("Creating deployment", {
8678
environmentId: environment.id,

0 commit comments

Comments
 (0)