Skip to content

rvn-lambda: don't create a module-owned ECR repo for image_registry - #83

Merged
kodiakhq[bot] merged 2 commits into
mainfrom
devin/1785690977-lambda-ecr-image-registry-gate
Aug 2, 2026
Merged

rvn-lambda: don't create a module-owned ECR repo for image_registry#83
kodiakhq[bot] merged 2 commits into
mainfrom
devin/1785690977-lambda-ecr-image-registry-gate

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

rvn-lambda created and managed a per-function ECR repository for every Image-package Lambda, even when build_source = "image_registry" (images come from an externally managed repo and the module-owned repo only ever held the ravion-bootstrap seed). This mirrors rvn-ecs-web by gating repo creation on build_source.

The complication vs. ECS: ECS bootstraps from a public placeholder image, but an Image Lambda must reference a real image in a private repo at CreateFunction time. So we can't just drop the repo — we need a valid initial image from the external repo. Rather than assume :latest exists (that would fail the create if absent), this adds a required initial ref.

Changes (all in the definition; the Terraform module already supported image_uri + ecr_repository_creation_enabled=false via its image_package_configuration check):

  • Gate ECR creation off for image_registry:
    ecr_repository_creation_enabled:
    -  << lambda_type != "edge" && package_type == "Image" >>
    +  << lambda_type != "edge" && package_type == "Image" && build_source != "image_registry" >>
  • New required input initial_image_ref (shown only for image_registry), used solely to build the create-time image_uri from image_repository (digest → repo@ref, tag → repo:ref):
    image_uri: << ... && build_source == "image_registry"
      ? (initial_image_ref contains "sha256:" ? image_repository + "@" + initial_image_ref
                                              : image_repository + ":" + initial_image_ref)
      : nil >>
    
    Deploy-time image promotion is unchanged and stays authoritative (the function's image_uri is ignore_changes), so editing initial_image_ref after create has no effect — documented in the input.
  • Hide the "Image registry lifecycle" section + ecr_scan_on_push_enabled / ecr_force_deletion_enabled for image_registry (no module repo to configure), matching the ECS approach.
  • build.destinations left unchanged: for image_registry the build is disabled, so the (now-null) ecr_repository_arn reference is unused — identical to the existing rvn-ecs-web convention.

Bootstrapping for dockerfile/nixpacks is untouched: those still create a module-owned repo and seed the bootstrap image.

Release: 0.3.30.4.0 (behavior change — existing image_registry instances will have their module-owned repo removed on next apply, and the new input is required).

Testing

  • tofu fmt -check -recursive, tofu init, tofu validate — pass
  • tofu test — added image_registry_no_module_ecr (asserts no module.ecr, no bootstrap, function created from external image_uri); 7/7 pass
  • ravion-modules compiler tests — added a rvn-lambda gating/initial_image_ref/image_uri regression test; 70/70 pass

Note: make publish-local-dev was not run — this sandbox has no RAVION_API_TOKEN or reachable local dev API.

Link to Devin session: https://app.devin.ai/sessions/e4d439b5aa94444abe844384a6b1413e
Requested by: @flybayer

Greptile Summary

This PR changes image-registry Lambda bootstrapping to use an externally managed ECR image instead of creating a module-owned repository.

  • Adds the required initial_image_ref input and constructs the create-time image URI from a tag or digest.
  • Disables module-owned ECR creation and hides its lifecycle controls for image_registry.
  • Adds Terraform and compiler regression coverage for the external-image path.

Confidence Score: 4/5

The PR is safe to merge, with a non-blocking input-validation gap that defers malformed image-reference errors until Lambda creation.

The external-image provisioning path is consistently gated and tested, but initial_image_ref is interpolated into the create-time URI without validating the documented tag-or-digest contract.

Files Needing Attention: compute/lambda/rvn-lambda-definition.yml

Important Files Changed

Filename Overview
compute/lambda/rvn-lambda-definition.yml Gates managed ECR resources by build source and supplies an external image URI, but the new image-reference input lacks format validation.
compute/lambda/tests/basic.tftest.hcl Adds plan assertions confirming that external-image Lambdas create neither a managed ECR repository nor a bootstrap image.
tools/ravion-modules/test/compiler.test.ts Adds compilation assertions for input visibility, ECR gating, and tag-or-digest image URI construction.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Input["image_repository + initial_image_ref"] --> Ref{"Digest?"}
  Ref -->|"sha256:*"| Digest["repository@digest"]
  Ref -->|"tag"| Tag["repository:tag"]
  Digest --> Create["Create Lambda function"]
  Tag --> Create
  Create --> Deploy["Later Ravion deployments promote image_ref"]
  Managed["Module-owned ECR/bootstrap"] -. "disabled for image_registry" .-> Create
Loading
Prompt To Fix All With AI
### Issue 1
compute/lambda/rvn-lambda-definition.yml:215-223
**Initial image refs lack validation**

The new required `initial_image_ref` accepts empty, whitespace-containing, full-URI, and malformed digest values even though it is interpolated directly into `image_uri`; these inputs reach AWS as malformed references and defer the error until Lambda creation. Add input validation for the supported tag and `sha256` digest forms.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "rvn-lambda: skip module-owned ECR repo f..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used (3)

Gate ecr_repository_creation_enabled on build_source so image_registry Lambdas no longer create a module-owned ECR repository. Add a required initial_image_ref input used to construct image_uri for the function's first create; deploy-time image promotion stays authoritative. Hide ECR lifecycle inputs for image_registry.

Co-Authored-By: brandon <brandon@flightcontrol.dev>
@flybayer flybayer self-assigned this Aug 2, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Ravion Module Publish Plan

Dry run only. No Ravion API mutations were made.

Module Current Version New Version Description
rvn-lambda 0.3.3 0.4.0 Stop creating a module-owned ECR repository when pulling from an image registry. Add a required initial image tag or digest used to create the function before its first deployment.

Diffs

rvn-lambda 0.3.3 -> 0.4.0

--- remote
+++ compiled
       build_source: image_registry
       package_type: Image
     type: string
+  - description: Tag or digest used only to create the function before its first deployment. It must already exist in the image repository above. Deployments promote the tag or digest you pass at deploy time; changing this value afterward has no effect. Do not include the repository URI.
+    id: initial_image_ref
+    label: Initial image tag or digest
+    placeholder: sha256:... or latest
+    required: true
+    show_when:
+      build_source: image_registry
+      package_type: Image
+    type: string
   - add_button_label: Add cmd segment
     default: []
     description: Optional command arguments that override the image default command (CMD). Leave empty to use the image default.
@@
   - id: section_ecr
     label: Image registry lifecycle
     show_when:
+      build_source:
+        - dockerfile
+        - nixpacks
       lambda_type: regional
       package_type: Image
     type: section
@@
     id: ecr_scan_on_push_enabled
     label: Scan images on push
     show_when:
+      build_source:
+        - dockerfile
+        - nixpacks
       lambda_type: regional
       package_type: Image
     type: boolean
@@
     id: ecr_force_deletion_enabled
     label: Force delete image repository
     show_when:
+      build_source:
+        - dockerfile
+        - nixpacks
       lambda_type: regional
       package_type: Image
     type: boolean
@@
 
   The Lambda Function module creates an AWS Lambda function, execution role, CloudWatch log group, optional artifact bucket, and a live alias that Ravion updates during deployments. Terraform provisions the long-lived function infrastructure with either a bootstrap zip package or a bootstrap container image. Deployments publish a new function version and move the live alias.
 
-  Terraform source: [flightcontrolhq/modules/compute/lambda](https://github.com/flightcontrolhq/modules/tree/rvn-lambda@0.3.3/compute/lambda)
+  Terraform source: [flightcontrolhq/modules/compute/lambda](https://github.com/flightcontrolhq/modules/tree/rvn-lambda@0.4.0/compute/lambda)
 
   ## Use cases
 
@@
         base_path: compute/lambda
         branch: main
         execution_environment_id: << module.input.execution_environment_id >>
-        ref: rvn-lambda@0.3.3
+        ref: rvn-lambda@0.4.0
         repo: https://github.com/flightcontrolhq/modules
         stack_id: <<stack.id>>
         terraform_variables:
@@
           description: << module.input.description || nil >>
           ecr_default_lifecycle_policy_enabled: true
           ecr_force_deletion_enabled: << module.input.ecr_force_deletion_enabled >>
-          ecr_repository_creation_enabled: << module.input.lambda_type != "edge" && module.input.package_type == "Image" >>
+          ecr_repository_creation_enabled: << module.input.lambda_type != "edge" && module.input.package_type == "Image" && module.input.build_source != "image_registry" >>
           ecr_repository_name: << module.input.name >>
           ecr_scan_on_push_enabled: << module.input.ecr_scan_on_push_enabled >>
           environment_variables: '<< module.input.lambda_type == "edge" ? {} : (module.input.environment_variables || {}) >>'
@@
           function_url_invoke_mode: << module.input.function_url_invoke_mode >>
           handler: '<< module.input.package_type == "Zip" ? module.input.handler : nil >>'
           image_config: '<< module.input.lambda_type == "edge" || module.input.package_type != "Image" ? nil : ((len(module.input.image_start_command || []) > 0 || len(module.input.image_entry_point || []) > 0 || module.input.image_working_directory) ? {command: (len(module.input.image_start_command || []) > 0 ? module.input.image_start_command : nil), entry_point: (len(module.input.image_entry_point || []) > 0 ? module.input.image_entry_point : nil), working_directory: module.input.image_working_directory} : nil) >>'
+          image_uri: '<< module.input.lambda_type != "edge" && module.input.package_type == "Image" && module.input.build_source == "image_registry" ? (module.input.initial_image_ref contains "sha256:" ? module.input.image_repository + "@" + module.input.initial_image_ref : module.input.image_repository + ":" + module.input.initial_image_ref) : nil >>'
           kms_key_arn: '<< module.input.lambda_type == "edge" ? nil : (module.input.kms_key_arn || nil) >>'
           lambda_at_edge_enabled: << module.input.lambda_type == "edge" >>
           layers: '<< module.input.lambda_type == "edge" || module.input.package_type != "Zip" ? [] : module.input.layers >>'

Comment on lines +215 to +223
- id: initial_image_ref
label: Initial image tag or digest
type: string
description: Tag or digest used only to create the function before its first deployment. It must already exist in the image repository above. Deployments promote the tag or digest you pass at deploy time; changing this value afterward has no effect. Do not include the repository URI.
placeholder: sha256:... or latest
required: true
show_when:
package_type: Image
build_source: image_registry

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Initial image refs lack validation

The new required initial_image_ref accepts empty, whitespace-containing, full-URI, and malformed digest values even though it is interpolated directly into image_uri; these inputs reach AWS as malformed references and defer the error until Lambda creation. Add input validation for the supported tag and sha256 digest forms.

Context Used: AGENTS.md (source)

Knowledge Base Used: Autoscaling and Lambda Compute Modules

Prompt To Fix With AI
This is a comment left during a code review.
Path: compute/lambda/rvn-lambda-definition.yml
Line: 215-223

Comment:
**Initial image refs lack validation**

The new required `initial_image_ref` accepts empty, whitespace-containing, full-URI, and malformed digest values even though it is interpolated directly into `image_uri`; these inputs reach AWS as malformed references and defer the error until Lambda creation. Add input validation for the supported tag and `sha256` digest forms.

**Context Used:** AGENTS.md ([source](https://github.com/flightcontrolhq/modules/blob/main/AGENTS.md))

**Knowledge Base Used:** [Autoscaling and Lambda Compute Modules](https://app.greptile.com/flightcontrol/-/custom-context/knowledge-base/flightcontrolhq/modules/-/docs/compute-other.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@kodiakhq
kodiakhq Bot merged commit 50b9141 into main Aug 2, 2026
7 checks passed
@kodiakhq
kodiakhq Bot deleted the devin/1785690977-lambda-ecr-image-registry-gate branch August 2, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant