Feature: Track last successfully deployed image per service for safe re-provisioning
- Dominant language
- Go
- Stars
- 569
- Forks
- 364
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 136
Description
### 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.
Contributor guide
Research direction
Start with service_target_containerapp.go and service_target_appservice.go, where SERVICE_{SERVICE}_IMAGE_NAME is written via SetServiceProperty, then trace the deploy-success and provisioning environment paths. Define how LAST_SUCCESSFUL_* state is recorded only after a successful service lifecycle, exposed for Bicep fallback, and seeded from a live Azure resource on first deploy; verify behavior across both service targets.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, go
- Domain
- cli, cloud, devops
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100