Extend arm-resource-patch rule with PATCH body schema diagnostics#4381
Extend arm-resource-patch rule with PATCH body schema diagnostics#4381Copilot wants to merge 16 commits into
Conversation
Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/8d5e1eda-4793-4990-923e-3863b9f28d83 Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
markcowl
left a comment
There was a problem hiding this comment.
Pull the latest from main, Reformulate ttests for the suggested changes, implement the changes, ensure that all tests pass, all files are formatted correctly and only the changes for this PR are in the PR diff.
…-body-schema-rule Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
…ew deprecation Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/713242e6-42ef-450f-adbc-fa7ec7dca99c Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
commit: |
markcowl
left a comment
There was a problem hiding this comment.
Pull the latest from main, make tests for the suggested changes, then imlement the changes. Ensure that all tests pass, that samples rebuild correctly and without error, that all files are correctly formatted and that your branch is up to date with mean and only changes that are part of this PR are in the PR diff.
Branch is up to date with Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
…Read-only required props Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/a4b1fbcd-d639-4dd2-bc82-f1dc449f07e6 Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
/azp run typespec-azure - PR Tools |
|
Azure Pipelines successfully started running 1 pipeline(s). |
⚡ Benchmark Results
Full details – comparing
|
| Metric | Baseline | Current | Change |
|---|---|---|---|
| total | 🔴 840.9ms | 🔴 832.3ms | -1.0% |
| loader | 🟢 164.2ms | 🟢 165.0ms | +0.5% |
| resolver | 🟢 17.7ms | 🟢 18.7ms | +5.6% 🔴 |
| checker | 🟡 204.7ms | 🟡 202.2ms | -1.2% |
| validation | 🟢 43.3ms | 🟢 41.0ms | -5.2% 🟢 |
| ↳ validation/@azure-tools/typespec-azure-core | 🟢 6.9ms | 🟢 6.6ms | -4.8% |
| ↳ validation/@typespec/http | 🟢 6.7ms | 🟢 6.2ms | -8.1% 🟢 |
| ↳ validation/@typespec/rest | 🟢 0.6ms | 🟢 0.5ms | -9.6% 🟢 |
| ↳ validation/@typespec/versioning | 🔴 27.4ms | 🔴 26.3ms | -4.1% |
| ↳ validation/compiler | 🟢 1.7ms | 🟢 1.5ms | -11.9% 🟢 |
| linter | 🟢 142.8ms | 🟢 151.2ms | +5.9% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/auth-required | 🟢 0.0ms | 🟢 0.0ms | -4.4% |
| ↳ linter/@azure-tools/typespec-azure-core/bad-record-type | 🟢 0.2ms | 🟢 0.2ms | -6.5% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/byos | 🟢 5.9ms | 🟢 6.1ms | +3.1% |
| ↳ linter/@azure-tools/typespec-azure-core/casing-style | 🟢 0.6ms | 🟢 0.6ms | +2.7% |
| ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance | 🟢 0.1ms | 🟢 0.1ms | -5.7% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/documentation-required | 🟢 0.8ms | 🟢 0.8ms | -0.4% |
| ↳ linter/@azure-tools/typespec-azure-core/friendly-name | 🟢 0.6ms | 🟢 0.6ms | +0.2% |
| ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required | 🟢 0.2ms | 🟢 0.2ms | +0.2% |
| ↳ linter/@azure-tools/typespec-azure-core/known-encoding | 🟢 0.2ms | 🟢 0.2ms | +0.8% |
| ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required | 🟢 0.3ms | 🟢 0.3ms | -0.5% |
| ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch | 🟢 0.2ms | 🟢 0.2ms | +3.6% |
| ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union | 🟢 0.3ms | 🟢 0.3ms | +3.4% |
| ↳ linter/@azure-tools/typespec-azure-core/no-enum | 🟢 0.0ms | 🟢 0.0ms | -3.8% |
| ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes | 🟢 0.1ms | 🟢 0.1ms | +4.5% |
| ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops | 🟢 0.1ms | 🟢 0.1ms | +11.2% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/no-format | 🟢 0.5ms | 🟢 0.5ms | -2.7% |
| ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric | 🟢 0.4ms | 🟢 0.4ms | +1.6% |
| ↳ linter/@azure-tools/typespec-azure-core/no-header-explode | 🔴 20.3ms | 🔴 21.0ms | +3.3% |
| ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage | 🟢 1.1ms | 🟢 1.1ms | -0.1% |
| ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator | 🟢 0.1ms | 🟢 0.1ms | -5.4% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/no-nullable | 🟢 0.2ms | 🟢 0.2ms | -12.2% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime | 🟢 1.2ms | 🟢 1.3ms | +1.9% |
| ↳ linter/@azure-tools/typespec-azure-core/no-openapi | 🟢 2.1ms | 🟢 1.9ms | -11.0% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/no-private-usage | 🟢 1.8ms | 🟢 1.8ms | -0.9% |
| ↳ linter/@azure-tools/typespec-azure-core/no-query-explode | 🔴 21.0ms | 🔴 21.4ms | +1.6% |
| ↳ linter/@azure-tools/typespec-azure-core/no-response-body | 🔴 24.7ms | 🔴 24.1ms | -2.6% |
| ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces | 🟢 0.0ms | 🟢 0.0ms | +6.1% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch | 🟢 5.8ms | 🟢 6.0ms | +3.5% |
| ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params | 🟢 0.2ms | 🟢 0.2ms | +5.1% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator | 🟢 0.1ms | 🟢 0.0ms | -12.5% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/no-unknown | 🟢 0.2ms | 🟢 0.2ms | -6.9% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union | 🟢 0.3ms | 🟢 0.3ms | +0.2% |
| ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version | 🟢 0.2ms | 🟢 0.2ms | +5.2% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/request-body-problem | 🟢 0.3ms | 🟢 0.2ms | -14.2% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/require-versioned | 🟢 0.0ms | 🟢 0.0ms | -7.9% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem | 🔴 23.3ms | 🔴 24.6ms | +5.3% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body | 🟢 0.3ms | 🟢 0.3ms | +6.0% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model | 🟢 0.2ms | 🟢 0.3ms | +8.0% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/use-standard-names | 🟢 5.4ms | 🟢 5.8ms | +7.0% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations | 🟢 0.1ms | 🟢 0.1ms | -2.6% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version | 🟢 6.3ms | 🟢 5.8ms | -7.6% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key | 🟢 0.1ms | 🟢 0.1ms | -15.8% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage | 🟢 0.1ms | 🟢 0.1ms | -1.5% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes | 🟢 8.8ms | 🟢 7.1ms | -18.9% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record | 🟢 0.4ms | 🟢 0.4ms | +12.9% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes | 🟢 0.8ms | 🟢 0.7ms | -9.5% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes | 🟢 0.0ms | 🟢 0.0ms | -6.1% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment | 🟢 0.2ms | 🟢 0.2ms | +4.2% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property | 🟢 0.1ms | 🟢 0.2ms | +3.3% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator | 🟢 0.0ms | 🟢 0.0ms | +9.2% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb | 🟢 0.1ms | 🟢 0.1ms | +18.8% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property | 🟢 0.1ms | 🟢 0.1ms | +5.1% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format | 🟢 0.1ms | 🟢 0.1ms | -9.6% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars | 🟢 0.3ms | 🟢 0.3ms | +7.6% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern | 🟢 0.0ms | 🟢 0.0ms | -35.0% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation | 🟢 0.2ms | 🟢 0.2ms | +11.1% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response | 🟢 5.4ms | 🟢 8.0ms | +48.9% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch | 🟢 0.4ms | 🟢 0.4ms | +21.6% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars | 🟢 0.2ms | 🟢 0.2ms | -1.8% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state | 🟢 0.1ms | 🟢 0.1ms | +3.8% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels | 🟢 0.1ms | 🟢 0.1ms | -6.0% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties | 🟢 0.2ms | 🟢 0.2ms | +2.3% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation | 🟢 0.0ms | 🟢 0.0ms | +10.3% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header | 🟡 17.5ms | 🔴 37.1ms | +112.2% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint | 🟢 0.0ms | 🟢 0.0ms | -14.7% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers | 🟢 0.3ms | 🟢 0.3ms | +12.7% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model | 🟢 0.1ms | 🟢 0.1ms | +4.2% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation | 🟢 0.2ms | 🟢 0.2ms | -4.8% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body | 🔴 24.9ms | 🔴 27.8ms | +11.5% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope | 🟢 0.1ms | 🟢 0.1ms | +7.7% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name | 🟢 0.2ms | 🟢 0.2ms | +6.9% 🔴 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop | 🟢 2.7ms | 🟢 2.4ms | -13.1% 🟢 |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type | 🟢 0.4ms | 🟢 0.4ms | +2.2% |
| ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression | 🟢 0.0ms | 🟢 0.0ms | -11.8% 🟢 |
| ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict | 🟢 1.1ms | 🟢 1.1ms | -2.3% |
| ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix | 🟢 0.2ms | 🟢 0.2ms | +2.3% |
| emit | 🟡 268.3ms | 🟡 254.1ms | -5.3% 🟢 |
| ↳ emit/@azure-tools/typespec-autorest | 🟢 159.0ms | 🟢 160.0ms | +0.6% |
| ↳ emit/@typespec/openapi3 | 🟢 163.8ms | 🟢 141.1ms | -13.9% 🟢 |
| ↳ emit/@typespec/openapi3/compute | 🟢 150.0ms | 🟢 125.8ms | -16.1% 🟢 |
| ↳ emit/@typespec/openapi3/write | 🟢 13.7ms | 🟢 15.2ms | +11.0% 🔴 |
Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)
|
All changed packages have been documented.
Show changes
|
|
You can try these changes here
|
There was a problem hiding this comment.
@copilot Pull the latest from main, then add some tests for the code fixes. Ensure all tests pass, all files are correctly formatted, samples rebuild cleanly, and only the changes associated withy this pull request are in the PR diff.
|
@copilot Note that, properties with default visibility have visibility (Lifecycle.Read, Lifecycle.Update, Lifecycle.Create). You seem to be marking these properties as not being updatable. Please change the way you look for the correct viisibility in a PATCH body - any property that has default visibility or create, update visibility, or create, update, read visibility, or read visibility can be included in a PATCH request. Update tests to validate this behavior, then implement the behavior, ensure all tests pass, all files are properly formatted, pull the latest from main and ensure that only changes associate with this pull request are in the pr diff. |
…eadOnlyOnly; apply doc/changeset suggestions Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/4fa3bf3e-294c-43c3-a193-8c03d78c3524 Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
@copilot Pull the latest from main, make the suggested changes, rebuild and rebuild the documentation, ensure that all tests pass, all files are properly formatted and only the changes associated with this pull request are in the PR diff.
| default: "The request body of a PATCH must be a model with a subset of resource properties", | ||
| missingTags: "Resource PATCH must contain the 'tags' property.", | ||
| modelSuperset: paramMessage`Resource PATCH models must be a subset of the resource type. The following properties: [${"name"}] do not exist in resource Model '${"resourceModel"}'.`, | ||
| notUpdateableInPatch: paramMessage`Property '${"propertyName"}' is in the PATCH request body but is not updateable on the resource. PATCH bodies may only contain properties whose visibility includes 'Lifecycle.Update' (this includes default visibility, '@visibility(Lifecycle.Update)' alone, or any combination of 'Lifecycle.Update' with other lifecycle modifiers), or whose visibility is exactly '{Lifecycle.Read}' by itself; other visibilities (for example '@visibility(Lifecycle.Create)' or '@visibility(Lifecycle.Create, Lifecycle.Read)') must be removed from the PATCH request model.`, |
There was a problem hiding this comment.
| notUpdateableInPatch: paramMessage`Property '${"propertyName"}' is in the PATCH request body but is not updateable on the resource. PATCH bodies may only contain properties whose visibility includes 'Lifecycle.Update' (this includes default visibility, '@visibility(Lifecycle.Update)' alone, or any combination of 'Lifecycle.Update' with other lifecycle modifiers), or whose visibility is exactly '{Lifecycle.Read}' by itself; other visibilities (for example '@visibility(Lifecycle.Create)' or '@visibility(Lifecycle.Create, Lifecycle.Read)') must be removed from the PATCH request model.`, | |
| notUpdateableInPatch: paramMessage`Property '${"propertyName"}' is in the PATCH request body but is not updateable on the resource. Meke this property updateable on the resource or remove it from the PATCH request.`, |
There was a problem hiding this comment.
Applied the suggested message text.
| missingTags: "Resource PATCH must contain the 'tags' property.", | ||
| modelSuperset: paramMessage`Resource PATCH models must be a subset of the resource type. The following properties: [${"name"}] do not exist in resource Model '${"resourceModel"}'.`, | ||
| notUpdateableInPatch: paramMessage`Property '${"propertyName"}' is in the PATCH request body but is not updateable on the resource. PATCH bodies may only contain properties whose visibility includes 'Lifecycle.Update' (this includes default visibility, '@visibility(Lifecycle.Update)' alone, or any combination of 'Lifecycle.Update' with other lifecycle modifiers), or whose visibility is exactly '{Lifecycle.Read}' by itself; other visibilities (for example '@visibility(Lifecycle.Create)' or '@visibility(Lifecycle.Create, Lifecycle.Read)') must be removed from the PATCH request model.`, | ||
| requiredInPatch: paramMessage`Property '${"propertyName"}' is required in the PATCH request body. PATCH request body properties must all be optional so partial updates work, unless the resource property they map to has visibility 'Lifecycle.Read' by itself.`, |
There was a problem hiding this comment.
| requiredInPatch: paramMessage`Property '${"propertyName"}' is required in the PATCH request body. PATCH request body properties must all be optional so partial updates work, unless the resource property they map to has visibility 'Lifecycle.Read' by itself.`, | |
| requiredInPatch: paramMessage`Property '${"propertyName"}' is required in the PATCH request body. PATCH request body properties must all be optional or readOnly.`, |
There was a problem hiding this comment.
Applied the suggested message text.
| notUpdateableInPatch: paramMessage`Property '${"propertyName"}' is in the PATCH request body but is not updateable on the resource. PATCH bodies may only contain properties whose visibility includes 'Lifecycle.Update' (this includes default visibility, '@visibility(Lifecycle.Update)' alone, or any combination of 'Lifecycle.Update' with other lifecycle modifiers), or whose visibility is exactly '{Lifecycle.Read}' by itself; other visibilities (for example '@visibility(Lifecycle.Create)' or '@visibility(Lifecycle.Create, Lifecycle.Read)') must be removed from the PATCH request model.`, | ||
| requiredInPatch: paramMessage`Property '${"propertyName"}' is required in the PATCH request body. PATCH request body properties must all be optional so partial updates work, unless the resource property they map to has visibility 'Lifecycle.Read' by itself.`, | ||
| defaultInPatch: paramMessage`Property '${"propertyName"}' has a default value in the PATCH request body. PATCH request body properties that are not present in the request body leave the value unchanged; they do not result in any default value being assigned.`, | ||
| nonMergePatchContentType: paramMessage`PATCH operation '${"operationName"}' specifies a content-type other than 'application/merge-patch+json'.`, |
There was a problem hiding this comment.
Need to include a variable for the content-type that was specified. Add a test to validate that the diagnostic message contains the offending content-type and update the code to emit the offending content-type in this diagnostic.
There was a problem hiding this comment.
Added a contentType parameter to the nonMergePatchContentType diagnostic and updated checkPatchContentType to find the first offending content-type and emit it. Updated the existing application/xml test to assert the value appears in the message and added a second test using text/plain to verify the variable interpolation.
| const readOnlyOnlyCache = new Map<ModelProperty, boolean>(); | ||
|
|
||
| for (const property of patchModel) { | ||
| // Required (non-optional) PATCH body properties are only allowed when the |
| context: LinterRuleContext<DiagnosticMessages>, | ||
| patchModel: ModelProperty[], | ||
| ) { | ||
| // The `isReadOnlyOnly` check is a pure per-source-property predicate that |
| const sourceProperty = getSourceProperty(property); | ||
| const cached = cache.get(sourceProperty); | ||
| if (cached !== undefined) return cached; | ||
| const lifecycle = getLifecycleVisibilityEnum(program); |
There was a problem hiding this comment.
This should be done once as part of setup for this rule - it should not be executed every time we test the readability of a property.
There was a problem hiding this comment.
Resolved by computing the lifecycle visibility class members (Read, Update) once in create(context) and threading them through as a LifecycleMembers struct. isReadOnlyOnly now reads lifecycleMembers.read directly instead of calling getLifecycleVisibilityEnum per-property.
| readOnlyOnlyCache: Map<ModelProperty, boolean>, | ||
| ): boolean { | ||
| const lifecycle = getLifecycleVisibilityEnum(program); | ||
| const updateMember = lifecycle.members.get("Update"); |
There was a problem hiding this comment.
This should be excuted once as part of the setup to this rule, not on every check
There was a problem hiding this comment.
Resolved together with the isReadOnlyOnly setup change — isAllowedInPatchByVisibility now reads the pre-resolved lifecycleMembers.update member instead of looking it up per-check.
|
|
||
| - All properties in the PATCH request body are optional (PATCH supports partial updates) or read-only (not included in requests). | ||
| - No PATCH request body property has a default value (a property absent from a PATCH request leaves the existing value unchanged; defaults are not applied). | ||
| - Every PATCH request body property maps back to a resource property whose visibility either includes `Lifecycle.Update` (this includes default visibility, `@visibility(Lifecycle.Update)` alone, or any combination of `Lifecycle.Update` with other lifecycle modifiers) or is exactly `{Lifecycle.Read}` by itself. Visibilities like `@visibility(Lifecycle.Create)` or `@visibility(Lifecycle.Create, Lifecycle.Read)` are not allowed. The check is applied recursively to nested model and `Record<Model>` property types. |
There was a problem hiding this comment.
| - Every PATCH request body property maps back to a resource property whose visibility either includes `Lifecycle.Update` (this includes default visibility, `@visibility(Lifecycle.Update)` alone, or any combination of `Lifecycle.Update` with other lifecycle modifiers) or is exactly `{Lifecycle.Read}` by itself. Visibilities like `@visibility(Lifecycle.Create)` or `@visibility(Lifecycle.Create, Lifecycle.Read)` are not allowed. The check is applied recursively to nested model and `Record<Model>` property types. | |
| - Every PATCH request body property maps back to a resource property that is updateable or readOnly. |
There was a problem hiding this comment.
Applied the suggestion in the docs source.
markcowl
left a comment
There was a problem hiding this comment.
@copilot Pull the latest from main, make the suggested changes, rebuild the affected projuects and documentation, validate that all tests pass and all files are correctly formatted, and that only changes associated with this pull request are in the PR diff.
…-body-schema-rule Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
…ove comments, hoist lifecycle setup Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/da5ec04b-586d-41d4-9f2a-a6f06146326d Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
markcowl
left a comment
There was a problem hiding this comment.
Pull the latest from main
Make the suggested changes
Ensure all tests pass and all files are correctly formatted
Ensure that the PR diff contains only changes associated with this PR
| for (const property of patchModel) { | ||
| if ( | ||
| !property.optional && | ||
| !isReadOnlyOnly(context.program, property, lifecycleMembers, readOnlyOnlyCache) |
There was a problem hiding this comment.
use isReadOnly as the name of this method. isReadOnlyOnly reads as an unnatural repetition of only
There was a problem hiding this comment.
Renamed to isReadOnly.
…Cache Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/3879120b-c321-458c-a0ba-bd792913f361 Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
/azp run typespec-azure - PR Tools |
|
Azure Pipelines successfully started running 1 pipeline(s). |
markcowl
left a comment
There was a problem hiding this comment.
Pull the latest from main, make this change, ensure that all files are properly formatted, all tests pass, and only the changes associated with this PR are in the PR diff.
| }); | ||
| }); | ||
|
|
||
| it("emits requiredInPatch diagnostic when a PATCH body property is required", async () => { |
There was a problem hiding this comment.
Add a test that verifies that there is no diagnostic when the 'properties' property of a tracked resource is included as an optional property in the patch request body. Make any necessary changes to the implementaion to make this test pass
There was a problem hiding this comment.
Added a test that verifies no diagnostic is emitted when properties?: FooProperties is included as an optional property in the PATCH body of a tracked resource (with FooProperties containing both a default-visibility property and a @visibility(Lifecycle.Read) property). The existing implementation already handles this correctly — the properties field on TrackedResource has default visibility (so hasVisibility(Update) is true), and the recursive walk into FooProperties finds only updateable or read-only properties — so no implementation change was needed. All 23 patch-operations tests pass.
…-body-schema-rule Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
…valid Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/f133c0ec-6735-40c7-8b00-4dc5fad8927f Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
requiredInPatch,defaultInPatch,notUpdateableInPatch,nonMergePatchContentType)notUpdateableInPatchacross nested model +Record<Model>properties with cycle protectionhasVisibility(Lifecycle.Update) || isReadOnly(...)predicatecreate(context)isReadOnlyOnly→isReadOnlyandreadOnlyOnlyCache→readOnlyCachepropertiesfield included as optional in PATCH body (no implementation change needed — existing recursion correctly accepts default-visibility containers wrapping read-only or updateable properties)