Skip to content

Commit bf7af84

Browse files
feat(webapp): add DEPLOY_IMAGE_OVERRIDE env var for custom image references
When set, bypasses auto-generation of image tags and uses the provided image reference directly for all deployments. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 652aea8 commit bf7af84

2 files changed

Lines changed: 38 additions & 17 deletions

File tree

apps/webapp/app/env.server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ const EnvironmentSchema = z
335335

336336
DEPLOY_IMAGE_PLATFORM: z.string().default("linux/amd64"),
337337
DEPLOY_VERSION_SUFFIX: z.string().optional(),
338+
// Full image reference override - bypasses auto-generation of image tags
339+
// When set, all deployments will use this exact image reference
340+
// Example: "myregistry.com/myorg/myapp:1.0.5"
341+
DEPLOY_IMAGE_OVERRIDE: z.string().optional(),
338342
DEPLOY_TIMEOUT_MS: z.coerce
339343
.number()
340344
.int()

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

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,29 +124,46 @@ export class InitializeDeploymentService extends BaseService {
124124

125125
const deploymentShortCode = nanoid(8);
126126

127-
const [imageRefError, imageRefResult] = await tryCatch(
128-
getDeploymentImageRef({
129-
registry: registryConfig,
130-
projectRef: environment.project.externalRef,
131-
nextVersion,
132-
environmentType: environment.type,
133-
deploymentShortCode,
134-
})
135-
);
127+
// If DEPLOY_IMAGE_OVERRIDE is set, use it instead of generating an image reference
128+
let imageRef: string;
129+
let isEcr = false;
130+
let repoCreated = false;
136131

137-
if (imageRefError) {
138-
logger.error("Failed to get deployment image ref", {
132+
if (env.DEPLOY_IMAGE_OVERRIDE) {
133+
imageRef = env.DEPLOY_IMAGE_OVERRIDE;
134+
logger.info("Using image override", {
135+
imageRef,
139136
environmentId: environment.id,
140137
projectId: environment.projectId,
141138
version: nextVersion,
142-
triggeredById: triggeredBy?.id,
143-
type: payload.type,
144-
cause: imageRefError.message,
145139
});
146-
throw new ServiceValidationError("Failed to get deployment image ref");
147-
}
140+
} else {
141+
const [imageRefError, imageRefResult] = await tryCatch(
142+
getDeploymentImageRef({
143+
registry: registryConfig,
144+
projectRef: environment.project.externalRef,
145+
nextVersion,
146+
environmentType: environment.type,
147+
deploymentShortCode,
148+
})
149+
);
148150

149-
const { imageRef, isEcr, repoCreated } = imageRefResult;
151+
if (imageRefError) {
152+
logger.error("Failed to get deployment image ref", {
153+
environmentId: environment.id,
154+
projectId: environment.projectId,
155+
version: nextVersion,
156+
triggeredById: triggeredBy?.id,
157+
type: payload.type,
158+
cause: imageRefError.message,
159+
});
160+
throw new ServiceValidationError("Failed to get deployment image ref");
161+
}
162+
163+
imageRef = imageRefResult.imageRef;
164+
isEcr = imageRefResult.isEcr;
165+
repoCreated = imageRefResult.repoCreated;
166+
}
150167

151168
// We keep using `BUILDING` as the initial status if not explicitly set
152169
// to avoid changing the behavior for deployments not created in the build server.

0 commit comments

Comments
 (0)