Skip to content

Commit 6fc3198

Browse files
feat: expose ingress URL in azd show JSON output as both ingresUrl and ingressUrl
Agent-Logs-Url: https://github.com/Azure/azure-dev/sessions/0eeabf99-cf67-45cd-a1b8-6dfa71188389 Co-authored-by: bwateratmsft <36966225+bwateratmsft@users.noreply.github.com>
1 parent d0036db commit 6fc3198

4 files changed

Lines changed: 28 additions & 4 deletions

File tree

cli/azd/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Features Added
66

7+
- `azd show -o json` now includes the deployed ingress URL for each service. The value is emitted under both `ingresUrl` (preserved for back-compat with existing consumers) and `ingressUrl` (correctly spelled, preferred going forward). Both keys are omitted when no ingress URL is available (e.g. for Container App Jobs).
78
- [[#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.
89
- [[#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.
910
- [[#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.

cli/azd/internal/cmd/show/show.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ func (s *showAction) Run(ctx context.Context) (*actions.ActionResult, error) {
229229
}
230230
}
231231
resSvc.IngresUrl = cachedSvc.IngressUrl
232+
resSvc.IngressUrl = cachedSvc.IngressUrl
232233
res.Services[svcName] = resSvc
233234
}
234235
}
@@ -264,6 +265,7 @@ func (s *showAction) Run(ctx context.Context) (*actions.ActionResult, error) {
264265
ResourceIds: resourceIds,
265266
}
266267
resSvc.IngresUrl = ingressUrl
268+
resSvc.IngressUrl = ingressUrl
267269
res.Services[svcName] = resSvc
268270

269271
// Add to cache

cli/azd/pkg/contracts/contracts_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ func TestShowResult_JSON(t *testing.T) {
268268
ResourceIds: []string{"/subscriptions/sub1/resourceGroups/rg1"},
269269
},
270270
IngresUrl: "https://api.example.com",
271+
IngressUrl: "https://api.example.com",
271272
},
272273
},
273274
}
@@ -281,10 +282,11 @@ func TestShowResult_JSON(t *testing.T) {
281282

282283
assert.Equal(t, "my-app", parsed["name"])
283284

284-
// IngresUrl should be excluded (json:"-")
285+
// ingresUrl and ingressUrl should both be present and equal the input value
285286
services := parsed["services"].(map[string]any)
286287
api := services["api"].(map[string]any)
287-
assert.NotContains(t, api, "ingresUrl")
288+
assert.Equal(t, "https://api.example.com", api["ingresUrl"])
289+
assert.Equal(t, "https://api.example.com", api["ingressUrl"])
288290
assert.NotContains(t, api, "IngresUrl")
289291

290292
// Project fields should be present
@@ -298,6 +300,19 @@ func TestShowResult_JSON(t *testing.T) {
298300
assert.Len(t, resourceIds, 1)
299301
}
300302

303+
func TestShowResult_JSON_ingress_omitted_when_empty(t *testing.T) {
304+
svc := ShowService{
305+
Project: ShowServiceProject{Path: "./src/web", Type: ShowTypeNode},
306+
}
307+
data, err := json.Marshal(svc)
308+
require.NoError(t, err)
309+
310+
var parsed map[string]any
311+
require.NoError(t, json.Unmarshal(data, &parsed))
312+
assert.NotContains(t, parsed, "ingresUrl")
313+
assert.NotContains(t, parsed, "ingressUrl")
314+
}
315+
301316
func TestShowService_JSON_nil_target(t *testing.T) {
302317
result := ShowService{
303318
Project: ShowServiceProject{

cli/azd/pkg/contracts/show.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,14 @@ type ShowService struct {
2626
Project ShowServiceProject `json:"project"`
2727
// Target contains information about the resource that the service is deployed
2828
// to.
29-
Target *ShowTargetArm `json:"target,omitempty"`
30-
IngresUrl string `json:"-"`
29+
Target *ShowTargetArm `json:"target,omitempty"`
30+
// IngresUrl is the deployed service's ingress URL. Retained (with the
31+
// historical misspelling) for backward compatibility with existing
32+
// consumers of `azd show -o json`. Prefer IngressUrl in new code.
33+
IngresUrl string `json:"ingresUrl,omitempty"`
34+
// IngressUrl is the deployed service's ingress URL. Mirrors IngresUrl
35+
// and is the correctly spelled, preferred key.
36+
IngressUrl string `json:"ingressUrl,omitempty"`
3137
}
3238

3339
// ShowServiceProject is the contract for a service's project as returned by `azd show`

0 commit comments

Comments
 (0)