with one click
mpg-migration
Handles Azure SDK for .NET management-plane migrations from AutoRest/Swagger to TypeSpec; use for MPG, mgmt migration, or Azure.ResourceManager.* migration requests.
Menu
Handles Azure SDK for .NET management-plane migrations from AutoRest/Swagger to TypeSpec; use for MPG, mgmt migration, or Azure.ResourceManager.* migration requests.
Review Azure SDK management-plane migration PRs (Swagger/AutoRest -> TypeSpec). Checks customization quality, TypeSpec decorator usage, and migration-specific anti-patterns on top of the standard mgmt PR review.
Review Azure SDK management-plane pull requests, check naming conventions, API compatibility, and code quality.
Patterns and techniques for mitigating breaking changes during Azure management-plane SDK migration from Swagger/AutoRest to TypeSpec. Covers SDK-side customizations (partial classes, CodeGenType, CodeGenSuppress) and TypeSpec decorator customizations (clientName, access, markAsPageable, alternateType, hierarchyBuilding).
Roll dice using a random number generator. Use when asked to roll a die (d6, d20, etc.), roll dice, or generate a random dice roll.
Roll dice using a random number generator.
Generate the code from typespec for C#. Parameter: C# SDK repository root location <cs_root>.
| name | mpg-migration |
| description | Handles Azure SDK for .NET management-plane migrations from AutoRest/Swagger to TypeSpec; use for MPG, mgmt migration, or Azure.ResourceManager.* migration requests. |
Use for Azure SDK for .NET management-plane migrations from AutoRest/Swagger to TypeSpec for packages named Azure.ResourceManager.*.
sdk/<service>/Azure.ResourceManager.<Service>/azure-rest-api-specs path if not at ../azure-rest-api-specs<service>-mpg-migration from mainsrc/Generated/ or metadata.json.WirePathAttribute removal entries in the centralized baseline file.client.tsp decorators with "csharp" scope before SDK custom code.Ask the user only when the spec repo path is missing, a fix requires files beyond client.tsp, or a generator bug has no safe workaround.
git status in SDK and spec repos, then sync both to latest main without disturbing unrelated dirty files.src/Custom/, src/Customization/, src/Customized/, hand-written partials, old shims) before first generation. Re-add only proven-needed compatibility shims later.<IncludeAutorestDependency>true</IncludeAutorestDependency> and remove/replace src/autorest.md.tsp-location.yaml to emitterPackageJsonPath: eng/azure-typespec-http-client-csharp-mgmt-emitter-package.json.tspCodeModel.json is preserved for hierarchy checks. -Services must be the exact package folder name, not service directory:
pwsh eng/packages/http-client-csharp-mgmt/eng/scripts/RegenSdkLocal.ps1 -Services "Azure.ResourceManager.<Service>" -LocalSpecRepoPath <path> -SaveInputs
Alternative from the package src/ directory: dotnet build /t:GenerateCode /p:SaveInputs=true.Before the build-fix loop, compare the generated hierarchy with the previous GA SDK. The previous GA DLL is restored automatically by ApiCompat from <ApiCompatVersion>. Write JSON outputs to temp/package-local scratch and do not commit them.
$scripts = "eng/packages/http-client-csharp-mgmt/eng/scripts"
pwsh $scripts/Get-PreviousGaResourceHierarchy.ps1 -ProjectPath sdk/<svc>/Azure.ResourceManager.<Svc>/src -OutFile ga-hierarchy.json
pwsh $scripts/Get-ResourceHierarchyFromTspCodeModel.ps1 -TspCodeModelPath sdk/<svc>/Azure.ResourceManager.<Svc>/src -GeneratedDir sdk/<svc>/Azure.ResourceManager.<Svc>/src/Generated -OutFile new-hierarchy.json
pwsh $scripts/Compare-ResourceHierarchy.ps1 -GAJson ga-hierarchy.json -NewJson new-hierarchy.json
0: every GA resource exists in the new SDK with the same ResourceType, parent set, scope, and singleton flag; continue.1: structural drift. Fix TypeSpec resource shape first (@parentResource, @singleton, scopes/templates). Do not enter ApiCompat mitigation yet.2: class-name renames only. Continue, but record and handle during naming/API compatibility work.For C# base-model/base-type compatibility, do not use @@hierarchyBuilding; use SDK custom code after the generated surface is stable.
Repeat: build → classify → fix → regenerate if needed → rebuild.
Always verify zero Swagger diff after spec changes. Keep a running status list grouped by issue category so real migration breaks, compatibility shims, and generator bugs stay distinct.
Classify each issue before fixing:
| Category | Preferred action |
|---|---|
| Spec shape: names, types, paging, visibility, grouping | Fix in client.tsp with scoped decorators |
| SDK compatibility gap: missing/changed shipped API | Add minimal SDK shim only after root cause is known |
| Customization drift | Remove stale custom code; re-add only proven shims |
| Generated-code drift | Regenerate/export API; do not hand-edit generated files |
| Generator bug | Stop, minimize repro, file/link issue |
Common decorator fixes:
| Problem | Decorator |
|---|---|
| Wrong property type | @@alternateType(Model.prop, targetType, "csharp") |
| Wrong operation parameter type | @@alternateType(Interface.op::parameters.param, targetType, "csharp") |
| Wrong name | @@clientName(target, "NewName", "csharp") |
| Model should be input and output | @@usage(Model, Usage.input, "csharp"); decorator appends, so specify only the missing flag |
| Needs pageable return type | @@markAsPageable(Interface.op, "csharp") |
| Flatten properties envelope | @@flattenProperty(Model.properties, "csharp") |
| Operation name collision | @@clientLocation(Interface.op, "GroupName", "csharp") |
SDK custom code goes in the package's existing customization folder (src/Custom/, src/Customization/, or src/Customized/). Use MCP tools for deterministic edits when available, then hand-write only remaining shim logic. Useful MCP edits include add_using_directive, remove_using_directive, regex_replacement, nullable_annotation_fix, rename_codegen_type, and add_codegen_suppress. Regenerate when CodeGen* attributes change.
Every customization file or significant custom member needs a root-cause comment explaining what generated differently and why SDK-side customization is required. Avoid vague comments like "for backward compatibility". Obsolete custom members do not need a separate justification comment when the [Obsolete] message already clearly explains the reason and replacement.
Model factory compatibility overloads should translate renamed parameters or enum/value types, then delegate to generated public model-factory overloads. Do not construct generated models through internal constructors, internal Properties bags, or private Core helpers just to preserve an old factory signature. First look for a public generated factory overload or public model surface that can receive the same values.
SDK-side fix patterns when decorators cannot help:
| Problem | Fix |
|---|---|
| Base model/base type changed | Add a custom partial model declaring the intended base model; use [CodeGenType] only when the custom type name differs from the generated/TypeSpec name, then regenerate. Do not use @@hierarchyBuilding. |
| Flattened properties lost on a polymorphic type | Shim properties delegating to the Properties bag |
| Protected constructor missing on a discriminated base | Add a protected constructor in the partial class |
Property lost due to @@alternateType model swap | Add the property in a partial class |
pwsh eng/scripts/Export-API.ps1 <service>.ApiCompatVersion / latest stable package tag. Use origin/main only if it matches that baseline.WirePathAttribute removal diffs.For every new public API, classify it before keeping it:
| Category | Action |
|---|---|
| Real service/API-version addition | Keep and note source API version in PR status |
| Rename of existing shipped API | Prefer @@clientName; otherwise suppress/add minimal shim. Do not keep both names without approval |
| Generator convenience/drift | Investigate operation id, route, resource type, and prior API before keeping |
Compare each new member against the previous GA public API listing or restored ApiCompat assembly, operation id and request path in generated XML docs/source, resource type/parent hierarchy, and the TypeSpec or Swagger API version where the operation/model first appears. If a new API is actually a rename of an existing API, fix the rename instead of documenting it as additive.
If generated code is structurally wrong after stale customizations are removed, stop and report a generator bug. Create a minimum TypeSpec repro, document any approved workaround in client.tsp or SDK custom code with an issue link, and pause migration if no safe workaround exists.
mpg-migration-pr-review rules.CHANGELOG.md has a short migration note and ci.mgmt.yml exists if needed.Add csharp customizations for <Service> migration.tsp-location.yaml to point to the fork spec commit, then push SDK changes to a fork and open draft SDK PR titled [Mgmt] <PackageName>: Migrate to TypeSpec.tsp-location.yaml to the final spec commit, regenerate once without LocalSpecRepoPath, run pre-commit-checks, and verify build.WirePathAttribute removal entries.tsp-location.yaml points to the final spec commit.