Azure / Azure/azure-dev

pkg/extensions: Manager.Install and Manager.Upgrade should be transactional

Open
#8,255 0 comments 0 reactions 0 assignees View on GitHub
area/extensions bug
Dominant language
Go
Stars
569
Forks
364
Avg merge
2d 19h
Merged PRs (30d)
136

Description

Both lifecycles can leave broken state on failure:

- **Upgrade** ([manager.go](https://github.com/Azure/azure-dev/blob/main/cli/azd/pkg/extensions/manager.go#L608-L628)): `Uninstall` → `Install`. If install fails, the original entry is gone from `azd extension list` with no rollback.
- **Install of a pack** ([manager.go](https://github.com/Azure/azure-dev/blob/main/cli/azd/pkg/extensions/manager.go#L393-L416)): if child N fails, children 1..N-1 installed by this call stay on disk and the bundle row is never written.

**Possible approach:** Two design options worth weighing:

1. **Snapshot-and-rollback** — track work done in this call (deps actually installed in this loop — not those that hit `ErrExtensionInstalled`); on failure, undo in reverse. For `Upgrade`, capture the pre-existing entry and restore it.
2. **Install-then-swap** — stage the new install in a sibling location, atomically swap on success.

(1) is simpler; (2) is more robust and matches what modern package managers do. Either way, the property we want is: after a failed install/upgrade, state is observably identical to before the command ran. Pre-existing installs (those the user already had) should never be touched.

**Acceptance:**
- [ ] After a failed leaf upgrade, the original entry is still present at the original version
- [ ] After a failed pack install, zero children installed *by this call* remain; pre-existing installs untouched
- [ ] After a failed pack upgrade, original bundle row + original children remain
- [ ] Failure error message indicates what was rolled back
- [ ] `manager_test.go` injects a failure mid-dep-loop and asserts state

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.