Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements Phase 1 of spec 004 by extending the CLI static application graph to surface dependency edges derived from compiled Bicep dependsOn (in addition to properties.connections), while also adding a required kind discriminator to the Radius.Core/2025-08-01-preview wire model so consumers can distinguish Connection vs Dependency edges. It also fixes a regression by excluding Radius.Core/applications and Radius.Core/environments from static-graph nodes/edge targets, and introduces a shared edge-extraction primitive intended for reuse in a Phase 2 runtime follow-up.
Changes:
- Add
ConnectionKindand requiredApplicationGraphConnection.kindtoRadius.Core/2025-08-01-preview(TypeSpec + regenerated OpenAPI/Go/Bicep types). - Implement shared
pkg/graph/edgesextractor (Connection + dependsOn + Connection-wins de-dupe + mirroring + deterministic sort) and wire it intopkg/cli/graph/modeled.go. - Update static-graph behavior/tests to exclude
Radius.Corecontrol-plane scope resources and to emitDependencyedges whendependsOnis the only source; update architecture docs to describe edge sources andkind.
Reviewed changes
Copilot reviewed 18 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| typespec/Radius.Core/applications.tsp | Adds ConnectionKind enum and required kind field on ApplicationGraphConnection. |
| swagger/specification/radius/resource-manager/Radius.Core/preview/2025-08-01-preview/openapi.json | Regenerated OpenAPI: kind added + ConnectionKind schema introduced. |
| pkg/corerp/api/v20250801preview/zz_generated_models.go | Regenerated preview models: ApplicationGraphConnection.Kind added. |
| pkg/corerp/api/v20250801preview/zz_generated_models_serde.go | Regenerated serde: marshal/unmarshal includes kind. |
| pkg/corerp/api/v20250801preview/zz_generated_constants.go | Regenerated constants: ConnectionKind{Connection,Dependency} added. |
| pkg/corerp/frontend/controller/applications/v20250801preview/graphicons.go | Runtime preview conversion sets Kind: Connection on emitted edges. |
| pkg/graph/edges/edges.go | New shared edge extraction primitive (connections + dependsOn + de-dupe + mirroring + deterministic sort). |
| pkg/graph/edges/edges_test.go | Unit tests for extractor behavior and determinism. |
| pkg/graph/edges/doc.go | New package file for edges (currently missing package godoc comment). |
| pkg/cli/graph/modeled.go | Static graph: adds exclusion list, feeds extractor inputs (connections + dependsOn), applies extracted edges with kind. |
| pkg/cli/graph/modeled_test.go | Adds/extends static-graph tests for exclusion and Connection-wins vs Dependency behavior. |
| docs/architecture/application-graph.md | Documents edge sources and kind, updates the data model diagram and wire-format callout. |
| hack/bicep-types-radius/generated/radius/radius.core/2025-08-01-preview/types.json | Regenerated Bicep type definitions to include kind. |
| hack/bicep-types-radius/generated/index.json | Regenerated Bicep index refs updated due to schema shifts. |
| specs/004-graph-dependency-edges/spec.md | New spec document for Phase 1/2 design and requirements. |
| specs/004-graph-dependency-edges/plan.md | Implementation plan for Phase 1. |
| specs/004-graph-dependency-edges/tasks.md | Task breakdown and dependency graph for the work. |
| specs/004-graph-dependency-edges/research.md | Research notes grounding design decisions in existing code. |
| specs/004-graph-dependency-edges/data-model.md | Defines the shared Go extractor model and wire model change. |
| specs/004-graph-dependency-edges/quickstart.md | End-to-end verification steps for the rabbitmq fixture. |
| specs/004-graph-dependency-edges/contracts/wire-change.md | Explicit contract for the TypeSpec wire change. |
| specs/004-graph-dependency-edges/checklists/requirements.md | Spec quality checklist for the feature. |
| .specify/feature.json | Updates active spec-kit feature directory pointer to spec 004. |
Files not reviewed (3)
- pkg/corerp/api/v20250801preview/zz_generated_constants.go: Generated file
- pkg/corerp/api/v20250801preview/zz_generated_models.go: Generated file
- pkg/corerp/api/v20250801preview/zz_generated_models_serde.go: Generated file
|
|
||
| package edges |
| if strings.EqualFold(resourceType, applicationsResourceType) || | ||
| strings.EqualFold(resourceType, environmentsResourceType) || | ||
| strings.EqualFold(resourceType, radiusCoreApplicationsType) || | ||
| strings.EqualFold(resourceType, radiusCoreEnvironmentsType) || | ||
| strings.EqualFold(resourceType, recipePacksResourceType) { |
| Both producers share the same extraction primitive | ||
| ([`pkg/graph/edges/`](../../pkg/graph/edges/)): exclusion of | ||
| control-plane types (`Radius.Core/applications`, `Radius.Core/environments`, | ||
| `Radius.Core/recipePacks`, plus the legacy `Applications.Core/applications` | ||
| and `Applications.Core/environments`), Connection-wins de-duplication, and | ||
| reciprocal `Outbound`/`Inbound` mirroring. Excluded types are neither | ||
| graph nodes nor edge targets. Phase 2 will bring `Kind: Dependency` to | ||
| the server by adding an optional `dependsOnEdges` field to | ||
| `GetGraphRequest` — callers who ran `bicep build` locally send the | ||
| compiled dependency list, and the server merges it into the graph | ||
| through the same primitive. |
…004, Phase 1) Phase 1 of spec 004 (specs/004-graph-dependency-edges/) — two behavior changes to the CLI static graph 'rad app graph app.bicep': 1. Edges from dependsOn — the static graph now surfaces implicit dependency edges from Bicep's compiled dependsOn list alongside the existing properties.connections edges. Same-pair overlap de-dupes with Connection wins (SC-001). Templates that reference another resource only via secretKeyRef now produce a Kind: Dependency edge (SC-002). 2. Radius.Core control-plane types (applications, environments, recipePacks) remain excluded from graph nodes and edge targets — upstream already lands this exclusion under the isExcludedResourceType helper; this branch relies on it rather than duplicating. Wire change on Radius.Core/2025-08-01-preview only: ApplicationGraphConnection gains a required kind: ConnectionKind field (Connection or Dependency). Applications.Core is untouched (FR-016) — its TypeSpec, generated code, handlers, and tests remain byte-identical. Implementation: - typespec/Radius.Core/applications.tsp: add ConnectionKind enum and required kind field. - Regenerated Go models, swagger, and Bicep type extensions via 'make generate'. - New pkg/graph/edges/ package: Resource, Edge types, and ExtractEdges primitive (connection + dependsOn + exclusion + Connection-wins de-dup + reciprocal mirroring + deterministic sort). Zero imports from pkg/cli/, pkg/corerp/, or net/http (verified via 'go list -deps'), keeping Phase 2 runtime reuse a wiring change. - pkg/cli/graph/modeled.go: BuildModeledGraph builds []edges.Resource in its resource loop and calls edges.ExtractEdges(_, excludeResourceTypes). A new applyEdges helper attaches each Edge to the owning resource's Connections slice via Edge.Owner()/Peer(). A new resolveConnectionSources helper pre-resolves properties.connections[*].source into canonical IDs. The former inline outboundConnections and addInboundConnections helpers are removed. All existing security work (secureString/secureObject parameter tracing, sensitiveKeyBlocklist, resolveGraphProperties, dropOnGraph) and icon work (collectStaticGraphIcons, resolveIconHash, includeIcons parameter) is preserved verbatim. - pkg/corerp/frontend/controller/applications/v20250801preview/graph_util.go: sets Kind: Connection on every emitted ApplicationGraphConnection (two sites — outbound converter and inbound mirror). Phase 2 will start emitting Kind: Dependency here via caller-supplied dependsOnEdges on GetGraphRequest. - pkg/cli/graph/modeled_test.go: adds SC-001 (ConnectionWinsOverDependencyOnRabbitMQShape) and SC-002 (DependencyEdgeSurfacesWithoutConnectionsBlock). - docs/architecture/application-graph.md: new 'Edge Sources and Kind' subsection; class diagram gains kind + ConnectionKind. - specs/004-graph-dependency-edges/: full Spec Kit folder with spec.md, plan.md, tasks.md, research.md, data-model.md, contracts/, quickstart.md, checklists/. Phase 2 (out of scope for this PR): server-side dependency edges via a new caller-supplied dependsOnEdges field on GetGraphRequest — the client (post 'bicep build') sends the compiled list to the server, which merges it through the same pkg/graph/edges/ primitive. Related follow-up: #12467 (evaluate simple ARM name expressions in the static graph so composed resource names render as literals rather than [format(...)] expressions). Success criteria verified: SC-001 (TestBuildModeledGraph_ConnectionWinsOverDependencyOnRabbitMQShape), SC-002 (TestBuildModeledGraph_DependencyEdgeSurfacesWithoutConnectionsBlock + end-to-end fixture), SC-003 (Applications.Core byte-identical; Radius.Core preview handler tests green), SC-004 ('go list -deps ./pkg/graph/edges/...' has no pkg/cli, pkg/corerp, or net/http imports), SC-005 (excludeResourceTypes in pkg/cli/graph/modeled.go is a single source location). Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Radius functional test overviewClick here to see the test run details
Test Status⌛ Building Radius and pushing container images for functional tests... |
Summary
Phase 1 of spec 004 —
specs/004-graph-dependency-edges/.Two concrete behavior changes to the CLI static graph (
rad app graph app.bicep):dependsOn— the static graph now surfaces implicit dependency edges from Bicep's compileddependsOnlist, in addition to the existingproperties.connectionsedges. Same-pair overlap de-dupes with Connection wins (SC-001). Templates that reference another resource only viasecretKeyRefnow produce aKind: Dependencyedge (SC-002).Radius.Core/applicationsandRadius.Core/environmentsare excluded from graph nodes and edge targets — fixing the observed regression where the application scope appeared as a node.Wire change on
Radius.Core/2025-08-01-previewonly:ApplicationGraphConnectiongains a requiredkind: ConnectionKindfield (ConnectionorDependency).Applications.Coreis untouched.What's included
a166bc9..d435919(specs)d8c5cf3foundation/wireConnectionKind+kindfield; regenerated Go/Swagger/Bicep types; runtime converter setsKind: Connectionon every emitted edgef3a2ecafoundation/pkgpkg/graph/edges/package skeleton70faf98us2pkg/cli/graph/modeled.goto coverRadius.Core/applicationsandRadius.Core/environments3bb4110us1ExtractEdges(connection + dependsOn + Connection-wins de-dup + mirroring + exclusion + deterministic sort); rewiremodeled.go; drop obsolete inline helpers8c392beus4ExtractEdgesnaming Phase 2 runtime plug-in (caller-supplieddependsOnEdgesonGetGraphRequest)ba3843apolishdocs/architecture/application-graph.md— Edge Sources and Kind subsection, class diagram, wire-format calloutTwo additional pre-existing commits (
960d83679,90df98cbf) predate the spec-kit workflow; they only touched the design note that the first spec-kit commit later removes. Net effect: added and removed within the same PR. Happy to squash on request.Non-goals for this PR
Kind: Dependencyedges. The runtime handler sees nodependsOnand emits onlyKind: Connection.dependsOnEdgesfield onGetGraphRequest— clients that just ranbicep buildsend the compiled list to the server, which merges it via the samepkg/graph/edges/primitive. See spec § Follow-up work.Follow-ups filed
format,concat,reference('sym').name) in the static graph so composed resource names like${appsecret.name}-consumerrender asappsecret-consumerin the emitted IDs rather than as the raw ARM expression. Not in scope here.Verification
make generateroundtripped cleanly; all regenerated artifacts committed.go build ./...— clean.go vet ./...— clean.gofmt -lon touched packages — empty.go test ./pkg/graph/edges/... ./pkg/cli/graph/... ./pkg/corerp/frontend/controller/applications/...— all green (11 new primitive tests + 2 new integration tests; no golden updates needed elsewhere).go list -deps ./pkg/graph/edges/...— no imports frompkg/cli/,pkg/corerp/, ornet/http(reuse discipline for Phase 2).my-radius-recipes/deploy/edges/rabbitmq-app.bicep:Radius.Core/applicationscorrectly absent; consumer emits twoKind: Dependencyoutbound edges toappsecretandrabbitmq; mirrored inbounds on both.Success criteria (from spec § Success Criteria)
TestBuildModeledGraph_ConnectionWinsOverDependencyOnRabbitMQShapeTestBuildModeledGraph_ExcludesRadiusCoreApplicationsFromRabbitMQShape+ end-to-end fixturekind: Connection)go list -deps— cleanexcludedTypesinpkg/cli/graph/modeled.goEvery commit is Signed-off-by per DCO.