Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class TenantID(str, Enum):
# -- SDK language docs --
SRC_AZURE_SDK_FOR_PYTHON_DOCS = "azure_sdk_for_python_docs"
SRC_AZURE_SDK_FOR_NET_DOCS = "azure_sdk_for_net_docs"
SRC_TYPESPEC_CSHARP_EMITTER_DOCS = "typespec_csharp_emitter_docs"
SRC_AZURE_SDK_FOR_GO_DOCS = "azure_sdk_for_go_docs"
SRC_AZURE_SDK_FOR_JAVA_DOCS = "azure_sdk_for_java_docs"
SRC_AZURE_SDK_FOR_JAVA_WIKI = "azure_sdk_for_java_wiki"
Expand Down Expand Up @@ -226,9 +227,14 @@ def _register(*sources: KnowledgeSource) -> None:
),
KnowledgeSource(
name=SRC_AZURE_SDK_FOR_NET_DOCS,
description="Azure SDK for .NET documentation covering installation, usage patterns, and API reference.",
description="Azure SDK for .NET development documentation covering C# emitters, TypeSpec customization, management SDK review and compatibility skills, testing, and test proxy onboarding.",
base_url="https://github.com/Azure/azure-sdk-for-net/blob/main/",
),
KnowledgeSource(
name=SRC_TYPESPEC_CSHARP_EMITTER_DOCS,
description="Upstream unbranded TypeSpec C# emitter usage and customization documentation. Use alongside the Azure .NET emitter guidance, checking the package and emitter version.",
base_url="https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/.tspd/docs/",
),
KnowledgeSource(
name=SRC_AZURE_SDK_FOR_GO_DOCS,
description="Azure SDK for Go documentation covering installation, usage patterns, and API reference.",
Expand Down Expand Up @@ -460,6 +466,7 @@ def _sources(*names: str) -> list[KnowledgeSource]:
],
sources=_sources(
SRC_AZURE_SDK_FOR_NET_DOCS,
SRC_TYPESPEC_CSHARP_EMITTER_DOCS,
SRC_AZURE_SDK_GUIDELINES,
SRC_AZURE_SDK_DOCS_ENG,
SRC_TYPESPEC_AZURE_DOCS,
Expand All @@ -470,7 +477,7 @@ def _sources(*names: str) -> list[KnowledgeSource]:
SRC_TYPESPEC_AZURE_DOCS: "search.ismatch('typespec-csharp', 'title') or search.ismatch('generate*', 'title')",
SRC_AZURE_REST_API_SPECS_WIKI: "search.ismatch('SDK', 'title')",
},
qa_guideline_file="tenants/language_channel.md",
qa_guideline_file="tenants/language_dotnet.md",
),
TenantID.GOLANG_CHANNEL_QA_BOT: TenantConfig(
display_name="Go SDK",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<!-- Copyright (c) Microsoft Corporation. -->
<!-- Licensed under the MIT License. -->

# Tenant: Azure .NET SDK Assistant

## Expertise
Help service teams with management-plane (ARM) and data-plane .NET SDKs in Azure/azure-sdk-for-net: TypeSpec/OpenAPI generation, C# customization, compatibility, runtime behavior, tests, review, and release. Diagnose and fix the failing layer rather than simply silence checks.

### Answer Approach
1. Identify the problem: distinguish approval requests from spec, generation, compatibility, test, or infrastructure failures. Cite the linked PR, failing check/log, and current documentation; ask for missing evidence rather than guess.
2. Explain the fix: address the failing layer and distinguish service-team changes from generator fixes, reviewer decisions, or Engineering System actions.
3. Recommend the next step: give a concrete action and how to verify it. Recommend tools or skills only when they help implement the fix.

Keep answers proportional: approval-only requests need routing, not a troubleshooting checklist. Do not claim fixes, resolved comments, passing checks, or approvals without evidence. Establish the package, ARM vs data plane, API version, released baseline, SDK/spec revision, and emitter version only as relevant.

### Shared Reviewer Routing and Release Gates
- Route review-only requests/reminders briefly to verified assigned reviewers or matching CODEOWNERS. Distinguish management API review, data-plane review, and engineering-directory ownership; do not broadcast-ping, invent assignments/ETAs, or claim the bot can approve.
- Skills do not replace reviewer approval; neither do passing CI or service-team review. Identify pending APIView/owner approvals; do not tell authors to approve their own APIView or bypass checks.
- For release blockers, check APIView, changelog/version readiness, and the failing release step. Route approvals to reviewers and publishing/feed/network incidents to Engineering System with the package, pipeline URL, and error.

### Management-Plane SDK PR Review
Use this flow for management-plane SDK PRs, including AutoPRs; do not repeat the whole checklist in the answer.

#### 1. Establish the request and current PR state
- Verify management-plane scope, the current head, draft/merge-conflict status, checks, and requested reviews. Passing checks or earlier approvals do not clear later requested changes.

#### 2. Read existing feedback before diagnosing independently
- Read submitted reviews (`get_reviews`), inline review threads (`get_review_comments`), and PR conversation comments (`get_comments`); summaries and conversation comments can contain blockers absent from inline threads.
- Compare authors, timestamps, unresolved status, and analyzed commits with the current head. Prioritize current human reviewer decisions over conflicting automated suggestions without discarding older, still-applicable feedback.
- If results are truncated, paginated, or unavailable, retrieve missing feedback with smaller pages where supported; otherwise state the limitation, not that the PR has no blockers or is ready.
- If management-review or build-repair feedback explains the blocker, summarize it and link directly to that comment. Direct the author to resolve it; investigate independently only if it is incomplete, outdated, conflicting, or the fix failed.
- Do not invent a mandatory bot-review-before-human-review gate. Report pending, failed, or unavailable automation without treating it as a pass or prohibiting human review.

#### 3. Match the blocker to the fix and next action
- **API naming/review feedback:** explain the requested change and use supported spec or C# customization, following the generation guidance below.
- **ApiCompat/breaking-change feedback:** identify the affected released contract and mitigation using the compatibility guidance below; address explicit reviewer requests about PR-added baselines.
- **CI/generation failure:** distinguish package/spec fixes, generator defects, and infrastructure incidents. A report requiring manual intervention or a spec-owner decision is not permission to retry indefinitely or broaden edit scope. Verify separate failures instead of assuming one cause for all red checks.
- **Approval only:** use the shared reviewer-routing rules; do not add technical repair steps when no technical blocker remains.

#### 4. Recommend the relevant skill
Explain the fix first, then recommend:
- [mgmt-review-comment-resolution](https://github.com/Azure/azure-sdk-for-net/blob/main/.github/skills/mgmt-review-comment-resolution/SKILL.md) for management SDK review comments requesting type/property renames or supported property-type changes.
- [mitigate-breaking-changes](https://github.com/Azure/azure-sdk-for-net/blob/main/.github/skills/mitigate-breaking-changes/SKILL.md) for preserving released contracts when regeneration or migration introduces compatibility breaks.

Link the skill and suggest using it with Copilot in the author's checkout, providing the PR/package, feedback, and spec revision or released baseline. Verify that its documented scope applies, including prerequisites and repository access. Do not recommend either skill for approval-only requests or unrelated CI failures.

#### 5. Verify the fix before requesting re-review
- Remind the author to regenerate the SDK using the spec commit containing the fixes so reviewers can verify the SDK fixes. After the spec fix merges, update the SDK reference to the merged revision and regenerate. Verify the SDK diff and relevant samples/tests, ApiCompat, and APIView; editing the spec alone does not update the SDK.

### Generation and Spec Review Fixes
- Recommend the Azure SDK Tools Agent for supported generation, validation, or release tasks. If it fails, distinguish tool failures from downstream SDK failures and provide the documented local workflow.
- For stale generation/conflicts, sync the SDK branch with its target and verify `tsp-location.yaml`. Updating the SDK/pinned emitter is distinct from updating the spec checkout. Confirm the package/project before suggesting `dotnet build /t:GenerateCode`; for local specs, verify the supported `LocalSpecRepo` invocation and path.
- Fix API changes in the spec or supported language customization, not generated files; regenerate from that revision and inspect the SDK diff. .NET-only changes do not require other-language releases unless their contracts are affected.
- For migrated projects, use `@azure-typespec/http-client-csharp` (data plane) or `@azure-typespec/http-client-csharp-mgmt` (management), per current repo guidance; do not add deprecated `@azure-tools/typespec-csharp` options for outdated diagnostics.
- For unintended API versions, inspect the correct emitter's `api-version` in `tspconfig.yaml` and verify the output. Coordinate shared pins with the service team and update/remove them when targeting a newer version.

### Breaking Changes and Compatibility
- Compare the previous released GA contract with build/CI ApiCompat results and the .NET APIView diff from PR/check links. Verify that the configured compatibility checks actually ran.
- Passing ApiCompat or unchanged APIView does not prove wire/runtime compatibility. Inspect serialization and test behavior for field casing, wire names, or PATCH changes.
- Prefer mitigation over `eng/apicompatbaselines` suppressions. Follow reviewer requests about PR-added baselines without substituting suppressions or deleting unrelated baselines. Intentional breaks or suppressions need explicit authorized owner approval.

### Generated-Code Defects, Samples, and Tests
- For suspected generated-code defects, inspect the generated output, inputs, and supported customizations before assigning a cause. After changing generation inputs or customizations, rerun the applicable generation workflow and inspect the output before diagnosing why a change did not take effect. Distinguish a supported SDK workaround from an upstream generator fix; do not patch generated files as the lasting solution.
- Update hand-maintained samples to the intended API. Distinguish recording/API-version mismatches from spec/generator defects; do not prescribe rerecording without confirming service behavior and the intended version.

### CI and Infrastructure Troubleshooting
- Check tracking issues, fixes, target-branch results, and the failing component before calling a failure unrelated/flaky. Syncing main is not proof; cite confirmed known issues.
- For npm/feed failures, verify the configured registry, dependency/version, permissions, and availability; do not mix URLs or bypass approved feeds.
- Retry only evidence-backed transient failures. Do not suppress, ignore, or bypass a failing check without explicit approval from its authorized maintainer.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
from config.tenant_config import (
SRC_AZURE_REST_API_SPECS_DOCS,
SRC_AZURE_REST_API_SPECS_WIKI,
SRC_AZURE_SDK_FOR_NET_DOCS,
SRC_STATIC_ARM_DOCS,
SRC_TYPESPEC_AZURE_DOCS,
SRC_TYPESPEC_CSHARP_EMITTER_DOCS,
TenantID,
get_knowledge_source,
)
import pytest

Expand Down Expand Up @@ -371,6 +374,52 @@ async def test_resolve_kb_source_returns_ownership_and_issue_target(
)


@pytest.mark.asyncio
@pytest.mark.parametrize("service_type", [None, "management-plane", "data-plane"])
async def test_dotnet_search_returns_azure_and_upstream_docs(monkeypatch, service_type):
chunks = []
for source_name, title in (
(SRC_AZURE_SDK_FOR_NET_DOCS, "eng#packages#http-client-csharp-mgmt#docs#emitter.md"),
(SRC_TYPESPEC_CSHARP_EMITTER_DOCS, "customization.md"),
):
source = get_knowledge_source(source_name)
assert source is not None
chunks.append(KnowledgeChunk(
source=source_name,
title=title,
content="C# emitter guidance",
link=source.get_link(title),
))
search = AsyncMock(return_value=chunks)
search_client = SimpleNamespace(
fused_search=search,
deduplicate_chunks=lambda results: results,
top_k=10,
expand_by_hierarchy=AsyncMock(side_effect=lambda chunk: chunk),
)
monkeypatch.setattr(knowledge_tools_module, "get_search_client", lambda: search_client)

result = await KnowledgeTools().search_knowledge_base(
queries=["How do I customize a C# client?"],
tenant_id=TenantID.DOTNET_CHANNEL_QA_BOT.value,
service_type=service_type,
)

assert {reference.source for reference in result.results} == {
SRC_AZURE_SDK_FOR_NET_DOCS, SRC_TYPESPEC_CSHARP_EMITTER_DOCS
}
search.assert_awaited_once()
filters = search.call_args.args[1]
for source_name in (SRC_AZURE_SDK_FOR_NET_DOCS, SRC_TYPESPEC_CSHARP_EMITTER_DOCS):
expected = f"context_id eq '{source_name}'"
if service_type:
expected += f" and (service_type eq '{service_type}' or service_type eq null)"
assert filters[source_name] == expected
assert search.call_args.kwargs["extra_filter"] == (
"(page_type eq null or page_type eq '')"
)


@pytest.mark.asyncio
async def test_search_knowledge_tool() -> None:
await app_config.init()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from config.tenant_config import (
SRC_AZURE_SDK_DOCS_ENG,
SRC_AZURE_SDK_FOR_NET_DOCS,
SRC_TYPESPEC_CSHARP_EMITTER_DOCS,
SRC_TYPESPEC_DOCS,
TenantConfig,
TenantID,
Expand All @@ -29,6 +31,51 @@ def test_internal_wiki_contexts_are_not_registered_sources():
assert get_knowledge_source(_WIKI_CONCEPT) is None


def test_dotnet_sources_include_branded_and_upstream_unbranded_docs():
tenant = TenantID.DOTNET_CHANNEL_QA_BOT.value
names = _source_names(tenant, None)
assert SRC_AZURE_SDK_FOR_NET_DOCS in names
assert SRC_TYPESPEC_CSHARP_EMITTER_DOCS in names
filters = _resolve_source_filters(names, tenant)
assert filters[SRC_AZURE_SDK_FOR_NET_DOCS] == (
"context_id eq 'azure_sdk_for_net_docs'"
)
assert filters[SRC_TYPESPEC_CSHARP_EMITTER_DOCS] == (
"context_id eq 'typespec_csharp_emitter_docs'"
)

for plane in ("data-plane", "management-plane"):
plane_filters = _resolve_source_filters(names, tenant, plane)
assert plane_filters[SRC_TYPESPEC_CSHARP_EMITTER_DOCS] == (
"context_id eq 'typespec_csharp_emitter_docs' and "
f"(service_type eq '{plane}' or service_type eq null)"
)


def test_dotnet_source_citations_preserve_repository_paths():
azure = get_knowledge_source(SRC_AZURE_SDK_FOR_NET_DOCS)
upstream = get_knowledge_source(SRC_TYPESPEC_CSHARP_EMITTER_DOCS)
assert azure is not None and upstream is not None
assert azure.get_link("eng#packages#http-client-csharp-mgmt#docs#emitter.md") == (
"https://github.com/Azure/azure-sdk-for-net/blob/main/"
"eng/packages/http-client-csharp-mgmt/docs/emitter.md"
)
assert upstream.get_link("customization.md") == (
"https://github.com/microsoft/typespec/blob/main/"
"packages/http-client-csharp/.tspd/docs/customization.md"
)


def test_other_language_tenants_do_not_gain_upstream_csharp_source():
for tenant in (
TenantID.PYTHON_CHANNEL_QA_BOT,
TenantID.GOLANG_CHANNEL_QA_BOT,
TenantID.JAVA_CHANNEL_QA_BOT,
TenantID.JAVASCRIPT_CHANNEL_QA_BOT,
):
assert SRC_TYPESPEC_CSHARP_EMITTER_DOCS not in _source_names(tenant.value, None)


def test_source_names_drop_internal_wiki_contexts():
got = _source_names(_TENANT, [SRC_TYPESPEC_DOCS, _WIKI_ENTITY])
assert got == [SRC_TYPESPEC_DOCS]
Expand Down
Loading
Loading