Skip to content

Bunch of Azure fixes#2087

Merged
lionello merged 14 commits intomainfrom
lio/azure-changes
May 5, 2026
Merged

Bunch of Azure fixes#2087
lionello merged 14 commits intomainfrom
lio/azure-changes

Conversation

@lionello
Copy link
Copy Markdown
Member

@lionello lionello commented May 5, 2026

Description

  • fix: replace Info with Warn for empty stack and workspace messages avoid interference with --json
  • streamline CD bootstrapping: only bootstrap what's needed, EAFP
  • added term.Timing() helper for profiling bootstrap performance
  • use slog for AI agent debugging (avoid super long debug messages)
  • handle empty endpoints (because pulumi-defang writes "" to worker endpoint output)
  • consistent use of term.Warn for "no stacks", "no projects", "no configs", etc.

Linked Issues

Checklist

  • I have performed a self-review of my code
  • I have added appropriate tests
  • I have updated the Defang CLI docs and/or README to reflect my changes, if necessary

Summary by CodeRabbit

  • Bug Fixes

    • Improved health-check handling for varied endpoint formats
  • Improvements

    • Faster Azure operation polling (2s)
    • More prominent warning messages when no stacks, workspaces, or projects are found
    • Consistent upload URLs now place blobs under an "uploads/" path
    • Updated interactive stack labels and date formatting (bracket-style)
  • Refactor

    • CD setup/deploy flow and Azure CD storage handling made more robust and idempotent
  • Tests

    • Updated tests and interactive-selection expectations to match new behaviors and labels

@lionello lionello requested a review from jordanstephens as a code owner May 5, 2026 00:28
@lionello lionello requested a review from edwardrf May 5, 2026 00:28
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ccfab849-85a8-4fa0-930d-df3cf17d97c5

📥 Commits

Reviewing files that changed from the base of the PR and between 642dda8 and 61d3494.

📒 Files selected for processing (1)
  • src/pkg/clouds/azure/aca/job.go

📝 Walkthrough

Walkthrough

Refactors Azure BYOC/CD and blob storage access and wiring (ETag, job startup, upload URLs), changes Pulumi state parsing callback, updates stack label formatting and account derivation, adjusts several CLI empty-result messages to warnings, adds timing instrumentation, and migrates one debug logger to slog.

Changes

Azure BYOC / CD and Blob Storage

