Skip to content

static-graph dependency edges#12468

Open
nithyatsu wants to merge 2 commits into
mainfrom
edges
Open

static-graph dependency edges#12468
nithyatsu wants to merge 2 commits into
mainfrom
edges

Conversation

@nithyatsu

Copy link
Copy Markdown
Contributor

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):

  1. Edges from dependsOn — the static graph now surfaces implicit dependency edges from Bicep's compiled dependsOn list, in addition to 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/applications and Radius.Core/environments are 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-preview only: ApplicationGraphConnection gains a required kind: ConnectionKind field (Connection or Dependency). Applications.Core is untouched.

What's included

Commit What
a166bc9..d435919 (specs) spec.md, plan.md, tasks.md, research.md, data-model.md, contracts/, quickstart.md, clarifications, ExtractOptions simplification, removed superseded design note
d8c5cf3 foundation/wire TypeSpec ConnectionKind + kind field; regenerated Go/Swagger/Bicep types; runtime converter sets Kind: Connection on every emitted edge
f3a2eca foundation/pkg New pkg/graph/edges/ package skeleton
70faf98 us2 Extend exclusion list in pkg/cli/graph/modeled.go to cover Radius.Core/applications and Radius.Core/environments
3bb4110 us1 Real ExtractEdges (connection + dependsOn + Connection-wins de-dup + mirroring + exclusion + deterministic sort); rewire modeled.go; drop obsolete inline helpers
8c392be us4 Doc comment on ExtractEdges naming Phase 2 runtime plug-in (caller-supplied dependsOnEdges on GetGraphRequest)
ba3843a polish Inline updates to docs/architecture/application-graph.md — Edge Sources and Kind subsection, class diagram, wire-format callout

Two 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

  • Applications.Core is unchanged (FR-016). Applications.Core TypeSpec, generated code, handlers, and tests remain byte-identical.
  • No server-side Kind: Dependency edges. The runtime handler sees no dependsOn and emits only Kind: Connection.
  • No property scanner on the server. Phase 2 will add server-side dependency edges via a new caller-supplied dependsOnEdges field on GetGraphRequest — clients that just ran bicep build send the compiled list to the server, which merges it via the same pkg/graph/edges/ primitive. See spec § Follow-up work.

Follow-ups filed

  • radius#12467 — evaluate simple ARM name expressions (format, concat, reference('sym').name) in the static graph so composed resource names like ${appsecret.name}-consumer render as appsecret-consumer in the emitted IDs rather than as the raw ARM expression. Not in scope here.

Verification

  • make generate roundtripped cleanly; all regenerated artifacts committed.
  • go build ./... — clean.
  • go vet ./... — clean.
  • gofmt -l on 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 from pkg/cli/, pkg/corerp/, or net/http (reuse discipline for Phase 2).
  • End-to-end verified against my-radius-recipes/deploy/edges/rabbitmq-app.bicep: Radius.Core/applications correctly absent; consumer emits two Kind: Dependency outbound edges to appsecret and rabbitmq; mirrored inbounds on both.

Success criteria (from spec § Success Criteria)

SC Verified by
SC-001 (rabbitmq-app: 2 nodes, single Connection edge, Connection wins) TestBuildModeledGraph_ConnectionWinsOverDependencyOnRabbitMQShape
SC-002 (secretKeyRef-only variant: 1 Dependency edge + mirrored inbound) TestBuildModeledGraph_ExcludesRadiusCoreApplicationsFromRabbitMQShape + end-to-end fixture
SC-003 (Applications.Core byte-identical; Radius.Core preview gains kind: Connection) Preview handler tests green, Applications.Core tests untouched
SC-004 (shared primitive in a neutral package, no CLI/control-plane imports) go list -deps — clean
SC-005 (exclusion list is one source location) excludedTypes in pkg/cli/graph/modeled.go

Every commit is Signed-off-by per DCO.

Copilot AI review requested due to automatic review settings July 17, 2026 02:03
@nithyatsu
nithyatsu requested review from a team as code owners July 17, 2026 02:03
@nithyatsu
nithyatsu marked this pull request as draft July 17, 2026 02:04
@nithyatsu nithyatsu changed the title Static-graph dependency edges + Radius.Core preview kind field (spec 004, Phase 1) static-graph dependency edges + Radius.Core preview kind field Jul 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 ConnectionKind and required ApplicationGraphConnection.kind to Radius.Core/2025-08-01-preview (TypeSpec + regenerated OpenAPI/Go/Bicep types).
  • Implement shared pkg/graph/edges extractor (Connection + dependsOn + Connection-wins de-dupe + mirroring + deterministic sort) and wire it into pkg/cli/graph/modeled.go.
  • Update static-graph behavior/tests to exclude Radius.Core control-plane scope resources and to emit Dependency edges when dependsOn is the only source; update architecture docs to describe edge sources and kind.

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

Comment thread pkg/graph/edges/doc.go
Comment on lines +16 to +17

package edges
Comment thread pkg/cli/graph/modeled.go Outdated
Comment on lines 323 to 327
if strings.EqualFold(resourceType, applicationsResourceType) ||
strings.EqualFold(resourceType, environmentsResourceType) ||
strings.EqualFold(resourceType, radiusCoreApplicationsType) ||
strings.EqualFold(resourceType, radiusCoreEnvironmentsType) ||
strings.EqualFold(resourceType, recipePacksResourceType) {
Comment on lines +238 to +248
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.
@nithyatsu nithyatsu changed the title static-graph dependency edges + Radius.Core preview kind field static-graph dependency edges Jul 17, 2026
…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>
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@radius-functional-tests

radius-functional-tests Bot commented Jul 17, 2026

Copy link
Copy Markdown

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository radius-project/radius
Commit ref 8d931f7
Unique ID funcd55fc31e31
Image tag pr-funcd55fc31e31
  • Dapr: 1.14.4
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-funcd55fc31e31
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-funcd55fc31e31
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-funcd55fc31e31
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funcd55fc31e31
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funcd55fc31e31
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ Recipe publishing succeeded
⌛ Starting corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...

@nithyatsu
nithyatsu marked this pull request as ready for review July 17, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants