Skip to content

Commit 5cd8feb

Browse files
feat(show): expose ingress URL in azd show -o json output (#8071)
* Initial plan * 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> * fix: gofmt show.go and add PR number to CHANGELOG entry Agent-Logs-Url: https://github.com/Azure/azure-dev/sessions/9e3f70d3-4ef2-4cc7-946f-cc972c4b2b50 Co-authored-by: bwateratmsft <36966225+bwateratmsft@users.noreply.github.com> * refactor: use custom MarshalJSON to emit both ingress URL keys from single field Agent-Logs-Url: https://github.com/Azure/azure-dev/sessions/b376eea2-f17e-4ec1-9623-4466b44860f0 Co-authored-by: bwateratmsft <36966225+bwateratmsft@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bwateratmsft <36966225+bwateratmsft@users.noreply.github.com>
1 parent 526fe96 commit 5cd8feb

3 files changed

Lines changed: 43 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+
- [[#8071]](https://github.com/Azure/azure-dev/pull/8071) `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/pkg/contracts/contracts_test.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,11 @@ func TestShowResult_JSON(t *testing.T) {
281281

282282
assert.Equal(t, "my-app", parsed["name"])
283283

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

290291
// Project fields should be present
@@ -298,6 +299,19 @@ func TestShowResult_JSON(t *testing.T) {
298299
assert.Len(t, resourceIds, 1)
299300
}
300301

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

cli/azd/pkg/contracts/show.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Licensed under the MIT License.
33
package contracts
44

5+
import "encoding/json"
6+
57
// ShowType are the values for the language property of a ShowServiceProject
68
type ShowType string
79

@@ -26,8 +28,30 @@ type ShowService struct {
2628
Project ShowServiceProject `json:"project"`
2729
// Target contains information about the resource that the service is deployed
2830
// to.
29-
Target *ShowTargetArm `json:"target,omitempty"`
30-
IngresUrl string `json:"-"`
31+
Target *ShowTargetArm `json:"target,omitempty"`
32+
// IngresUrl is the deployed service's ingress URL. When marshaled to JSON,
33+
// it is emitted under both "ingresUrl" (back-compat) and "ingressUrl"
34+
// (correctly spelled, preferred). Only this field needs to be set.
35+
IngresUrl string `json:"-"`
36+
}
37+
38+
// MarshalJSON implements json.Marshaler for ShowService.
39+
// It emits the ingress URL under both "ingresUrl" and "ingressUrl" keys
40+
// so that existing consumers using the historical misspelling continue to work
41+
// while new consumers can use the correct spelling.
42+
func (s ShowService) MarshalJSON() ([]byte, error) {
43+
type alias struct {
44+
Project ShowServiceProject `json:"project"`
45+
Target *ShowTargetArm `json:"target,omitempty"`
46+
IngresUrl string `json:"ingresUrl,omitempty"`
47+
IngressUrl string `json:"ingressUrl,omitempty"`
48+
}
49+
return json.Marshal(alias{
50+
Project: s.Project,
51+
Target: s.Target,
52+
IngresUrl: s.IngresUrl,
53+
IngressUrl: s.IngresUrl,
54+
})
3155
}
3256

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

0 commit comments

Comments
 (0)