Skip to content

[EPIC] Auto-updates and daily channel #7759

@kristenwomack

Description

@kristenwomack

Problem statement

We want to make it even easier to stay current and get early access to new features. The core azd update command and daily channel are now shipping, and now we want to expand the safety net by allowing teams pin to a known-good version. We also want a one-command rollback. This epic tracks completing those guarantees so auto-update is accessible for everyone from solo developers to platform teams managing azd across their organization.

Vision

Two channels, one command, zero surprises. The foundation is live: Daily gives early adopters bleeding-edge features, Stable gets reliable releases, and azd update ties it all together with opt-in auto-update. The remaining work is about making auto-update bulletproof—crash-loop guards, version pinning, and instant rollback—so developers always have control and can always recover.

Who this helps

  • Early adopters and power users who want the newest features as soon as they're testable. The daily channel gives them early access and a direct way to influence the product direction, with a clear opt-in/opt-out path.
  • Platform engineers managing azd across teams or organizations. Version pinning, rollback capability, and safety guards give them confidence that updates are controlled and predictable—especially in CI/CD pipelines.
  • Azure developers who just want things to work. A gentle nudge when a new version is available and a one-command upgrade path means staying current is effortless.
  • Contributors and maintainers who benefit from a pre-release feedback channel that surfaces issues early, improving quality for everyone before features reach stable.

What already ships

