Skip to content

[docs] Reference Bicep helpers and their Azure SDK mappings - #1756

Merged
David Pine (IEvangelist) merged 3 commits into
release/13.6from
sebros/bicep-helper-reference
Sep 28, 2026
Merged

David Pine (IEvangelist) merged 3 commits into
release/13.6from
sebros/bicep-helper-reference

Conversation

@sebastienros

Copy link
Copy Markdown
Contributor

Documents changes from microsoft/aspire#19675: microsoft/aspire#19675, authored by Sébastien Ros (@sebastienros).

Scope and documentation gap

This is the explicitly requested separate follow-up, not a replacement for #1747 (integration authoring/diagnostics) or #1748 (service coverage). Neither existing PR nor its branch is modified. The release rollup #1599 is not the source PR and is untouched.

Adds a focused, user-oriented reference for infrastructure.bicep():

  • All 32 factory exports, including the resourceIdentifier export alias, with arguments, return/value semantics, underlying C# SDK counterpart or AST node, and emitted Bicep.
  • All 3 string-builder methods, 3 infrastructure declaration helpers, 16 binary / 3 unary operators, value/security metadata, and explicit array/object/null constructor and declaration-type boundaries.
  • Complete TypeScript and C# Storage examples: deterministic valid-length naming, resource-group location, parameter/deployment tags, concatenation, and resource-ID output.
  • Complete TypeScript and C# Key Vault examples: JSON object/array data, variable/member/index access, deployment-time equality/conditional, retention settings, purge-protection caveats, and integer output. Existing authorization stays intact.
  • Clear separation of remote handles, host-language evaluation, deployment-time functions, GUID/URI literals versus functions, SDK typing versus conversions, and secure metadata versus protection of output destinations.

Files

  • Added src/frontend/src/content/docs/integrations/cloud/azure/bicep-helpers.mdx.
  • Added one cross-link in src/frontend/src/content/docs/integrations/cloud/azure/customize-resources.mdx; existing guidance and examples are preserved.
  • Added discovery entries in src/frontend/config/sidebar/integrations.topics.ts and deployment.topics.ts.

Exact target rationale and provenance

Prepared target resolution: candidate_source=pr_milestone, candidate_source_detail=13.6, candidate_target_branch=release/13.6, target_resolution=exact_match. The matching docs release branch exists; this is not a latest-release or main fallback.

  • Docs base: release/13.6 at e20e81f100b699c4dd6adbf01a52f6fd7bad11bd.
  • Head: sebros/bicep-helper-reference, on the origin microsoft/aspire.dev, not a fork.
  • Product release source: 43496a2a306c81c862c947b11b4f4e5494b6fe08. Factory, value wrapper, declaration and string-builder implementations checked against this release, not 14.x main.
  • Actual generated SDK and installed CLI: 13.6.0-preview.1.26473.12, source a11eca9611073f7cf66fa87faac63c2119e87713, matching this docs branch's generated API data.
  • Exact Aspire packages restored from the official public dotnet9 feed after the original staging darc feed returned HTTP 404. Only isolated scratch configuration changed.

Official Azure SDK verification

Verified Microsoft Learn and the corresponding official SDK implementation, rather than inferring mappings from Aspire XML summaries:

Validation

  • Extracted both exact TypeScript snippets and compiled them using tsc -p tsconfig.apphost.json against genuine generated release SDK code, with no SDK patches, casts, diagnostics suppression or production changes.
  • Both TypeScript AppHosts successfully ran local aspire publish with a nonsecret Parameters__environment=Production input and generated Storage / Key Vault Bicep. Expected warning: no compute environment in these resource-only examples.
  • Compiled both exact C# counterparts with the matching Aspire packages and generated local manifests. Storage and Key Vault Bicep files are each byte-for-byte identical between the C# and TypeScript versions.
  • Independently ran Azure.Provisioning 1.6.0 offline generation to confirm literals, interpolation and all operator spellings.
  • The full existing pnpm test:unit:twoslash-blocks gate passed (2 tests). New proxy examples intentionally use ordinary TypeScript fences, as their operator/runtime surface is checked against genuine SDK modules rather than the site's simplified declaration bundle.
  • Frontmatter SEO checks passed (3 tests); touched sidebar files passed ESLint; Prettier and git diff --check passed.
  • Local Astro route returned 200; Playwright inspected desktop/mobile tables, synchronized TypeScript/C# tabs, headings and cross-link navigation. No page-wide mobile overflow. Unrelated dev-only /api/live/ and /api/live/stream/ requests return 404 without the static host.
  • All 19 external links in the new page returned HTTP 200.
  • No production site build, Azure deployment, cloud access mutation, secret creation, billing operation, workflow dispatch, or dependency-manifest/lockfile change in this PR.