Layer / File(s) Summary
Data Shape & API
src/pkg/cli/client/byoc/state/parse.go, src/pkg/cli/client/byoc/state/parse_test.go
ParsePulumiStateFile signature removed the bucket arg; objLoader callback now takes (ctx, object string); tests updated.
Driver State & Credential Caching
src/pkg/clouds/azure/cd/driver.go, src/pkg/clouds/azure/cd/blob.go
Added Driver.storageKeyMu and Driver.storageKey; newSharedKeyCredential lazily initializes/caches storage key; added Driver.IterateBlobs and Driver.DownloadBlob wrappers; container-explicit functions made unexported.
Container Resolution & Setup
src/pkg/clouds/azure/cd/setup.go
Added resolveBlobContainer that prefers existing pulumi then projects; FindStorageAccount/SetUpStorageAccount set d.BlobContainerName from resolver; reduced container-creation logic.
Upload Path & SAS
src/pkg/clouds/azure/cd/upload.go
CreateUploadURL prefixes blob names with uploads/ and uses d.newSharedKeyCredential(ctx) for signing.
BYOC Azure Client Flow
src/pkg/cli/client/byoc/azure/byoc.go
Removed setUpDone field; added SetUpCD(ctx, force), setUpJob(ctx), environment(...), cdCommand/runCdCommand; concurrent Pulumi state parsing using driver.DownloadBlob; many methods instrumented with defer term.Timing()().
BYOC AWS/GCP Callers
src/pkg/cli/client/byoc/aws/list.go, src/pkg/cli/client/byoc/gcp/byoc.go
Call sites updated to the new ParsePulumiStateFile loader signature; AWS listing goroutines stream parsed state infos into channels with ctx.Done guards.
Tests & Contexts
src/pkg/cli/client/byoc/azure/byoc_test.go, src/pkg/clouds/azure/*_test.go
Tests updated to use t.Context() and reflect API/behavior changes (container name, env keys, renamed helpers).

Stack Selector, CLI messages, and Miscellaneous

Layer / File(s) Summary
Parameters / Account
src/pkg/stacks/stacks.go, src/pkg/stacks/manager.go
Parameters.Account() now returns Azure subscription ID for Azure; ListRemote sets ListItem.Account from parsed params with fallback to stack.GetProviderAccountId().
Label Generation
src/pkg/stacks/selector.go, src/pkg/stacks/selector_test.go
Renamed MakeStackSelectorLabelsmakeStackSelectorLabels; labels now use s.Account directly, date format changed to time.UnixDate, and multi-part labels use bracketed/space formatting (e.g., name [acct]). Tests updated.
CLI Empty-Result Severity
src/cmd/cli/command/stack.go, src/cmd/cli/command/stack_test.go, src/cmd/cli/command/workspace.go, src/pkg/cli/cd.go
Empty-result user messages changed from info/printf to warning-level (Warn/Warnf); tests updated to expect warning prefixes.
Timing Utility & Instrumentation
src/pkg/term/timing.go, various azure files
Added term.Timing() helper; many Azure/CD/job functions now use defer term.Timing()() for timing logs.
Healthcheck Normalization & Logging Migration
src/pkg/cli/getServices.go, src/pkg/agent/plugins/compat_oai/generate.go
Healthcheck endpoints now preserve explicit schemes, prepend https:// for bare hosts, and skip others; generate.go switched debug logging from term.Debugf to slog.DebugContext.
CD Env Wiring & Proto / Module
src/pkg/cli/client/byoc/aws/byoc.go, src/protos/io/defang/v1/fabric.proto, src/go.mod
Moved DEFANG_STATES_UPLOAD_URL/DEFANG_EVENTS_UPLOAD_URL env assignment later in runCdCommand; renamed enum CD_TYPE_AZURE_ACI_JOBIDCD_TYPE_AZURE_ACA_JOBID; made golang.org/x/sync v0.19.0 a direct require.

Sequence Diagram(s)

sequenceDiagram
participant CLI as CLI
participant Byoc as ByocAzure
participant Driver as AzureDriver
participant Blob as AzureBlob
participant ACA as ACAJob
CLI->>Byoc: Deploy / CdCommand (cdCommand, env)
Byoc->>Byoc: SetUpCD(ctx) / setUpJob(ctx)
Byoc->>Driver: IterateBlobs(ctx, prefix) / DownloadBlob(ctx, key)
Driver->>Blob: List / Get / SAS sign (uses cached storageKey)
Blob-->>Driver: Blob metadata / bytes
Driver-->>Byoc: blob bytes / state.Info
Byoc->>ACA: StartJobExecution (env with ETAG, DEFANG_MODE, upload URLs)
ACA->>Blob: Log workspace lookup / key fetch
ACA-->>Byoc: job execution status / logs
Byoc-->>CLI: Job ID / ETag / result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jordanstephens
  • edwardrf
  • raphaeltm

"🐰
I hopped through blobs and labels bright,
Bracketed stacks now look just right.
Timers tick, warnings softly chime,
Uploads find 'uploads/' every time.
Hooray for tidy code and rhyme!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Bunch of Azure fixes' accurately reflects the primary focus of the changeset, which encompasses multiple Azure-related improvements and bug fixes across BYOC, ACA, and CD infrastructure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lio/azure-changes

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.1)

level=warning msg="The linter 'gomodguard' is deprecated (since v2.12.0) due to: new major version. Replaced by gomodguard_v2."
level=warning msg="Suggested new configuration:\nlinters:\n enable:\n - gomodguard_v2\n"
level=warning msg="[linters_context] running gomodguard failed: unable to read module file go.mod: current working directory must have a go.mod file: if you are not using go modules it is suggested to disable this linter"
level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/pkg/cli/client/byoc/aws/list.go (1)

77-85: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Close each S3 object body after reading it.

GetObject returns a streaming body that must be closed. In this loop, leaking bodies will eventually pin connections and can make ListPulumiStacks stall or fail on buckets with many state files.

Suggested fix
 			state, err := state.ParsePulumiStateFile(ctx, s3Obj{obj}, func(ctx context.Context, path string) ([]byte, error) {
 				getObjectOutput, err := s3client.GetObject(ctx, &s3.GetObjectInput{
 					Bucket: &bucketName,
 					Key:    &path,
 				})
 				if err != nil {
 					return nil, err
 				}
-				return io.ReadAll(getObjectOutput.Body)
+				defer getObjectOutput.Body.Close()
+				return io.ReadAll(getObjectOutput.Body)
 			})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/cli/client/byoc/aws/list.go` around lines 77 - 85, The loop calling
s3client.GetObject inside the state.ParsePulumiStateFile call is leaking
streaming bodies; after successfully calling s3client.GetObject (in the
anonymous func passed to state.ParsePulumiStateFile) ensure you close
getObjectOutput.Body (e.g., call getObjectOutput.Body.Close() via defer
immediately after checking err == nil) so the HTTP connection is released; make
sure the close runs regardless of subsequent io.ReadAll errors to avoid pinned
connections when processing many s3Obj entries.
src/pkg/clouds/azure/cd/blob.go (1)

26-44: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Synchronize the cached storage-key initialization.

CdList spawns goroutines that call DownloadBlob concurrently (byoc.go:127), which invokes newSharedKeyCredential without synchronization. The unsynchronized reads and writes to d.storageKey at lines 27–28 and 30–42 create a data race. Concurrent goroutines can also trigger duplicate ListKeys API calls (line 35).

Guard the lazy initialization with sync.Once or a mutex on Driver.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/clouds/azure/cd/blob.go` around lines 26 - 44, The Driver's lazy init
of d.storageKey in newSharedKeyCredential is racy (used concurrently by CdList
-> DownloadBlob). Protect the initialization by adding synchronization on Driver
(e.g., a sync.Mutex or sync.Once field) so that reads/writes to storageKey are
synchronized and only one goroutine calls NewStorageAccountsClient/ListKeys;
update newSharedKeyCredential to check storageKey under the lock (or via Once)
and perform the API call while holding the lock (or via the Once.Do) to avoid
duplicate ListKeys calls and data races.
🧹 Nitpick comments (5)
src/pkg/stacks/selector_test.go (1)

556-663: ⚡ Quick win

Add a DeployedAt table case to lock down timestamp label formatting.

stackLabelParts now includes a non-zero deployed-at branch; a dedicated table entry here would prevent silent regressions in label rendering.

As per coding guidelines: **/*_test.go: "Use table-driven tests for comprehensive test coverage in unit tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/stacks/selector_test.go` around lines 556 - 663, Add a table-driven
test case to TestMakeStackSelectorLabels that covers the non-zero deployed-at
branch by passing a ListItem with a populated DeployedAt timestamp and asserting
makeStackSelectorLabels emits the expected timestamp fragment (matching the
formatting produced by stackLabelParts); update the tests slice with a case name
like "include deployed at timestamp" that supplies a deterministic DeployedAt
value and the corresponding wantLabels entry so future changes to
stackLabelParts's timestamp formatting will fail the test.
src/pkg/stacks/manager_test.go (1)

650-832: ⚡ Quick win

Add a table case for account precedence/fallback in remote stacks.

Given the new ListRemote account logic, please add a case that asserts: (1) stack-file account wins when present, and (2) providerAccountId is used when stack-file account is empty.

As per coding guidelines: **/*_test.go: "Use table-driven tests for comprehensive test coverage in unit tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/stacks/manager_test.go` around lines 650 - 832, Add a new
table-driven case to TestGetStack that covers remote account precedence: create
a case (e.g. name "remote stack account precedence") with options
Default.Parameters{Name: "remotestack-account"}, set remoteStack to a Parameters
instance that in one variant contains a stack-file account variable (e.g.
remoteStack.Variables["ACCOUNT"] = "stack-file-account") and assert expectedEnv
contains that account; add a second variant where the stack-file account is
empty but the provider account id is present (simulate by setting
remoteStack.Variables["PROVIDER_ACCOUNT_ID"] = "provider-account") and assert
expectedEnv falls back to "provider-account". Place the case in the existing
TestGetStack table alongside the other entries and set expectedStack/expectedEnv
accordingly so the test validates that ListRemote account logic prefers the
stack-file account and otherwise uses providerAccountId.
src/pkg/cli/client/byoc/azure/byoc_test.go (1)

283-288: ⚡ Quick win

Don't leave the new CDImage guard test skipped.

t.Skip("not sure") means this path is no longer covered, so a regression in setUpJob's precondition will slip through silently. Either assert the expected error now or drop the test until the behavior is defined.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/cli/client/byoc/azure/byoc_test.go` around lines 283 - 288, Remove
the t.Skip in TestSetUpJobMissingCDImage and make the test assert the expected
failure instead of being skipped: call newTestProvider(t,
cloudazure.LocationEastUS, "sub") and invoke b.setUpJob(t.Context()), then
require err != nil and optionally assert the error message mentions the missing
CDImage (or matches the configured precondition error) so the precondition in
setUpJob is exercised; if the intended behavior is undefined, remove the test
entirely instead of skipping it.
src/pkg/clouds/azure/cd/driver_test.go (1)

289-300: ⚡ Quick win

Keep these assertions on the exported blob APIs.

Switching these tests to iterateBlobsInContainer / downloadBlobFromContainer bypasses the new wrapper logic in blob.go, so regressions in IterateBlobs and DownloadBlob would no longer be caught here. Prefer exercising the public entrypoints and reserve helper tests for helper-specific behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/clouds/azure/cd/driver_test.go` around lines 289 - 300, The tests are
calling unexported helpers iterateBlobsInContainer and downloadBlobFromContainer
which bypass the public wrapper in blob.go; change the calls to use the exported
methods IterateBlobs and DownloadBlob on the driver (e.g. replace
d.iterateBlobsInContainer(...) with d.IterateBlobs(...) and
d.downloadBlobFromContainer(...) with d.DownloadBlob(...)), keep the same
contexts/inputs and assertions expecting errors, and ensure the test exercises
the public entrypoints so regressions in IterateBlobs and DownloadBlob are
caught.
src/pkg/cli/client/byoc/azure/byoc.go (1)

111-130: ⚡ Quick win

Use structured slog fields for the new blob-scan debug path.

These new debug messages are string-formatted, so the blob name and error are harder to filter and they diverge from the repo logging rule. Switching this path to slog.Debug/DebugContext with named fields would keep it machine-readable.

As per coding guidelines, **/*.go: Use log/slog for structured debug logging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/cli/client/byoc/azure/byoc.go` around lines 111 - 130, Replace the
unstructured term.Debug/term.Debugf calls in the blob-scan goroutine with
structured slog logging (e.g., slog.Debug or slog.DebugContext) and emit named
fields for the blob name and error so logs remain machine-readable; specifically
update the messages around the iterator error and the ParsePulumiStateFile skip
(the calls around state.ParsePulumiStateFile, the loop over blobs, and the use
of item.Name()) to call slog.Debug/DebugContext with attributes like "blob":
item.Name() and "err": err (or "reason": err) instead of string formatting,
keeping the surrounding control flow (ctx/cancel, wg, stackCh, and
b.driver.DownloadBlob) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pkg/cli/client/byoc/azure/byoc.go`:
- Around line 422-425: CdCommand/cdCommand may leave cmd.mode at the enum zero
value causing env["DEFANG_MODE"] to be unconditionally set to
"deployment_mode_unspecified"; change the logic so DEFANG_MODE is only added to
env when cmd.mode is explicitly set (i.e., not the enum zero/default). In other
words, guard the assignment of env["DEFANG_MODE"] (currently using
cmd.mode.String()) with a check like "if cmd.mode != 0" or the concrete enum's
UNSPECIFIED value so that existing default behavior is preserved when mode is
unset.
- Around line 117-147: The loop launches an unbounded goroutine per blob causing
unbounded concurrent b.driver.DownloadBlob calls; limit concurrency by
introducing a semaphore/bounded worker pool (e.g., a buffered channel sized to a
constant like maxParallel) and acquire it before starting the goroutine or
before calling DownloadBlob, then release it in a defer so only maxParallel
downloads run at once; keep existing wg, ctx cancellation,
state.ParsePulumiStateFile and sending to stackCh the same, but ensure the
semaphore is respected around the download/parse work to prevent Azure
throttling and memory spikes.

In `@src/pkg/cli/getServices.go`:
- Around line 107-112: The current check treats any colon in endpoint as a
signal to skip (causing endpoints like "example.com:443" to be marked skipped),
so replace the colon check with a scheme delimiter check: change the condition
that currently uses strings.Contains(endpoint, ":") to instead check for "://",
and only prepend "https://" when endpoint != "" && !strings.Contains(endpoint,
"://"); keep the else branch that sets *results[serviceInfo.Service.Name] =
"skipped" for truly invalid or non-HTTP schemes. This preserves allowing
schemeless host:port values while still defaulting bare hosts to HTTPS.
- Around line 112-124: Multiple goroutines and the main thread can concurrently
write to the same results map entry (results[serviceInfo.Service.Name]) — e.g.,
main thread writes "skipped" while spawned goroutines running RunHealthcheck
also assign to *results[serviceInfo.Service.Name], causing a race; protect all
reads/writes to the results map entry using a mutex (e.g., a sync.Mutex or
sync.RWMutex) or a per-service lock: acquire the lock before setting "skipped"
and also acquire it inside the goroutine before assigning result, then release
after the write so updates to results[serviceInfo.Service.Name] are serialized
while keeping wg, RunHealthcheck, and existing control flow unchanged.

In `@src/pkg/clouds/azure/aca/job.go`:
- Around line 202-211: The code dereferences
resp.Properties.AppLogsConfiguration without a nil check; update the Get
response handling in the SetUpManagedEnvironment flow (the envClient.Get block)
to first verify resp.Properties.AppLogsConfiguration != nil before assigning lc
:= *resp.Properties.AppLogsConfiguration and before accessing its fields
(Destination, LogAnalyticsConfiguration.CustomerID); if AppLogsConfiguration is
nil, skip this configured-check branch and continue creating/configuring the
environment, ensuring j.EnvironmentID is only set when resp.ID is valid and the
log-analytics matching condition succeeds.

---

Outside diff comments:
In `@src/pkg/cli/client/byoc/aws/list.go`:
- Around line 77-85: The loop calling s3client.GetObject inside the
state.ParsePulumiStateFile call is leaking streaming bodies; after successfully
calling s3client.GetObject (in the anonymous func passed to
state.ParsePulumiStateFile) ensure you close getObjectOutput.Body (e.g., call
getObjectOutput.Body.Close() via defer immediately after checking err == nil) so
the HTTP connection is released; make sure the close runs regardless of
subsequent io.ReadAll errors to avoid pinned connections when processing many
s3Obj entries.

In `@src/pkg/clouds/azure/cd/blob.go`:
- Around line 26-44: The Driver's lazy init of d.storageKey in
newSharedKeyCredential is racy (used concurrently by CdList -> DownloadBlob).
Protect the initialization by adding synchronization on Driver (e.g., a
sync.Mutex or sync.Once field) so that reads/writes to storageKey are
synchronized and only one goroutine calls NewStorageAccountsClient/ListKeys;
update newSharedKeyCredential to check storageKey under the lock (or via Once)
and perform the API call while holding the lock (or via the Once.Do) to avoid
duplicate ListKeys calls and data races.

---

Nitpick comments:
In `@src/pkg/cli/client/byoc/azure/byoc_test.go`:
- Around line 283-288: Remove the t.Skip in TestSetUpJobMissingCDImage and make
the test assert the expected failure instead of being skipped: call
newTestProvider(t, cloudazure.LocationEastUS, "sub") and invoke
b.setUpJob(t.Context()), then require err != nil and optionally assert the error
message mentions the missing CDImage (or matches the configured precondition
error) so the precondition in setUpJob is exercised; if the intended behavior is
undefined, remove the test entirely instead of skipping it.

In `@src/pkg/cli/client/byoc/azure/byoc.go`:
- Around line 111-130: Replace the unstructured term.Debug/term.Debugf calls in
the blob-scan goroutine with structured slog logging (e.g., slog.Debug or
slog.DebugContext) and emit named fields for the blob name and error so logs
remain machine-readable; specifically update the messages around the iterator
error and the ParsePulumiStateFile skip (the calls around
state.ParsePulumiStateFile, the loop over blobs, and the use of item.Name()) to
call slog.Debug/DebugContext with attributes like "blob": item.Name() and "err":
err (or "reason": err) instead of string formatting, keeping the surrounding
control flow (ctx/cancel, wg, stackCh, and b.driver.DownloadBlob) unchanged.

In `@src/pkg/clouds/azure/cd/driver_test.go`:
- Around line 289-300: The tests are calling unexported helpers
iterateBlobsInContainer and downloadBlobFromContainer which bypass the public
wrapper in blob.go; change the calls to use the exported methods IterateBlobs
and DownloadBlob on the driver (e.g. replace d.iterateBlobsInContainer(...) with
d.IterateBlobs(...) and d.downloadBlobFromContainer(...) with
d.DownloadBlob(...)), keep the same contexts/inputs and assertions expecting
errors, and ensure the test exercises the public entrypoints so regressions in
IterateBlobs and DownloadBlob are caught.