The following capabilities are implemented and merged (PR #6942 + follow-ups #7011, #7012):

Capability Details
azd update command Manual check-and-install for the active channel. Works on Windows (MSI + script), macOS (Homebrew + binary), Linux (script + binary). Blocks in CI/CD environments.
Channel model Two channels: stable and daily. Channel inferred from binary version string (contains daily. → daily channel). Explicit set via azd update --channel stable|daily.
Channel switching Confirmation prompt on switch. Warns when switching to daily via package manager (requires uninstall-first workflow for Homebrew/winget). Channel persisted in azd config (updates.channel).
Opt-in auto-update Enable with azd config set updates.autoUpdate on. Stages new binary in background; applies on next azd invocation via ApplyStagedUpdate(). Configurable check interval (--check-interval-hours, default 24h stable / 4h daily).
Staged update pipeline StageUpdateHasStagedUpdateApplyStagedUpdateCleanStagedUpdate. Staged binary validated (verifyStagedBinary) before apply. Applied-marker tracking for post-update messaging.
Code signature verification macOS: codesign --verify. Windows: Authenticode signature check. Unsigned daily builds allowed with log warning.
MSI update backup On Windows MSI path: backupCurrentExe() creates temp backup before replace. restoreExeFromBackup() on failure. Backup cleaned up after success.
Package manager awareness Detects Homebrew, winget, apt, snap installs. Routes updates through native package manager or warns when channel switch requires uninstall.
Update cache Version check results cached to update-check.json with channel-aware expiration. Manual azd update forces fresh check (ignoreCache: true).
First-use notice Beta feature stage notice on first azd update invocation with link to feature stages documentation.

Config keys in use: updates.channel, updates.autoUpdate, updates.checkIntervalHours
Key source files: cli/azd/cmd/update.go, cli/azd/pkg/update/manager.go, cli/azd/pkg/update/config.go, cli/azd/pkg/update/msi_windows.go

Goals — remaining work (in scope)

1. Crash-loop guard (#6983)

Problem: If a staged auto-update produces a binary that panics on startup, the user is stuck. There's no AZD_SKIP_AUTO_UPDATE escape hatch, no failure counter, and no automatic rollback.

Proposed behavior:

  • AZD_SKIP_AUTO_UPDATE=1 env var: Bypasses ApplyStagedUpdate() entirely. Escape hatch for emergencies and debugging.
  • Consecutive-failure counter: Track apply attempts in a local state file (e.g., ~/.azd/update-apply-attempts.json). Increment on each ApplyStagedUpdate() call; reset to zero on successful azd startup (i.e., command runs to completion or interactive session starts).
  • Auto-disable threshold: After 3 consecutive failed apply attempts, auto-update is disabled and the staged binary is deleted. A warning is printed: "Auto-update disabled after 3 consecutive failures. Run 'azd update' to retry manually."
  • "Last good version" marker: Write the current working version to ~/.azd/last-good-version on every successful startup. This gives the rollback command (below) a known-safe target.

Open design questions:

  • Should the failure counter be time-windowed (e.g., 3 crashes within 1 hour) or purely sequential?
  • Should the auto-disable be sticky (require azd config set updates.autoUpdate on to re-enable) or auto-reset after a successful manual azd update?

2. Version pinning (#6984)

Problem: Teams need reproducible builds. Today azd update always pulls "latest" for the channel. There's no way to pin a specific version, and auto-update ignores team constraints.

Proposed behavior:

  • azd update --version X.Y.Z: Install a specific version, regardless of channel. The version must exist in the release feed for the active channel.
  • Global pin via config: azd config set updates.pinnedVersion 1.23.5. When set:
    • azd update skips the update if current version matches the pin
    • Auto-update (ApplyStagedUpdate) refuses to apply if the staged version differs from the pin
    • azd update --version overrides the pin for that invocation but doesn't clear it
  • Project-level pin via .azd-version file: A file in the project root (next to azure.yaml) containing a single semver string. When present:
    • azd prints a warning on startup if the running version doesn't match
    • Auto-update respects the project pin (won't apply a staged version that doesn't match)
    • Project pin takes precedence over global pin
  • Pin interaction with channels: Pinned version must match the active channel. Pinning a stable version while on the daily channel (or vice versa) produces an error with a clear suggestion.

Open design questions:

  • Should .azd-version support ranges (e.g., >=1.23.0 <2.0.0) or only exact versions?
  • Should azd update --version for daily builds accept build numbers (e.g., daily.12345) in addition to semver?

3. Rollback / recovery (#6982)

Problem: Today the MSI path backs up the binary temporarily during update, but the backup is deleted after success. If a user realizes the new version has a problem after a successful update, there's no way to go back without a full reinstall.

Proposed behavior:

  • Persistent backup: After a successful update (manual or auto), keep the previous binary as azd.prev (or in ~/.azd/backup/azd-<version>). Only the most recent previous version is retained.
  • azd update --rollback: Replace the current binary with the backup. Print the version being restored. Clear any staged update. Reset the crash-loop counter.
  • Rollback with no backup: If no backup exists (e.g., fresh install), print a clear error: "No previous version available. Use 'azd update --version X.Y.Z' to install a specific version."
  • Interaction with version pinning: Rollback should set updates.pinnedVersion to the restored version to prevent auto-update from immediately re-applying the problematic version. The user can clear the pin with azd config unset updates.pinnedVersion when ready.

Open design questions:

  • Should rollback keep N previous versions (like a version stack) or just the most recent?
  • Should the backup include the version metadata so azd update --rollback can report "Rolled back from X.Y.Z to A.B.C"?

Non-goals (out of scope)

  • Forced auto-updates: Updates are always opt-in. No silent upgrades, no "update required to continue" gates.
  • Managing updates for non-azd tools: That's azd tool's job. This epic covers azd itself.
  • Daily channel SLA: Daily builds prioritize early access over stability. We'll address issues quickly, but daily channel users should expect occasional rough edges compared to stable.
  • Multi-version management: Running multiple azd versions side-by-side (like nvm for Node) is out of scope.

Success criteria

  • Daily channel available with distinct branding and documentation on how to opt in (shipped)
  • azd update works on Windows, macOS, and Linux for manual updates (shipped)
  • Auto-update opt-in functional with configurable check frequency (shipped)
  • Channel switching works with confirmation and package-manager awareness (shipped)
  • Crash-loop guard: auto-update disables itself after 3 consecutive startup failures, and AZD_SKIP_AUTO_UPDATE=1 bypasses staged apply
  • Version pinning: azd config set updates.pinnedVersion X.Y.Z prevents auto-update past that version; .azd-version file provides project-level pinning
  • azd update --version X.Y.Z installs a specific version
  • Rollback: azd update --rollback restores the previous version without data loss
  • Daily channel has completed at least one full pre-release cycle (ship → feedback → fix → stable)

Dependencies

  • Azure Dev Tools (azd tool): Update mechanisms should feel cohesive. If azd tool update uses a different pattern than azd update, developers will be confused. Coordinate UX and implementation approach.
  • Release engineering: Daily build pipeline is operational. Signing and distribution for both channels are in place.
  • Installer / package manager owners: Homebrew, winget, apt, snap; package-manager-aware update routing is implemented. Additional changes may be needed for version pinning support (e.g., brew pin).

Metadata

Metadata

Assignees

Labels

area/core-cliCLI commands, cmd/, internal/cmd/area/installerInstall scripts, MSI, self-updateepicLarge multi-issue initiative

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions