[Storage] Use ArmCustomPatch template#43207
Conversation
Next Steps to Merge✅ All automated merging requirements have been met! To get your PR merged, see aka.ms/azsdk/specreview/merge.Comment generated by summarize-checks workflow run. |
API Change CheckAPIView identified API level changes in this PR and created the following API reviews
Comment generated by After APIView workflow run. |
|
[NEW] 🟡 Warning [Uniform versioning — stable API version modified; Go SDK breaking change unresolved] This PR modifies two already-shipped stable API versions on
Per the uniform-versioning policy, shipped stable API versions are immutable. The change is a definition rename ( The PR carries Classification: Fix: Obtain |
| }; | ||
|
|
||
| /** | ||
| * A Connector is a tracked ARM resource modeled as a sub-resource of a Storage Account. |
There was a problem hiding this comment.
[NEW] 🟡 Warning [TSP — Misleading docstring on PATCH request body model]
The docstring says:```typespec
/**
- A Connector is a tracked ARM resource modeled as a sub-resource of a Storage Account.
*/
model ConnectorUpdate extends TrackedResourceUpdate { ... }```ButConnectorUpdateis the PATCH request body — not a tracked ARM resource. This wording was copy-pasted from the `Connector` tracked resource model. The incorrect description leaks into the generated SDK XML/JSDoc/PyDoc as misleading API documentation.
Classification: [NEW] — ConnectorUpdate was added in this PR.
Fix:```diff
-/**
-
- A Connector is a tracked ARM resource modeled as a sub-resource of a Storage Account.
- /
+/*
-
- The updatable properties of a Storage Connector. Used as the body of the Update (PATCH) operation.
- */```
| } | ||
|
|
||
| /** | ||
| * A DataShare is a tracked ARM resource modeled as a sub-resource of a Storage Account. |
There was a problem hiding this comment.
[NEW] 🟡 Warning [TSP — Misleading docstring on PATCH request body model]
Same issue as ConnectorUpdate: this docstring says:```typespec
/**
- A DataShare is a tracked ARM resource modeled as a sub-resource of a Storage Account.
*/
model DataShareUpdate extends TrackedResourceUpdate { ... }```ButDataShareUpdateis the PATCH request body, not a tracked ARM resource. Copy-pasted from the `DataShare` tracked resource.
Classification: [NEW] — DataShareUpdate was added in this PR.
Fix:```diff
-/**
-
- A DataShare is a tracked ARM resource modeled as a sub-resource of a Storage Account.
- /
+/*
-
- The updatable properties of a Storage DataShare. Used as the body of the Update (PATCH) operation.
- */```
| } | ||
|
|
||
| /** | ||
| * The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location' |
There was a problem hiding this comment.
[NEW] 🟡 Warning [TSP — Local model shadows Azure.ResourceManager.CommonTypes.TrackedResourceUpdate + misleading description]
Two issues with this model:
1. Naming collision / shadowing. The local model is named TrackedResourceUpdate, which is the same simple name as the built-in Azure.ResourceManager.CommonTypes.TrackedResourceUpdate. Inside this TypeSpec project any future reference to the unqualified name TrackedResourceUpdate will silently resolve to this local definition instead of the common-type. This is a footgun for future maintainers who may expect to reference the standard library model.
2. Misleading description. The docstring says "has 'tags' and a 'location'" but this model only adds tags. location is not settable via PATCH — it comes from the parent Azure.ResourceManager.CommonTypes.Resource and should be treated as read-only in update payloads.
Classification: [NEW] — TrackedResourceUpdate was added in this PR.
Fix:
-
Rename the model to avoid the shadowing (e.g.,
StorageTrackedResourcePatchorStorageTrackedResourceUpdate), update the two callers (ConnectorUpdate extends ...andDataShareUpdate extends ...), and coordinate Go/JS/Python SDK breaking-change approvals for the definition rename.
If renaming is not desired due to additional SDK churn, add an inline comment explicitly noting the intentional shadowing so future maintainers don't accidentally unqualify a reference expecting the CommonTypes version. -
Fix the description:
-/**
- * The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'
- */
+/**
+ * The patchable subset of a tracked ARM resource (— only resource tags). Used as a base for resource Update (PATCH) payloads.
+ */```<!-- posted-by: arm-api-reviewer-agent -->| /** | ||
| * Test connection to backing data source before creating the storage connector. | ||
| */ | ||
| @visibility(Lifecycle.Create, Lifecycle.Update) |
There was a problem hiding this comment.
[NEW] 💡 Suggestion [TSP — Unreachable Lifecycle.Create visibility on PATCH-only model]
@visibility(Lifecycle.Create, Lifecycle.Update)
testConnection?: boolean = false;```This decorator is on a property of `StorageConnectorPropertiesUpdate`, which is **only used as the `PatchModel` of `ArmCustomPatchAsync`**. That means this model never appears in a Create body — `Lifecycle.Create` is unreachable here. This appears to be a copy-paste from the corresponding property in `StorageConnectorProperties` (where Create + Update visibility is appropriate).
**Classification:** `[NEW]` — `StorageConnectorPropertiesUpdate` was added in this PR.
**Fix (optional):** Drop the decorator entirely (the property is visible in all contexts by default, which is fine for a PATCH-only model) or narrow to `@visibility(Lifecycle.Update)` for documentation clarity:
```diff
- @visibility(Lifecycle.Create, Lifecycle.Update)
- testConnection?: boolean = false;
+ testConnection?: boolean = false;```<!-- posted-by: arm-api-reviewer-agent -->| model StorageConnectorPropertiesUpdate { | ||
| /** | ||
| * State - Active or Inactive. Whether or not the Storage Connector should start as active (default: Active) | ||
| * (While set to false on the Storage Connector, all data plane requests using this Storage Connector fail, and this Storage Connector is not billed if it would be otherwise. |
There was a problem hiding this comment.
[NEW] 💡 Suggestion [TSP — Unbalanced parenthesis in property description]
The description opens a parenthesis but never closes it:
/**
* State - Active or Inactive. Whether or not the Storage Connector should start as active (default: Active)
* (While set to false on the Storage Connector, all data plane requests using this Storage Connector fail, and this Storage Connector is not billed if it would be otherwise.
*/```The same issue exists in the corresponding `StorageConnectorProperties.state` (pre-existing); this PR carried it forward into the new `StorageConnectorPropertiesUpdate`.
**Classification:** `[NEW]` for `StorageConnectorPropertiesUpdate` — this model was added in this PR. The same issue is `[EXISTING]` in `StorageConnectorProperties` (pre-existing).
**Fix (optional):**```diff
- * (While set to false on the Storage Connector, all data plane requests using this Storage Connector fail, and this Storage Connector is not billed if it would be otherwise.
+ * (While set to false on the Storage Connector, all data plane requests using this Storage Connector fail, and this Storage Connector is not billed if it would be otherwise.)
```<!-- posted-by: arm-api-reviewer-agent -->| emitter-output-dir: "{output-dir}/{service-dir}/arm-storage" | ||
| service-dir: sdk/storage | ||
| flavor: "azure" | ||
| compatibility-lro: true |
There was a problem hiding this comment.
[NEW] 💡 Suggestion [tspconfig — Consider documenting why compatibility-lro: true is set]
compatibility-lro: true```This setting preserves the pre-existing LRO method shape in the JavaScript SDK (`@azure/arm-storage`) that was already in GA before the TypeSpec migration. Without it, the `ArmCustomPatchAsync` template would change the emitted JavaScript LRO wrapper method names, causing a breaking change for existing callers.
**Classification:** `[NEW]` — added in this PR.
**Fix (optional):** Add a comment so future maintainers understand why this flag is set and can evaluate whether to keep it when bumping to a new API version:
```diff
+ # Preserve pre-existing LRO method signatures in @azure/arm-storage (GA SDK back-compat). compatibility-lro: true```<!-- posted-by: arm-api-reviewer-agent -->| @@clientName( | ||
| BlobServiceProperties.properties, | ||
| "BlobServiceProperties", | ||
| "!javascript" |
There was a problem hiding this comment.
[NEW] 💡 Suggestion [TSP — Consider adding a block comment explaining the !javascript scope pattern]
This PR adds "!javascript" to 9 @@clientName calls in this file (lines 199, 209, 224, 232, 243, 250, 275, 313, 325, 332) for the same reason: the JavaScript SDK already shipped these property names and renaming them would break existing callers. Adding a single block comment before the first such occurrence would document the convention once, instead of requiring readers to infer the pattern from 9 nearly-identical changes.
Classification: [NEW] — these scope qualifiers were added in this PR.
Fix (optional): Add a comment above this line:
+// The JS SDK (@azure/arm-storage) already shipped the property renames below under the original names.
+// The "!javascript" scope ensures the renames apply to all other languages but leave the JS names unchanged.
@@clientName(
BlobServiceProperties.properties,
"BlobServiceProperties",
"!javascript"
);```<!-- posted-by: arm-api-reviewer-agent -->|
[NEW] 🟡 Warning — Stable API version mutation with Go SDK breaking-change approval pending This PR modifies two already-shipped stable API versions:
The PR carries the label Action required before merge:
Note: Wire-level inspection of 2025-08-01 confirms the PATCH payloads are byte-identical between BASE and HEAD — the |
| }; | ||
|
|
||
| /** | ||
| * A Connector is a tracked ARM resource modeled as a sub-resource of a Storage Account. |
There was a problem hiding this comment.
[NEW] 🟡 Warning — Misleading doc-comment on ConnectorUpdate
The doc-comment says "The resource model definition for an Azure Resource Manager tracked top level resource…" — that is the boilerplate for a tracked ARM resource, but ConnectorUpdate is the PATCH request body (it only carries tags and properties). A reader scanning the generated SDK docs will think this is a full resource type.
Suggested fix: Replace the auto-generated tracked-resource blurb with something accurate, e.g.:
ypespec /** Request body for a PATCH update to a StorageConnector resource. */
| } | ||
|
|
||
| /** | ||
| * A DataShare is a tracked ARM resource modeled as a sub-resource of a Storage Account. |
There was a problem hiding this comment.
[NEW] 🟡 Warning — Misleading doc-comment on DataShareUpdate
Same issue as ConnectorUpdate above: the boilerplate says "tracked top level resource" but this model is the PATCH body for a DataShare resource. Please replace with an accurate description, e.g.:
ypespec /** Request body for a PATCH update to a StorageDataShare resource. */
| } | ||
|
|
||
| /** | ||
| * The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location' |
There was a problem hiding this comment.
[NEW] 🟡 Warning — Misleading doc-comment and potential naming collision on TrackedResourceUpdate
Two issues:
-
Inaccurate description. The comment says "has a 'tags' and a 'location' property", but the model only has
tags— there is nolocationproperty in a PATCH body (changing location on a tracked resource is not supported by ARM). -
Naming collision risk.
Azure.ResourceManager.CommonTypesalready exports a type namedTrackedResourceUpdate. Although the two definitions are currently shape-identical (tags: Record<string>+ allOf to the baseResource), having a local type with the same name as an ARM common type can cause confusion for future maintainers and may silently shadow the common type if import order changes.
Suggested fixes:
- Correct the description to mention only
tags. - Consider a more specific name (e.g.,
StorageTrackedResourceUpdate) to avoid the naming overlap, or explicitly alias the common type instead.
| /** | ||
| * Test connection to backing data source before creating the storage connector. | ||
| */ | ||
| @visibility(Lifecycle.Create, Lifecycle.Update) |
There was a problem hiding this comment.
[NEW] 💡 Suggestion — Dead Lifecycle.Create visibility on testConnection
testConnection is defined inside StorageConnectorPropertiesUpdate, which is the PATCH-only request body. The visibility is set to @visibility(Lifecycle.Create, Lifecycle.Update), but Lifecycle.Create is unreachable here — a PATCH body is never used in a PUT/create operation.
Consider using @visibility(Lifecycle.Update) only, or simply omitting the decorator (the default for a PATCH-body property already scopes to update).
| model StorageConnectorPropertiesUpdate { | ||
| /** | ||
| * State - Active or Inactive. Whether or not the Storage Connector should start as active (default: Active) | ||
| * (While set to false on the Storage Connector, all data plane requests using this Storage Connector fail, and this Storage Connector is not billed if it would be otherwise. |
There was a problem hiding this comment.
[NEW] 💡 Suggestion — Unbalanced parenthesis in state description (pre-existing, carried into new model)
The description for state reads: "The state of the storage connector (either Active or Inactive" — the closing parenthesis ) is missing.
Suggested fix:
ypespec /** The state of the storage connector (either Active or Inactive). */
This is a pre-existing issue in StorageConnectorProperties that has been copied into the new StorageConnectorPropertiesUpdate model; worth fixing in both places.
| emitter-output-dir: "{output-dir}/{service-dir}/arm-storage" | ||
| service-dir: sdk/storage | ||
| flavor: "azure" | ||
| compatibility-lro: true |
There was a problem hiding this comment.
[NEW] 💡 Suggestion — Add a rationale comment for compatibility-lro: true
compatibility-lro: true is a non-obvious emitter knob. Future maintainers (and SDK reviewers) will not know why it was enabled without context. Please add a brief inline comment, for example:
yaml # Required for JavaScript SDK back-compat: preserves the pre-LRO polling behavior # that existing callers depend on. Remove only after coordinating a major-version bump. compatibility-lro: true
| @@clientName( | ||
| BlobServiceProperties.properties, | ||
| "BlobServiceProperties", | ||
| "!javascript" |
There was a problem hiding this comment.
[NEW] 💡 Suggestion — Add a block comment explaining the "!javascript" scope pattern
This PR introduces nine @@clientName(..., "!javascript") overrides, but there is no comment explaining what the scope filter does or why it is applied here. Readers unfamiliar with the @azure-tools/typespec-client-generator-core scoping feature will not understand the intent.
Suggested comment to add above the first occurrence (or near the top of the file):
ypespec // The "!javascript" scope excludes the JavaScript/TypeScript emitter from the // @@clientName rename below, preserving the original auto-generated name for // the JS SDK to maintain back-compatibility with existing callers.
#38586) Configurations: 'specification/storage/Storage.Management/tspconfig.yaml', and CommitSHA: 'b373ded4a6c77a9f541ca8f020fd2072db632751' in SpecRepo: 'https://github.com/Azure/azure-rest-api-specs' Pipeline run: https://dev.azure.com/azure-sdk/internal/_build/results?buildId=6318750 Refer to https://eng.ms/docs/products/azure-developer-experience/develop/sdk-release/sdk-release-prerequisites to prepare for SDK release. **Release plan link:** [https://azsdk-releaseplan-dashboard-hveph5aqhhcfhtgu.westus-01.azurewebsites.net/?releaseplan=2220](https://azsdk-releaseplan-dashboard-hveph5aqhhcfhtgu.westus-01.azurewebsites.net/?releaseplan=2220) **Submitted by**: weiwei@microsoft.com ## Release Plan Details - Release Plan: https://aka.ms/sdk-release-planner?release-plan-id=3044af4d-f349-f111-bec7-000d3a5c46b0 Spec pull request: Azure/azure-rest-api-specs#43207 Spec API version: --------- Co-authored-by: kazrael2119 <98569699+kazrael2119@users.noreply.github.com>
Choose a PR Template
Switch to "Preview" on this description then select one of the choices below.
Click here to open a PR for a Data Plane API.
Click here to open a PR for a Control Plane (ARM) API.
Click here to open a PR for only SDK configuration.