In `@src/pkg/stacks/manager_test.go`:
- Around line 650-832: Add a new table-driven case to TestGetStack that covers
remote account precedence: create a case (e.g. name "remote stack account
precedence") with options Default.Parameters{Name: "remotestack-account"}, set
remoteStack to a Parameters instance that in one variant contains a stack-file
account variable (e.g. remoteStack.Variables["ACCOUNT"] = "stack-file-account")
and assert expectedEnv contains that account; add a second variant where the
stack-file account is empty but the provider account id is present (simulate by
setting remoteStack.Variables["PROVIDER_ACCOUNT_ID"] = "provider-account") and
assert expectedEnv falls back to "provider-account". Place the case in the
existing TestGetStack table alongside the other entries and set
expectedStack/expectedEnv accordingly so the test validates that ListRemote
account logic prefers the stack-file account and otherwise uses
providerAccountId.

In `@src/pkg/stacks/selector_test.go`:
- Around line 556-663: Add a table-driven test case to
TestMakeStackSelectorLabels that covers the non-zero deployed-at branch by
passing a ListItem with a populated DeployedAt timestamp and asserting
makeStackSelectorLabels emits the expected timestamp fragment (matching the
formatting produced by stackLabelParts); update the tests slice with a case name
like "include deployed at timestamp" that supplies a deterministic DeployedAt
value and the corresponding wantLabels entry so future changes to
stackLabelParts's timestamp formatting will fail the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5de98887-564e-4b14-983a-3117384fd9e4

📥 Commits

Reviewing files that changed from the base of the PR and between c38a8c5 and ee534a9.

📒 Files selected for processing (26)
  • src/cmd/cli/command/stack.go
  • src/cmd/cli/command/stack_test.go
  • src/cmd/cli/command/workspace.go
  • src/pkg/agent/plugins/compat_oai/generate.go
  • src/pkg/cli/cd.go
  • src/pkg/cli/client/byoc/aws/list.go
  • src/pkg/cli/client/byoc/azure/byoc.go
  • src/pkg/cli/client/byoc/azure/byoc_test.go
  • src/pkg/cli/client/byoc/gcp/byoc.go
  • src/pkg/cli/client/byoc/state/parse.go
  • src/pkg/cli/client/byoc/state/parse_test.go
  • src/pkg/cli/getServices.go
  • src/pkg/clouds/azure/aca/job.go
  • src/pkg/clouds/azure/aca/job_test.go
  • src/pkg/clouds/azure/cd/blob.go
  • src/pkg/clouds/azure/cd/driver.go
  • src/pkg/clouds/azure/cd/driver_test.go
  • src/pkg/clouds/azure/cd/setup.go
  • src/pkg/clouds/azure/cd/upload.go
  • src/pkg/clouds/azure/common.go
  • src/pkg/stacks/manager.go
  • src/pkg/stacks/manager_test.go
  • src/pkg/stacks/selector.go
  • src/pkg/stacks/selector_test.go
  • src/pkg/stacks/stacks.go
  • src/pkg/term/timing.go

Comment thread src/pkg/cli/client/byoc/azure/byoc.go Outdated
Comment thread src/pkg/cli/client/byoc/azure/byoc.go
Comment thread src/pkg/cli/getServices.go
Comment thread src/pkg/cli/getServices.go
Comment thread src/pkg/clouds/azure/aca/job.go
Copy link
Copy Markdown
Contributor

@edwardrf edwardrf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LBTM

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/pkg/cli/client/byoc/state/parse.go (1)

51-51: ⚡ Quick win

Use structured slog for the debug log statement.

Line 51 uses term.Debugf, which is unstructured logging and diverges from the coding guideline requiring log/slog for structured debug logging in Go files. Switch to slog.DebugContext with keyed attributes ("object" and "size_bytes").

Proposed change
 import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"log/slog"
 	"path"
 	"strconv"
 	"strings"
@@
-	term.Debugf("loading Pulumi state from %q (size %d bytes)", obj.Name(), obj.Size())
+	slog.DebugContext(ctx, "loading Pulumi state", "object", obj.Name(), "size_bytes", obj.Size())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pkg/cli/client/byoc/state/parse.go` at line 51, Replace the unstructured
term.Debugf call with a structured slog call: use slog.DebugContext(ctx, ...)
instead of term.Debugf and pass keyed attributes for the object name and size
(e.g. slog.String("object", obj.Name()) and slog.Int64("size_bytes",
obj.Size())). Update imports to include "log/slog" and ensure a context variable
(ctx) is in scope where the original term.Debugf is called; locate the call to
term.Debugf in parse.go and replace it with slog.DebugContext using obj.Name()
and obj.Size() as the attribute values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pkg/clouds/azure/aca/job.go`:
- Around line 141-143: In setUpLogWorkspace, the wsClient.Get success branch
dereferences resp.Properties.CustomerID without nil checks; update the Get
branch (response from wsClient.Get) to first verify resp.Properties != nil and
resp.Properties.CustomerID != nil before dereferencing, and only then assign
customerID and log; mirror the defensive checks used in the CreateOrUpdate
branch so you avoid a potential nil pointer dereference when calling
resp.Properties.CustomerID.

---

Nitpick comments:
In `@src/pkg/cli/client/byoc/state/parse.go`:
- Line 51: Replace the unstructured term.Debugf call with a structured slog
call: use slog.DebugContext(ctx, ...) instead of term.Debugf and pass keyed
attributes for the object name and size (e.g. slog.String("object", obj.Name())
and slog.Int64("size_bytes", obj.Size())). Update imports to include "log/slog"
and ensure a context variable (ctx) is in scope where the original term.Debugf
is called; locate the call to term.Debugf in parse.go and replace it with
slog.DebugContext using obj.Name() and obj.Size() as the attribute values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 547e6e10-2ef7-4626-a469-9ab34de2e4ba

📥 Commits

Reviewing files that changed from the base of the PR and between ee534a9 and 1510e77.

📒 Files selected for processing (7)
  • src/pkg/cli/client/byoc/aws/byoc.go
  • src/pkg/cli/client/byoc/aws/list.go
  • src/pkg/cli/client/byoc/azure/byoc.go
  • src/pkg/cli/client/byoc/state/parse.go
  • src/pkg/clouds/azure/aca/job.go
  • src/pkg/clouds/azure/cd/blob.go
  • src/pkg/clouds/azure/cd/driver.go
✅ Files skipped from review due to trivial changes (3)
  • src/pkg/cli/client/byoc/aws/byoc.go
  • src/pkg/clouds/azure/cd/blob.go
  • src/pkg/cli/client/byoc/aws/list.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/pkg/clouds/azure/cd/driver.go
  • src/pkg/cli/client/byoc/azure/byoc.go

Comment thread src/pkg/clouds/azure/aca/job.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/protos/io/defang/v1/fabric.proto (1)

586-592: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add deprecated alias to maintain backward compatibility for external clients.

The enum constant was renamed from CD_TYPE_AZURE_ACI_JOBID to CD_TYPE_AZURE_ACA_JOBID in commit 642dda8. While the numeric value (4) preserves wire compatibility, removing the old constant name breaks external clients that depend on the original constant. Existing external code referencing CdType_CD_TYPE_AZURE_ACI_JOBID will fail to compile.

Add a deprecated alias in a follow-up change to allow graceful migration:

Suggested backward-compatible fix
 enum CdType {
+  option allow_alias = true;
   CD_TYPE_UNSPECIFIED = 0;
   CD_TYPE_AWS_CODEBUILD_BUILDID = 1;
   CD_TYPE_GCP_CLOUDBUILD_BUILDID = 2;
   CD_TYPE_DO_APPPLATFORM_DEPLOYMENTID = 3;
+  CD_TYPE_AZURE_ACI_JOBID = 4 [deprecated = true];
   CD_TYPE_AZURE_ACA_JOBID = 4;
 }

Then regenerate protos: cd src && make protos

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/protos/io/defang/v1/fabric.proto` around lines 586 - 592, Add a
deprecated alias for the renamed enum value so external clients referencing the
old name still compile: in the enum CdType add the old constant name
CD_TYPE_AZURE_ACI_JOBID with the same numeric value as CD_TYPE_AZURE_ACA_JOBID
(4) and mark it deprecated (e.g., CD_TYPE_AZURE_ACI_JOBID = 4 [deprecated =
true]); then regenerate protos (cd src && make protos).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/protos/io/defang/v1/fabric.proto`:
- Line 591: fabric.proto was modified (added CD_TYPE_AZURE_ACA_JOBID = 4), but
the checked-in generated protobuf artifacts were not updated; regenerate the
derived files by running the project codegen (cd src && make protos) to produce
updated outputs for all src/protos/**/*.proto, verify that generated files
reflect the new CD_TYPE_AZURE_ACA_JOBID constant, add those regenerated
artifacts to this PR, and run the build/tests to ensure consumers compile
against the new schema.

---

Outside diff comments:
In `@src/protos/io/defang/v1/fabric.proto`:
- Around line 586-592: Add a deprecated alias for the renamed enum value so
external clients referencing the old name still compile: in the enum CdType add
the old constant name CD_TYPE_AZURE_ACI_JOBID with the same numeric value as
CD_TYPE_AZURE_ACA_JOBID (4) and mark it deprecated (e.g.,
CD_TYPE_AZURE_ACI_JOBID = 4 [deprecated = true]); then regenerate protos (cd src
&& make protos).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 238a3f1b-0837-4b7a-91ef-7e28403ae66f

📥 Commits

Reviewing files that changed from the base of the PR and between 1510e77 and 642dda8.

⛔ Files ignored due to path filters (1)
  • src/protos/io/defang/v1/fabric.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (3)
  • src/go.mod
  • src/pkg/cli/client/byoc/azure/byoc.go
  • src/protos/io/defang/v1/fabric.proto

Comment thread src/protos/io/defang/v1/fabric.proto
@lionello lionello merged commit 3968770 into main May 5, 2026
4 of 5 checks passed
@lionello lionello deleted the lio/azure-changes branch May 5, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants