Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
974b3d7
feat(exegraph): graph-driven execution engine for up/provision/deploy
jongio Apr 16, 2026
3734eb2
chore(preflight): unblock mage preflight on feat/exegraph
Apr 17, 2026
ac75c09
chore(preflight): lint + test fixes for feat/exegraph
jongio Apr 17, 2026
675fa10
fix(exegraph): address wbreza review findings (high+medium+low)
jongio Apr 17, 2026
27b3826
fix(exegraph): address remaining wbreza review findings
jongio Apr 17, 2026
77c3bc4
fix(bicep): remove dead env.LookupEnv branch in Phase 2 loop
jongio Apr 17, 2026
f91772b
fix(exegraph): address wbreza re-review findings
jongio Apr 17, 2026
58d4cf8
fix(exegraph): address copilot review findings
jongio Apr 17, 2026
7a9c8db
fix(exegraph): address wbreza pass #4 + JeffreyCA findings (HIGH)
jongio Apr 17, 2026
5f06c8f
docs(exegraph): update spec to reflect prepackage/postpackage graph n…
jongio Apr 17, 2026
c910be0
fix(exegraph): address wbreza pass #4 concurrency + behavior findings
jongio Apr 17, 2026
3726b57
style(exegraph): gofmt fixes for up_graph.go and environment_test.go
jongio Apr 17, 2026
aafd043
style(exegraph): use slices.Contains in provisionStepFailed (go fix)
jongio Apr 17, 2026
3cf734e
fix(exegraph): safe-by-default layer dep detection + dependsOn override
jongio Apr 18, 2026
427704c
Address vhvb1989 follow-ups: concurrency docs, sub-phase progress, sp…
jongio Apr 18, 2026
fe9ecd9
Address vhvb1989 follow-ups #3 (hook ordering) and #4 (telemetry)
jongio Apr 18, 2026
a6a08b3
Add 'dependson' to cspell.misc.yaml exegraph words
jongio Apr 18, 2026
2679ad5
Rephrase 'azd's' -> 'the azd' in concurrency-model.md for cspell
jongio Apr 18, 2026
16c3617
fix(provision): propagate hook-mediated env writes across layers
jongio Apr 18, 2026
2ab5356
docs(exegraph): document 8-step layer lifecycle + envMu/hookMu contract
jongio Apr 18, 2026
22e719d
chore(preflight): fix lint+cspell, exclude branch-stale playback reco…
jongio Apr 18, 2026
8be1ee5
fix(up): emit synthetic cmd.package + cmd.provision telemetry spans
jongio Apr 19, 2026
277534b
fix(deploy): wire services.<name>.uses into parallel deploy graph
jongio Apr 20, 2026
66d188b
fix(containerregistry): prevent parallel deploy contamination via uni…
jongio Apr 20, 2026
3922ea7
fix(env,up): close cross-process .env race + serialize prepackage→pre…
jongio Apr 20, 2026
a32ef22
refactor(env): polish flock helper, ctx-aware lock, defer cleanups
jongio Apr 20, 2026
d075089
chore(env): sweep stale .env.tmp-* + document mode tightening
jongio Apr 21, 2026
6ab9c3e
test: make Test_CLI_Telemetry_NestedCommands order-independent
jongio Apr 21, 2026
294bae0
test: skip multi-service remote-build test when no cassette + no live…
jongio Apr 21, 2026
9163603
chore: retrigger CI (Test_CLI_ProvisionState flaky on prior run)
jongio Apr 22, 2026
7aff87e
fix(deploy): drain progress goroutines before final render (fixes #7863)
jongio Apr 22, 2026
02953f6
refactor: address weikanglim review — remove template hash, env cache…
jongio Apr 22, 2026
21b4b01
refactor: remove external envMu — Environment is already internally t…
jongio Apr 22, 2026
f6bd5a0
fix(env): protect Save() overlay against concurrent DotenvSet (hemari…
jongio Apr 23, 2026
71d8745
fix(deploy): emit heartbeat progress during ARM polling (parallel dep…
jongio Apr 23, 2026
94bf17e
fix: address wbreza CHANGES_REQUESTED review — 23 findings
jongio Apr 23, 2026
1f7bb3a
fix: strip Bicep line comments from regex scanners to prevent false m…
jongio Apr 23, 2026
660d336
refactor: consolidate deploy graph state into deployGraphState struct
jongio Apr 24, 2026
e51e3a9
chore: retrigger CI (Test_CLI_ProvisionState flaky credential timeout…
jongio Apr 24, 2026
394f6db
fix: sequential deploy fallback when no services declare uses: edges
jongio Apr 24, 2026
4a61b1d
docs: document service deploy ordering semantics and uses: directive
jongio Apr 24, 2026
60da201
fix: add br/alias registry skip + bicep cache edge case tests
jongio Apr 24, 2026
f5c86e3
feat: advisory SERVICE_* dependency scanning + bicep cache edge case …
jongio Apr 24, 2026
fbf433d
test: add coverage for deployGraphState, resolveDAGConcurrency, and p…
jongio Apr 24, 2026
6a8ccdf
docs: fix inaccurate ordering references and stale expandedEnvCache s…
jongio Apr 24, 2026
412af5e
chore: retrigger CI (CrossBuildCLI LinuxARM64 canceled on prior run)
jongio Apr 26, 2026
8a62439
fix: resolve go-fix and golangci-lint CI failures
jongio Apr 27, 2026
7a0b45a
fix: warn on malformed concurrency env vars + bound resource-group ch…
jongio Apr 27, 2026
206b833
fix: prevent azd up hang after provisioning
jongio Apr 28, 2026
833b030
fix: use defer Unlock() consistently to prevent deadlock on recovered…
jongio Apr 28, 2026
cbf1c6f
fix: revert envMu defer in runProvisionSingleLayer (self-deadlock)
jongio Apr 29, 2026
1b4eaca
docs: document publish step timeout in spec
jongio Apr 29, 2026
55f125a
fix: harden path validation and deduplicate cache lookups
jongio Apr 29, 2026
73d4382
refactor: extract classifyStepResult and harden scheduler tests
jongio Apr 29, 2026
8bbf599
fix: show deploy progress table during azd up
jongio Apr 29, 2026
7cd12ba
docs: add debug logging and non-blocking contract docs
jongio Apr 29, 2026
60c8689
fix: resolve .env context-canceled on first run and deploy duration m…
jongio Apr 29, 2026
e4a2fa9
fix: suppress previewer output when deploy progress table is active
jongio Apr 29, 2026
f19150b
refactor: rename PreviewerSuppressor to PreviewerPauser for cspell
jongio Apr 30, 2026
bf3b35a
fix: use 'provision' step name for single-layer projects
jongio Apr 30, 2026
e0a7ec2
chore: exclude stale PreflightQuota playback tests
jongio Apr 30, 2026
c961bdc
fix: enable parallel deploy for Aspire projects via build-gate policy
jongio Apr 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .vscode/cspell.global.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ words:
- azdo
- choco
- winget
- bicepparam
- cmdhook
- containerapp
- containerapps
- Exegraph
- exegraph
- GOMAXPROCS
- unrecovered
ignoreWords:
- AADSTS
- afwp
Expand Down
5 changes: 5 additions & 0 deletions .vscode/cspell.misc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ overrides:
- singleflight
- stdlib
- whatif
- filename: ./docs/specs/exegraph/**
words:
- stdlib
- dependson
- appsettings
- filename: schemas/**/azure.yaml.json
words:
- prodapi
Expand Down
71 changes: 40 additions & 31 deletions cli/azd/.vscode/cspell-azd-dictionary.txt
Original file line number Diff line number Diff line change
@@ -1,39 +1,12 @@
AADSTS
ABRT
ACCESSTOKEN
ALLUSERS
AZCLI
AZURECLI
AZURESUBSCRIPTION
Agentic
BOOLSLICE
BUILDID
BUILDNUMBER
Backticks
Cobo
Errorf
Frontends
GOARCH
GOCOVERDIR
GOTOOLCHAIN
GOWORK
Ghostty
LASTEXITCODE
MCPJSON
PSHOME
PYTHONDONTWRITEBYTECODE
PYTHONUNBUFFERED
RPCJSONRPC
STRINGSLICE
SliceOfPtrs
Syncer
TOCTOU
Truef
Veyor
agentmanifests
aiomysql
aiopg
akvs
ALLUSERS
alphafeatures
apimanagement
apims
Expand Down Expand Up @@ -68,6 +41,7 @@ asyncpg
avmres
azapi
azblob
AZCLI
azcorelog
azdcli
azdcontext
Expand All @@ -83,17 +57,22 @@ azsdk
azureai
azureaiagent
azureappservice
AZURECLI
azurecodingagent
azureedge
azureml
azurestaticapps
AZURESUBSCRIPTION
azuretools
azureutil
azureyaml
bicepparam
Backticks
bicept
blockblob
BOOLSLICE
buildargs
BUILDID
BUILDNUMBER
buildpacks
byoi
callstack
Expand All @@ -104,6 +83,7 @@ chelupati
circleci
cmdrecord
cmdsubst
Cobo
cognitiveservices
concurx
conditionalize
Expand All @@ -120,6 +100,7 @@ csharpapp
csharpapptest
cupaloy
custommaps
dependson
deletedservices
devcenter
devcenters
Expand All @@ -142,51 +123,62 @@ envlist
envname
envsubst
errcheck
Errorf
errorinfo
errorlint
evals
eventhub
eventhubs
executil
flexconsumption
Frontends
fsnotify
funcapp
funcignore
functionapp
Ghostty
gjson
go-imath
GOARCH
GOCOVERDIR
godotenv
gofmt
golangci
googleapis
goroutines
gosec
goterm
gotest
gotestsum
GOTOOLCHAIN
govet
GOWORK
grpcserver
hotspot
Idxs
ignorefile
iidfile
ineffassign
INSTALLDIR
jaegertracing
javac
jmes
jmespath
jongio
jquery
keychain
keepalives
keychain
kubelogin
langchain
langchaingo
LASTEXITCODE
ldflags
lechnerc77
libc
llms
INSTALLDIR
localtools
maml
MCPJSON
mcptools
memfs
mergo
Expand Down Expand Up @@ -235,18 +227,25 @@ patternmatcher
pflag
pgadmin
posix
postdeploy
postprovision
predeploy
preinit
preprovision
protogen
proxying
psanford
pseudonymized
PSHOME
psycopg
psycopgbinary
pulumi
pyapp
pycache
pyproject
pytest
PYTHONDONTWRITEBYTECODE
PYTHONUNBUFFERED
pyvenv
rabbitmq
reauthentication
Expand All @@ -259,6 +258,7 @@ resourcegraph
resourcegroup
restoreapp
retriable
RPCJSONRPC
runtimes
rzip
secureobject
Expand All @@ -268,6 +268,7 @@ serverfarms
servicebus
setenvs
skus
SliceOfPtrs
snapshotter
springapp
sqlserver
Expand All @@ -277,20 +278,27 @@ staticwebapp
stdbool
stdlib
stdouttrace
STRINGSLICE
struct
structs
subst
substr
succ
swacli
syncatomic
Syncer
teamcity
testdata
threadsafe
tmpl
TOCTOU
toplevel
traceparent
tracesdk
tracestate
tracetest
trafficmanager
Truef
typeflag
unhide
unmanage
Expand All @@ -303,6 +311,7 @@ unsets
upgrader
utsname
uxlib
Veyor
vite
vsrpc
vuejs
Expand Down
8 changes: 8 additions & 0 deletions cli/azd/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ This file is the authoritative reference for core azd terminal UX patterns inclu
- **Extension-specific documentation**: Keep extension-specific environment variables and configuration documented in the extension's own docs, not in core azd reference docs, unless they are consumed by the core CLI itself
- **Verify env vars against source**: When documenting environment variables, verify the actual parsing method in code — `os.LookupEnv` (presence-only) vs `strconv.ParseBool` (true/false) vs `time.ParseDuration` vs integer seconds. Document the expected format and default value accurately

### Concurrency

The graph-driven `up`/`provision`/`deploy` engine runs multiple service steps and (when `infra.layers[]` is configured) multiple layer provision steps in parallel. Several long-lived types now have explicit locking contracts that you MUST honor when adding new methods or write paths.

See [docs/concurrency-model.md](./docs/concurrency-model.md) for the full list — `environment.Environment`, `environment.Manager`, `kubectl.Cli`, `containerAppTarget`/`aksTarget`, and `serviceManager` — and the rules for adding new concurrent state.

When adding a method that mutates one of these types: take the documented lock, hold it across the full read-modify-write, and run `go test -race` to catch missed locks (single-goroutine tests will not).

### Path Safety

- **Validate derived paths**: When deriving directory names from user input or template paths, always validate the result is not `.`, `..`, empty, or contains path separators. These can cause path traversal outside the working directory
Expand Down
14 changes: 14 additions & 0 deletions cli/azd/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@

### Features Added

- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Layer dependency analysis for `infra.layers` is now safe-by-default: when the static analyzer encounters a syntax pattern it cannot resolve to a literal env-var name (non-literal `readEnvironmentVariable(varName)` in `.bicepparam`, ARM template expressions like `[parameters('foo')]` in `.parameters.json`, or `param x = readEnvironmentVariable('Y')` defaults inside `.bicep`), the consuming layer is forced to depend on all earlier layers. This trades parallelism for correctness on under-analyzed inputs.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) New `infra.layers[].dependsOn` field in `azure.yaml` lets authors declare hook-mediated edges (for example, when a postprovision hook in another layer writes an env var that this layer's bicepparam reads at provision time) that no static analyzer can infer from `.bicep` / `.bicepparam` / `.parameters.json` contents alone. Explicit edges union with detected edges and are validated for unknown layer names, self-references, and cycles.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Add `provision.layer.*` telemetry attributes (`count`, `max_parallel`, `safe_fallback_count`, `explicit_dependson_count`) on the ambient command span for multi-layer `azd provision` / `azd up` runs so the team can measure adoption and detect when the safe-by-default detector fallback engages on real templates.

### Breaking Changes

### Bugs Fixed

- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Fix `concurrent map writes` panics when running `azd up` or `azd deploy` against multi-service projects: `*environment.Environment` now serializes all `dotenv` map access with an internal `sync.RWMutex`, the environment manager serializes `Save`/`Reload` calls, the singleton `kubectl.Cli` and `kustomize.Cli` are concurrency-safe, and AKS service publish/deploy updates to `SERVICE_<name>_IMAGE_NAME`/`ENDPOINT_URL` are wrapped in a package-level mutex (mirroring the Container Apps pattern).
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Restore intra-phase progress detail (e.g. `"Pushing image"`, `"Updating container app"`) in the per-service progress tracker during `azd deploy` and `azd up`. The graph-driven engine previously dropped sub-phase `ServiceProgress.Message` updates, leaving the tracker's "Detail" column blank between phase transitions.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Make `x-ms-client-request-id` unique per HTTP request (previously derived from the shared OpenTelemetry trace id, which duplicated the header across every call in a single `azd` invocation). The Azure ARM common-types spec requires this header to be unique per request so Azure services can use it as a deduplication / idempotency / log-correlation key for individual calls — a shared value broke that contract and could cause collisions in parallel deploy / provision scheduling. Microsoft Graph's `client-request-id` header now uses the same per-request UUID for the same reason.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) Fix cross-service image contamination when publishing multiple Container Apps in parallel via ACR remote build (`docker.remoteBuild: true`). ACR's `GetBuildSourceUploadURL` derives the relative blob path it hands back (`tasks-source/<yyyymmdd>/<correlationId>.tar.gz`) from the caller's `x-ms-correlation-request-id` header, and azd was sending the same correlation id — the root OpenTelemetry trace id shared across every request in a command — on every parallel upload. Each upload overwrote the previous service's source tarball before either build consumed it, so every Container App ended up running the last-uploaded service's image content under its own repository name. ACR source uploads now override `x-ms-correlation-request-id` with a freshly generated UUID per HTTP request so each parallel upload lands in a distinct blob.

### Other Changes

- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) **Security:** environment `.env` files are now persisted with mode `0600` (owner read/write only) on Unix-like systems. Previously they inherited the process umask (typically `0644`). The change tightens default permissions for files that may contain subscription IDs and values written via `azd env set`.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) `azd up` now emits a single `"Provisioning and deploying (azd up)"` title and consolidated final message instead of the legacy `"Packaging services (azd package)"` / `"Provisioning Azure resources (azd provision)"` / `"Deploying services (azd deploy)"` banners and the `"Your up workflow to provision and deploy to Azure completed in …"` footer. CI/automation that grep-matches the legacy strings on stdout will need to update its expected output.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) `azd up` honors `AZD_DEPLOY_CONCURRENCY` as a fallback when `AZD_UP_CONCURRENCY` is unset, so existing deploy-tuning configurations carry over to the unified up workflow.
- [[#7776]](https://github.com/Azure/azure-dev/pull/7776) `FailFast` semantics in the parallel scheduler: when a step fails, the scheduler cancels the run context to interrupt in-flight work, but steps that don't honor context cancellation (e.g., long-running ARM operations) will run to completion before the run returns. This is a behavior change versus the previous strictly-sequential `azd up`, which never started a later step after a prior failure.

## 1.24.3 (2026-05-01)

### Features Added
Expand Down
2 changes: 1 addition & 1 deletion cli/azd/cmd/actions_coverage3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func Test_NewUpAction_Constructor(t *testing.T) {
t.Parallel()
flags := &upFlags{}
console := mockinput.NewMockConsole()
a := newUpAction(flags, console, nil, nil, nil, nil, nil, nil, nil)
a := newUpAction(flags, console, nil, nil, nil, nil, nil, nil, nil, nil)
ua := a.(*upAction)
require.Same(t, flags, ua.flags)
}
Expand Down
5 changes: 5 additions & 0 deletions cli/azd/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,11 @@ func registerCommonDependencies(container *ioc.NestedContainer) {
container.MustRegisterScoped(project.NewImportManager)
container.MustRegisterScoped(project.NewServiceManager)

// Unified up action: the exegraph-backed `azd up` entry point that
// collapses provision + package + publish + deploy (and project command
// hooks) into a single DAG.
container.MustRegisterScoped(cmd.NewUpGraphAction)

// Even though the service manager is scoped based on its use of environment we can still
// register its internal cache as a singleton to ensure operation caching is consistent across all instances
container.MustRegisterSingleton(func() project.ServiceOperationCache {
Expand Down
Loading