Skip to content

Commit fa7b59f

Browse files
amarbakir-govsignalsclaude
authored andcommitted
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 7829da9 commit fa7b59f

2 files changed

Lines changed: 39 additions & 18 deletions

File tree

apps/webapp/app/env.server.ts

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

346346
DEPLOY_IMAGE_PLATFORM: z.string().default("linux/amd64"),
347347
DEPLOY_VERSION_SUFFIX: z.string().optional(),
348+
// Full image reference override - bypasses auto-generation of image tags
349+
// When set, all deployments will use this exact image reference
350+
// Example: "myregistry.com/myorg/myapp:1.0.5"
351+
DEPLOY_IMAGE_OVERRIDE: z.string().optional(),
348352
DEPLOY_TIMEOUT_MS: z.coerce
349353
.number()
350354
.int()

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

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -146,29 +146,46 @@ export class InitializeDeploymentService extends BaseService {
146146

147147
const deploymentShortCode = nanoid(8);
148148

149-
const [imageRefError, imageRefResult] = await tryCatch(
150-
getDeploymentImageRef({
151-
registry: registryConfig,
152-
projectRef: environment.project.externalRef,
153-
nextVersion,
154-
environmentType: environment.type,
155-
deploymentShortCode,
156-
})
157-
);
158-
159-
if (imageRefError) {
160-
logger.error("Failed to get deployment image ref", {
149+
// If DEPLOY_IMAGE_OVERRIDE is set, use it instead of generating an image reference
150+
let imageRef: string;
151+
let isEcr = false;
152+
let repoCreated = false;
153+
154+
if (env.DEPLOY_IMAGE_OVERRIDE) {
155+
imageRef = env.DEPLOY_IMAGE_OVERRIDE;
156+
logger.info("Using image override", {
157+
imageRef,
161158
environmentId: environment.id,
162159
projectId: environment.projectId,
163160
version: nextVersion,
164-
triggeredById: triggeredBy?.id,
165-
type: payload.type,
166-
cause: imageRefError.message,
167161
});
168-
throw new ServiceValidationError("Failed to get deployment image ref");
169-
}
162+
} else {
163+
const [imageRefError, imageRefResult] = await tryCatch(
164+
getDeploymentImageRef({
165+
registry: registryConfig,
166+
projectRef: environment.project.externalRef,
167+
nextVersion,
168+
environmentType: environment.type,
169+
deploymentShortCode,
170+
})
171+
);
170172

171-
const { imageRef, isEcr, repoCreated } = imageRefResult;
173+
if (imageRefError) {
174+
logger.error("Failed to get deployment image ref", {
175+
environmentId: environment.id,
176+
projectId: environment.projectId,
177+
version: nextVersion,
178+
triggeredById: triggeredBy?.id,
179+
type: payload.type,
180+
cause: imageRefError.message,
181+
});
182+
throw new ServiceValidationError("Failed to get deployment image ref");
183+
}
184+
185+
imageRef = imageRefResult.imageRef;
186+
isEcr = imageRefResult.isEcr;
187+
repoCreated = imageRefResult.repoCreated;
188+
}
172189

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

0 commit comments

Comments
 (0)