SME attention: tested preview string-builder limitation

The exact generated 13.6.0-preview.1.26473.12 TypeScript SDK implements BicepStringBuilderProxyImpl.build() with await this._client.flushPendingPromises() (.aspire/modules/aspire.mts:18905-18906). Inside configureInfrastructure, this waits for the enclosing pending callback. The fully awaited original Storage sample consistently timed out after 120 seconds, with Flushing 2 pending promise(s) in the trace.

The runnable sample now uses concat and publishes successfully. The page preserves the underlying string-builder reference and narrowly labels this exact preview limitation; it does not attribute the problem to C# BicepStringBuilder or Bicep itself. Please reassess/remove this caveat when the generated SDK is fixed. No product fix, SDK modification, or new product issue is included.

Minimal reproduction (inside a configured callback, after obtaining bicep):

const label = await bicep.createStringBuilder();
await label.appendLiteral('storage-');
await label.appendValue(await bicep.string('example'));
await label.build();

Original source signal accounting

Prepared inputs require documentation and are not excluded. This user-requested helper follow-up narrows the original broad PR's remaining gap; #1747 remains the relevant authoring/diagnostics draft.

Triggered category Concrete source evidence and treatment
cli_command_file_changed src/Aspire.Cli/Commands/Sdk/SdkDumpCommand.cs: experimental capability metadata. Existing authoring draft #1747; this page documents experimental helper boundaries, not CLI behavior again.
diagnostic_documentation_changed docs/list-of-diagnostics.md: provisioning/projection diagnostics. Existing #1747; new page retains ASPIREAZUREPROVISIONING001 caveat.
diff_scan_skipped_due_to_missing_patch AspireProvisioningProxyGenerator.cs exceeded cached patch coverage. This follow-up directly reads release source and validates actual generated package SDK instead of treating missing patch as a skip.
integration_readme_changed Shared Aspire.Hosting.Azure.Provisioning/README.md and per-service READMEs. New page adds the missing complete helper-to-SDK/Bicep mapping without duplicating general authoring prose.
new_hosting_integration_project Shared runtime and original provisioning service .csproj additions. New examples explicitly name Storage/KeyVault opt-in packages; service inventory stays separate.
new_package_added Runtime, generator and original 12 provisioning service packages. Actual matching runtime/Storage/KeyVault packages used to generate and execute snippets.
new_public_type BicepValueProxy, ProvisionableResourceProxy, export provider attribute. Reference explains value/resource handle distinctions and factory/declaration semantics; export provider authoring stays in #1747.
polyglot_code_generator_changed TypeScript/Python/Java code generators and TypeScript projector. Genuine generated TypeScript SDK validated; the observed build-method limitation is explicitly surfaced.
pr_body_has_user_facing_section Source PR's “User-facing usage” section contains customization examples. This adds complete user-oriented Storage and Key Vault scenarios, not more internal authoring guidance.
target_framework_changed New provisioning project target-framework declarations. No evidence of a changed AppHost prerequisite; this PR doesn't change prerequisites or dependency manifests.

Human review is required before merging, especially the exact-preview string-builder caveat and exhaustive mapping tables. SME requested: Eric Erhardt (@eerhardt).

Document all 32 factory exports, companion declarations, and validated Storage and Key Vault examples.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove cross-language proxy implementation details while preserving helper mappings and examples.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

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.

Copilot review overview

🟡 Changes recommended

Correct the invalid options-object signatures for parameter, referenceExpression, and addBicepParameter.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds Aspire 13.6 documentation for Azure Bicep helpers, SDK mappings, and Storage/Key Vault examples.

Changes:

  • Adds a comprehensive Bicep helper reference.
  • Adds Storage and Key Vault TypeScript/C# examples.
  • Adds a customization cross-link and sidebar entries.
File Reviewed changes
src/​frontend/​src/​content/​docs/​integrations/​cloud/​azure/​bicep-helpers.mdx New helper reference and examples; several documented signatures require correction.
src/​frontend/​src/​content/​docs/​integrations/​cloud/​azure/​customize-resources.mdx Added cross-link to the reference.
src/​frontend/​config/​sidebar/​integrations.topics.ts Added integration navigation entry.
src/​frontend/​config/​sidebar/​deployment.topics.ts Added deployment navigation entry.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

Frontend HTML artifact ready

The latest frontend build uploaded the frontend-dist artifact for PR #1756. Use the VS Code button below to open this PR with GitHub Artifacts Explorer and browse the built HTML locally.

VS Code: Open PR #1756 artifacts

This comment updates automatically when a new frontend build artifact is uploaded.

@IEvangelist David Pine (IEvangelist) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Automated docs-accuracy review — PR #1756

Two-phase check: Phase A verifies every factual claim against the product source of truth; Phase B validates the rendered docs as a first-time user (blind to source) via a locally-served site + Playwright.

Summary

Phase A — source of truth

  • microsoft/aspire @ release/13.6 = 43496a2a306c81c862c947b11b4f4e5494b6fe08 (matches the SHA this PR pins)
  • Azure/azure-sdk-for-net @ 4d32854480515e716c762be7925660bce6da251a (Azure.Provisioning 1.6.0, the SHA this PR pins)

Claims: 23 non-narrative claim groups extracted — ✅ 20 verified · 🟡 2 verified-with-nuance · ❔ 1 unverifiable · ❌ 0 contradicted.

Phase B — doc-tester: exercised 2 routes (/integrations/cloud/azure/bicep-helpers/ new, /integrations/cloud/azure/customize-resources/ edited) → 0 critical, 0 PR-attributable warnings. Language tabs sync (syncKey="aspire-lang"), all internal links + in-page anchors resolve, cross-link round-trips, no mobile overflow.

Verdict: COMMENT. No contradictions in Phase A and no critical rendering issues in Phase B. One unverifiable runtime caveat (inline) and two SDK-emission nuances are noted for author awareness only — nothing blocking.


Phase A — Claim verification

One inline comment is posted for the single unverifiable claim. Everything else verified against the two pinned SHAs; full evidence below.

✅ Verified & 🟡 verified-with-nuance claims (23 groups) — evidence

Core Aspire — microsoft/aspire@43496a2

  • ✅ 32 factory methods — exactly 32 method-level [AspireExport] on BicepValueFactoryProxy (BicepValueFactory.cs).
  • ✅ Literal helpers string/integer/boolean/double/guid/uri/location/timeSpan → BicepValue<string|int|bool|double|Guid|Uri|AzureLocation|TimeSpan> (BicepValueFactory.cs:44-133); location requires non-empty.
  • ✅ parameter/referenceExpression → AsProvisioningParameter (creates/reuses ProvisioningParameter; referenceExpression carries isSecure) (BicepValueFactory.cs:135-172).
  • ✅ identifier → IdentifierExpression, isSecure:false (BicepValueFactory.cs:180-188).
  • ✅ resourceIdentifier → [AspireExport("resourceIdentifier")] alias of Identifier(ProvisionableResourceProxy) → Identifier(resource.BicepIdentifier) (BicepValueFactory.cs:196-210).
  • ✅ Named Bicep functions → C# counterparts: concat→Concat, createGuid→CreateGuid, uniqueString→GetUniqueString, subscriptionResourceId→GetSubscriptionResourceId, take→Take, toLower→ToLower, toUpper→ToUpper, asString→AsString, parseJson→ParseJson, resourceGroup→GetResourceGroup, subscription→GetSubscription, tenant→GetTenant, deployment→GetDeployment — all present (BicepValueFactory.cs).
  • ✅ take/index parameter unions (value string|BicepValue; count int|BicepValue; index string|int|BicepValue) — AspireUnion attrs.
  • ✅ General expressions → AST nodes: function→FunctionCallExpression+IdentifierExpression, member→MemberExpression, index→IndexExpression, binary→BinaryExpression, unary→UnaryExpression, conditional→ConditionalExpression.
  • ✅ String builder appendLiteral/appendValue/build → BicepStringBuilder.Append(string)/Append(BicepExpression)/Build() (BicepStringBuilderProxy.cs).
  • ✅ Declaration helpers addBicepParameter(name,type,{isSecure?})/addBicepVariable(name,type)/addBicepOutput(name,type) → ProvisioningParameter/Variable/Output (ProvisioningDeclarationExtensions.cs).
  • ✅ ProvisioningValueType = String/Boolean/Integer/Object/Guid → string/bool/int/object/Guid; no Array/Double/TimeSpan (ProvisioningDeclarationExtensions.cs:15-21,168-179).
  • 🟡 Guid → Bicep string — verified-with-nuance: backed by the code comment "CDK maps GUIDs to strings" rather than an explicit type row.
  • ✅ Secure restrictions: only string/object/GUID securable; boolean/integer rejected (ValidateIsSecure).
  • 🟡 @secure() / string-interpolation emission — verified-with-nuance: these are SDK-emission details (how the value is rendered), correct in substance.
  • ✅ kind.get()/isSecure.get() + secure-flag propagation across composition (BicepValueProxy.cs).
  • ✅ addBicepParameter does not bind an Aspire parameter (unlike bicep.parameter).
  • ✅ getStorageAccount()/getKeyVaultService() TS projections — polyglot TS AppHosts + Provisioning READMEs at SHA.
  • ✅ addAzureStorage/addAzureKeyVault exist (api files).
  • ✅ TS import of ProvisioningValueType/BinaryBicepOperator/createStringBuilder from ./.aspire/modules/aspire.mjs — polyglot TS AppHosts + READMEs.

Azure SDK — Azure/azure-sdk-for-net@4d32854

  • ✅ BinaryBicepOperator 16 members + Bicep symbols (And &&, Or ||, Coalesce ??, Equal ==, EqualIgnoreCase =~, NotEqual !=, NotEqualIgnoreCase !~, Greater >, GreaterOrEqual >=, Less <, LessOrEqual <=, Add +, Subtract -, Multiply *, Divide /, Modulo %) — match exactly.
  • ✅ UnaryBicepOperator Not (!value) / Negate (-value) / SuppressNull (value!) — match exactly.
  • ✅ double whole int-range → integer; otherwise json('1.5') (BicepSyntax.cs:32-41).
  • ✅ timeSpan standalone one-hour → '01:00:00'; property format may require ISO8601/numeric units (BicepTypeMapping.cs).
  • ✅ BicepFunction.Interpolate exists (BicepFunction.cs).

Narrative / external (noted, not blocking, not contradicted): Storage name rules (3–24 lowercase alnum), uniqueString 13-char, Key Vault retention 7–90 days, purge-protection immutable — backed by external Microsoft Learn links / documented Azure behavior.


Phase B — Doc-tester results (blind user; rendered site only)

Served locally via pnpm dev at http://localhost:4321/; browsed with Playwright (headless Edge). Scoped to the two routes touched by this PR.

Critical issues: none.

Warnings: none attributable to the PR.

Environmental only (not a doc defect, not surfaced as a finding): every dev page logs GET /api/live/ 404, GET /api/live/stream/ 404, and [live-status] Live API not found (404). That's the live-status feature needing the static host; the PR body already calls it out.

Passed checks:

  • Page title renders: "Compose Azure infrastructure with Bicep helpers | Aspire".
  • Heading outline complete and logically ordered (H1 + 7 H2s + 7 H3s).
  • Language tabs render as synced TypeScript/C# groups (TypeScript selected first). Clicking C# on the first group switched both groups to C# — confirms syncKey="aspire-lang". [TS:true,C#:false]×2 → [TS:false,C#:true]×2.
  • 8 tables render; 8 code blocks render, none empty.
  • Internal links: the only site-relative content target is /integrations/cloud/azure/customize-resources/ (trailing slash, resolves 200), present twice.
  • In-page anchors: 18 hash links, all resolve (0 missing).
  • Cross-link round-trip: on /customize-resources/, the new "Compose Azure infrastructure with Bicep helpers" link → /integrations/cloud/azure/bicep-helpers/ navigates and lands on the correct H1.
  • Mobile (375×800): no page-level horizontal overflow (scrollWidth == clientWidth == 375).
  • No broken images (lazy-load placeholders only).

Recommendations: none blocking — the page is well-structured and reads cleanly for a first-time visitor.

Knowledge gaps (blind-user perspective): the external Microsoft Learn API links were not fetched in Phase B (external targets are out of scope for internal link validation; the PR body states all 19 returned 200). Their correctness is covered by Phase A, not Phase B.


Automated docs-accuracy reviewer · Phase A reads product source at the pinned SHAs; Phase B is deliberately blind to source and only exercises the rendered site.

Comment thread src/frontend/src/content/docs/integrations/cloud/azure/bicep-helpers.mdx Outdated
Comment thread src/frontend/src/content/docs/integrations/cloud/azure/bicep-helpers.mdx Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist
David Pine (IEvangelist) merged commit 717442f into release/13.6 Sep 28, 2026
11 checks passed
@IEvangelist
David Pine (IEvangelist) deleted the sebros/bicep-helper-reference branch September 28, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-from-code Copilot initiated issue from dotnet/aspire repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants