Skip to content

Commit 407214f

Browse files
feat: Add DEPLOY_IMAGE_OVERRIDE env var for custom image references
Allow users to specify a custom image reference via DEPLOY_IMAGE_OVERRIDE environment variable instead of using the auto-generated format. When set, all deployments use this exact image reference, enabling workflows with externally-built images or custom naming schemes. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 544061d commit 407214f

2 files changed

Lines changed: 43 additions & 22 deletions

File tree

apps/webapp/app/env.server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ const EnvironmentSchema = z.object({
240240
DEPLOY_REGISTRY_ECR_ASSUME_ROLE_EXTERNAL_ID: z.string().optional(),
241241
DEPLOY_IMAGE_PLATFORM: z.string().default("linux/amd64"),
242242
DEPLOY_VERSION_SUFFIX: z.string().optional(), // Optional suffix for deployment versions, e.g., "hardened"
243+
// Full image reference override - bypasses auto-generation of image tags
244+
// When set, all deployments will use this exact image reference
245+
// Example: "myregistry.com/myorg/myapp:1.0.5"
246+
DEPLOY_IMAGE_OVERRIDE: z.string().optional(),
243247
DEPLOY_TIMEOUT_MS: z.coerce
244248
.number()
245249
.int()

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

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,34 +69,51 @@ export class InitializeDeploymentService extends BaseService {
6969
})
7070
: undefined;
7171

72-
const [imageRefError, imageRefResult] = await tryCatch(
73-
getDeploymentImageRef({
74-
host: env.DEPLOY_REGISTRY_HOST,
75-
namespace: env.DEPLOY_REGISTRY_NAMESPACE,
76-
projectRef: environment.project.externalRef,
77-
nextVersion,
78-
environmentSlug: environment.slug,
79-
registryTags: env.DEPLOY_REGISTRY_ECR_TAGS,
80-
assumeRole: {
81-
roleArn: env.DEPLOY_REGISTRY_ECR_ASSUME_ROLE_ARN,
82-
externalId: env.DEPLOY_REGISTRY_ECR_ASSUME_ROLE_EXTERNAL_ID,
83-
},
84-
})
85-
);
72+
// If DEPLOY_IMAGE_OVERRIDE is set, use it instead of generating an image reference
73+
let imageRef: string;
74+
let isEcr = false;
75+
let repoCreated = false;
8676

87-
if (imageRefError) {
88-
logger.error("Failed to get deployment image ref", {
77+
if (env.DEPLOY_IMAGE_OVERRIDE) {
78+
imageRef = env.DEPLOY_IMAGE_OVERRIDE;
79+
logger.info("Using image override", {
80+
imageRef,
8981
environmentId: environment.id,
9082
projectId: environment.projectId,
9183
version: nextVersion,
92-
triggeredById: triggeredBy?.id,
93-
type: payload.type,
94-
cause: imageRefError.message,
9584
});
96-
throw new ServiceValidationError("Failed to get deployment image ref");
97-
}
85+
} else {
86+
const [imageRefError, imageRefResult] = await tryCatch(
87+
getDeploymentImageRef({
88+
host: env.DEPLOY_REGISTRY_HOST,
89+
namespace: env.DEPLOY_REGISTRY_NAMESPACE,
90+
projectRef: environment.project.externalRef,
91+
nextVersion,
92+
environmentSlug: environment.slug,
93+
registryTags: env.DEPLOY_REGISTRY_ECR_TAGS,
94+
assumeRole: {
95+
roleArn: env.DEPLOY_REGISTRY_ECR_ASSUME_ROLE_ARN,
96+
externalId: env.DEPLOY_REGISTRY_ECR_ASSUME_ROLE_EXTERNAL_ID,
97+
},
98+
})
99+
);
98100

99-
const { imageRef, isEcr, repoCreated } = imageRefResult;
101+
if (imageRefError) {
102+
logger.error("Failed to get deployment image ref", {
103+
environmentId: environment.id,
104+
projectId: environment.projectId,
105+
version: nextVersion,
106+
triggeredById: triggeredBy?.id,
107+
type: payload.type,
108+
cause: imageRefError.message,
109+
});
110+
throw new ServiceValidationError("Failed to get deployment image ref");
111+
}
112+
113+
imageRef = imageRefResult.imageRef;
114+
isEcr = imageRefResult.isEcr;
115+
repoCreated = imageRefResult.repoCreated;
116+
}
100117

101118
logger.debug("Creating deployment", {
102119
environmentId: environment.id,

0 commit comments

Comments
 (0)