Skip to content

Feature: Track last successfully deployed image per service for safe re-provisioning #9202

Description

@jongio

Is your feature request related to a problem?

When azd deploy runs a multi-service project, each service is built, pushed to ACR, and deployed sequentially. If the deployment fails partway through (e.g. service A deploys successfully but service B fails), the SERVICE_B_IMAGE_NAME env var points to the newly pushed image that was never verified in production.

On the next azd provision, Bicep picks up SERVICE_B_IMAGE_NAME and configures the infrastructure with an image that was never successfully deployed. This can cause the provisioned infrastructure to reference a broken or untested image.

There is currently no distinction between "the image azd most recently pushed" and "the image that was last confirmed working in a successful deploy." Projects that need this safety guarantee must build custom hook scripts to seed and track known-good image state, which is boilerplate that belongs in the CLI.

Describe the solution you'd like

After each service completes its deploy lifecycle successfully, azd should persist a LAST_SUCCESSFUL_{SERVICE}_IMAGE_NAME env var (or equivalent state). During provisioning, Bicep templates could reference this known-good image as a fallback, so that a failed deploy doesn't leave infrastructure pointing at an unverified image.

Concretely:

  1. After a service deploy succeeds, write LAST_SUCCESSFUL_{SERVICE}_IMAGE_NAME = {image} to the azd environment.
  2. Expose this value alongside SERVICE_{SERVICE}_IMAGE_NAME so Bicep can use a pattern like coalesce(candidateImage, lastSuccessfulImage).
  3. On first deploy (no prior state), seed from the live Azure resource if one exists (read the current container image from the running App Service / Container App).

Describe alternatives you considered

  • Custom preprovision/postdeploy hooks that shell out to az webapp config container show / az containerapp show to read live images and store them in azd env vars. This works but adds 100+ lines of cross-platform scripts (PowerShell + Bash) per project, queries Azure resources directly (fragile to naming conventions), and duplicates logic that azd already has internally.
  • Always using latest tag and relying on ACR immutability policies. This doesn't solve the "which image was last known-good" problem, just the tag collision problem.
  • Manual rollback via azd deploy --from-image. This requires operator intervention and doesn't prevent the next azd provision from picking up the bad image.

Additional context

azd already writes SERVICE_{SERVICE}_IMAGE_NAME in service_target_containerapp.go and service_target_appservice.go via SetServiceProperty. The proposed LAST_SUCCESSFUL_* tracking would follow the same pattern, gated on deploy success. This would complement the existing SERVICE_*_IMAGE_NAME rather than replacing it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions