Skip to content

Add arm-resource-required-operations linter rule#4380

Draft
Copilot wants to merge 21 commits into
mainfrom
copilot/add-arm-resource-required-operations-rule
Draft

Add arm-resource-required-operations linter rule#4380
Copilot wants to merge 21 commits into
mainfrom
copilot/add-arm-resource-required-operations-rule

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 5, 2026

Adds a new arm-resource-required-operations linter rule for @azure-tools/typespec-azure-resource-manager that validates ARM resources declare their required operations.

Required operations by resource kind

  • Tracked (non-singleton): read, createOrUpdate, delete, list-by-parent (satisfied by list-by-resource-group), and list-by-subscription (only for top-level resource-group-scoped resources).
  • Tracked singleton: read, createOrUpdate only.
  • Proxy / Extension: only read is required.

The "any resource with createOrUpdate (PUT) must also define delete" condition continues to be enforced by the existing no-resource-delete-operation rule and is intentionally not duplicated here.

Resources derived from Azure.ResourceManager.CommonTypes.NetworkSecurityPerimeterConfiguration, PrivateLinkResource, or PrivateEndpointConnection are exempt.

The rule iterates each ResolvedResource entry returned by resolveArmResources (called once per program) — a single resource model may represent multiple actual resources, so entries are not grouped by model. Operations contributed by additional resolver entries sharing the same canonical ancestor path (path-doubling artifacts) are merged into the canonical entry's operation set. kind, singleton, and operations are read directly off each ResolvedResource. A single default diagnostic is emitted listing every missing operation when more than one is missing; specific message IDs (missingGet, missingCreateOrUpdate, missingDelete, missingListByParent, missingListBySubscription) are used when only one operation is missing. The diagnostic target is the resource's @armResourceOperations interface (where the operations are declared), and code fixes insert template-based operation declarations into that interface.

Changes

  • New rule and registration in the resource-manager ruleset.
  • 18 unit tests covering tracked (full set, singleton, individual missing operations), proxy/extension (read-only valid, PUT-without-delete valid for this rule — covered by no-resource-delete-operation, missing-read emits missingGet), @armVirtualResource skip, and the NSP / PrivateLink / PrivateEndpoint exemptions.
  • Sample updates: added listBySubscription to the Widget interfaces in legacy/optional-body and legacy/rename-operations (and refreshed their snapshots).
  • Rule documentation page and chronus changelog entry.

Copilot AI and others added 2 commits May 5, 2026 18:04
…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copilot AI requested a review from markcowl May 5, 2026 18:13
@markcowl markcowl changed the title Add arm-resource-required-operations rule and extend arm-resource-patch Add arm-resource-required-operations rule May 5, 2026
Copy link
Copy Markdown
Member

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

Please pull the latest from main, make the changes requested, ensure that all tests are passing, all files are formatted correctly, that samples rebuild correctly and that the PR diff contains only changes associated with this pr

return {
model: (model: Model) => {
if (isInternalTypeSpec(context.program, model)) return;
const armResource = getArmResources(context.program).find((r) => r.typespecType === model);
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.

getArmResources is an expensive operation. We shgoulr un this once for the prgram and filter the results for each resource model.

Also, we should use resolveArmResources instead of getArmResources, as it handles both standard and legacy resource operations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched to resolveArmResources, called once per program and cached in a Map<Model, ResolvedResource[]> closure that's reused for every model visit (5b963c9).

): RequiredOperation[] {
const kind = armResource.kind;
if (kind !== "Tracked" && kind !== "Proxy" && kind !== "Extension") {
return [];
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.

All resources that are not singletons should have read, list-by-parent

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unified the requirements so every non-singleton resource needs read + createOrUpdate + delete + list-by-parent. Tracked resources additionally need list-by-subscription, and a list-by-resource-group operation satisfies the list-by-parent requirement at resource-group scope (5b963c9).

Copilot AI and others added 2 commits May 5, 2026 21:19
…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 5, 2026

Please pull the latest from main, make the changes requested, ensure that all tests are passing, all files are formatted correctly, that samples rebuild correctly and that the PR diff contains only ch...

Merged latest main, applied the requested rule changes, ran pnpm format, and verified the full ARM test suite (300 tests) and rulesets tests pass. PR diff vs main only contains files for the new arm-resource-required-operations rule (5b963c9).

Copilot AI changed the title Add arm-resource-required-operations rule Add arm-resource-required-operations rule May 5, 2026
Copilot AI requested a review from markcowl May 5, 2026 21:32
Copy link
Copy Markdown
Member

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

Pull the latest from main, make the requested changes, validate that all tests pass and all files are formatted correctly, that your branch is up to date with main and that all changes in the PR diff are part of this PR.

},
create(context) {
// Resolve resources once for the program and reuse for every model visit.
let resourcesByModel: Map<Model, ResolvedResource[]> | undefined;
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.

This is the wrong way to use the result of resolveARmResources. Each ResolvedResource is a resource with its operations and you should use this rather than making other calls to to assemble resource definitions.

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.

The 'model' does not define a resource in some scenarios - some scenarios use a single model to describe multiple resources, so using the returned ResolvedResource array from resolveArmResources uniquely defines each resource, and you should be able to get the resource kind from this as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Restructured to iterate ResolvedResource entries from resolveArmResources via a root: listener and read kind, singleton, and operations directly off each entry — no auxiliary lookups for those. Because a single declared resource can produce multiple ResolvedResource entries (ARM operation templates emit extra paths for createOrUpdate when a nested resource exists), entries are grouped by model identity and one diagnostic is reported per logical resource using the union of their operations (38144d7).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched to iterating each ResolvedResource returned by resolveArmResources (root listener). Kind/singleton are now read from the ResolvedResource itself. Multiple entries that the resolver produces for the same model (path-doubling for createOrUpdate under nested resources) are grouped per model and merged into a single logical-resource check, using the canonical (shortest resourceType.types) entry for kind/singleton/name (38144d7).

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 6, 2026

Pull the latest from main, make the requested changes, validate that all tests pass and all files are formatted correctly, that your branch is up to date with main and that all changes in the PR diff ...

Branch is up to date with main (no new upstream commits since the last sync). Applied the requested ResolvedResource-based restructuring, ran pnpm format, and verified the full ARM test suite (300/300) and rulesets tests pass. PR diff vs main only contains files for the new arm-resource-required-operations rule (38144d7).

Copilot AI changed the title Add arm-resource-required-operations rule Add arm-resource-required-operations linter rule May 6, 2026
Copilot AI requested a review from markcowl May 6, 2026 02:41
@markcowl
Copy link
Copy Markdown
Member

markcowl commented May 7, 2026

@copilot there is a merge conflict. Pull the latest from main, merge your changes, validate that all tests pass and all files are formatted correctly, that your branch is up to date with main and that all changes in the PR diff are part of this PR.

…rce-required-operations-rule

Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/f98c08fb-bae8-4462-a33e-47862ea7bfed

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
@markcowl
Copy link
Copy Markdown
Member

markcowl commented May 8, 2026

@copilot you did not resolve any of the merge conflicts

…rce-required-operations-rule

# Conflicts:
#	packages/typespec-azure-resource-manager/README.md
#	packages/typespec-azure-resource-manager/src/linter.ts
#	website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 8, 2026

@copilot you did not resolve any of the merge conflicts

Sorry — the previous attempt's resolved merge state was lost before the merge commit was created, so the conflicts reappeared. Re-merged latest main, resolved the conflicts in linter.ts, README.md, and linter.md (kept both the arm-resource-required-operations and version-progression rows), and committed the merge. Rebuild + pnpm regen-docs + pnpm format produced no further changes; ARM tests pass (314/314), rulesets tests pass (3/3) (4b375a2).

@markcowl
Copy link
Copy Markdown
Member

@copilot There are merge conflicts. Please pull the latest from main, fix any conflicts rebuild and rebuild docs, check that all files are formatted correctly, all tests pass, and that only the changes associates with this PR are in the PR diff

…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 11, 2026

@copilot There are merge conflicts. Please pull the latest from main, fix any conflicts rebuild and rebuild docs, check that all files are formatted correctly, all tests pass, and that only the change...

Merged latest main — clean merge with no conflicts this round (the only new upstream commit was 8a0b6e3 which touched TCGC docs, not files this PR changes). Rebuild + pnpm regen-docs produced no diffs, pnpm format clean, ARM tests pass (314/314), rulesets tests pass (3/3) (b5cfec6).

Copy link
Copy Markdown
Member

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

We need to narrow this rule and update the tests to match.

  • We should keep the checks over tracked resource, with the exceptions we currently have for singleton resources.
  • We should also require that anjy resource with a 'put' operation has a 'delete' operation.
  • We should only require 'get' operations for other resources

Please update the tests to match this narrowing, update any codefixes to match, ensure that all tests pass, all files are correctly formatted. Pull the latest from main and enxure that only the changes associated with this pull request are in the pr diff.

Copilot AI and others added 2 commits May 13, 2026 00:09
…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
…and delete if put present)

Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/42b7ce08-198a-4a01-9260-473a33e46175

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 13, 2026

We need to narrow this rule and update the tests to match.

  • We should keep the checks over tracked resource, with the exceptions we currently have for singleton resources.
  • We should also require th...

Narrowed the rule per your guidance:

  • Tracked resources keep the full required set with the existing singleton exception (singleton tracked = read + createOrUpdate only).
  • Non-tracked resources (proxy / extension) only require read.
  • Any resource that defines createOrUpdate (PUT) must also define delete, regardless of kind.

Updated the tests to match (replaced the old "nested proxy missing list-by-parent" test with: proxy-with-only-read = valid, proxy-with-put-but-no-delete emits missingDelete, proxy-missing-read emits missingGet; relaxed the extension test). Removed the #suppress annotations from the polymorphic proxy/extension samples since they're now valid under the narrower rule. Code-fix list trims itself naturally — only fixes for actually-missing operations are offered.

Merged latest main (clean), regenerated docs, pnpm format clean, ARM tests pass (324/324), rulesets (3/3), sample snapshots (68/68); PR diff scoped to this rule (aebb3fa).

Copilot AI requested a review from markcowl May 13, 2026 00:22
Copy link
Copy Markdown
Member

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

@copilot Pull the latest from main, make the suggested changes, adjust tests accordingly, ensure that all tests pass and all files are formatted correctly. Ensure that only the changes associated with this PR are in the PR diff


Every ARM resource that provides a create operation must also provide a delete operation.

> **See also:** This rule has been superseded by
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.

Let's keep this rule around and not check for this condition in the new rule

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted no-resource-delete-operation.md to its original content and removed the "createOrUpdate must also define delete" check from arm-resource-required-operations — that condition is now solely enforced by no-resource-delete-operation. The proxy-with-PUT-without-delete test is now toBeValid for this rule (2fc6eb9).

Copilot AI and others added 2 commits May 13, 2026 17:44
…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 13, 2026

@copilot Pull the latest from main, make the suggested changes, adjust tests accordingly, ensure that all tests pass and all files are formatted correctly. Ensure that only the changes associated wi...

Merged latest main (clean), removed the PUT-requires-delete check from this rule (deferring to the existing no-resource-delete-operation rule) and reverted that rule's doc to its original form. Updated the relevant test and the rule's doc page. pnpm format clean, ARM tests 324/324, rulesets 3/3, sample snapshots 68/68; PR diff scoped to this rule (2fc6eb9).

Copilot AI requested a review from markcowl May 13, 2026 17:54
Copy link
Copy Markdown
Member

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

Pull the latest from main, create tests validating the suggested changes, make the changes, ensure all tests pass and all files are formatted correctly. Ensure that only changes associated with this PR are in the PR diff.

- "@azure-tools/typespec-azure-rulesets"
---

Add new `arm-resource-required-operations` linting rule that ensures every ARM resource declares the complete set of required lifecycle and list operations (singleton-aware; supersedes `no-resource-delete-operation`).
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.

Suggested change
Add new `arm-resource-required-operations` linting rule that ensures every ARM resource declares the complete set of required lifecycle and list operations (singleton-aware; supersedes `no-resource-delete-operation`).
Add new `arm-resource-required-operations` linting rule that ensures every ARM resource declares the complete set of required lifecycle and list operations (singleton-aware; complements`no-resource-delete-operation`).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied (b6ee6db).

severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-resource-manager/rules/arm-resource-required-operations",
description:
"ARM resources must define their required operations: tracked resources need the full lifecycle and list set, other resources need a read, and any resource defining createOrUpdate must also define delete.",
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.

Suggested change
"ARM resources must define their required operations: tracked resources need the full lifecycle and list set, other resources need a read, and any resource defining createOrUpdate must also define delete.",
"ARM resources must define their required operations: tracked resources need the full lifecycle and list set, other resources need a read operation.",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied (b6ee6db).

// operations) and read kind / singleton / operations directly from the
// returned ResolvedResource entries.
//
// A single declared resource can produce multiple ResolvedResource
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.

A single resource model ,may represent multiple actual resources. We should not group resources this way, and should ensure that the diagnostic locationf or this rule is the interface that contains the resource operations and not the resource itself.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reworked: the rule now iterates each ResolvedResource (no grouping by Model) and targets the @armResourceOperations interface containing the resource's operations. Pure resolver path-doubling artifacts (where a model appears as its own ancestor) are detected and their operations merged into the canonical entry's present-op set so they don't produce spurious duplicate diagnostics (b6ee6db).

Copilot AI and others added 2 commits May 14, 2026 20:53
…rce-required-operations-rule

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
…date description and changelog

Agent-Logs-Url: https://github.com/Azure/typespec-azure/sessions/35057102-f07f-45ec-a141-adc327a4aabf

Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
Copilot AI requested a review from markcowl May 14, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:autorest Issues for @azure-tools/typespec-autorest emitter int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library lib:tcgc Issues for @azure-tools/typespec-client-generator-core library meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants