Skip to content

[Swagger Linter Migration] GetCollectionOnlyHasValueAndNextLink - #5358

Draft
Yuchao Yan (msyyc) wants to merge 1 commit into
Azure:mainfrom
msyyc:promote-lintdiff-get-collection-only-has-value-and-next-link-to-arm
Draft

[Swagger Linter Migration] GetCollectionOnlyHasValueAndNextLink#5358
Yuchao Yan (msyyc) wants to merge 1 commit into
Azure:mainfrom
msyyc:promote-lintdiff-get-collection-only-has-value-and-next-link-to-arm

Conversation

@msyyc

Copy link
Copy Markdown
Member

Original Swagger linter

The original rule performs these checks:

  • Selects resolved properties objects under 200 responses for ARM GET operations in both paths and x-ms-paths.
  • Excludes raw path keys ending in }, operations, or default.
  • Uses the path portion after the provider namespace and treats an even provider-tail segment count as a collection path.
  • Requires exactly two response-envelope properties.
  • Requires those properties to be named value and nextLink.

How the Swagger linter works

The Spectral selector traverses resolved Swagger paths and x-ms-paths, selects each eligible GET operation's responses.200.schema.properties, and passes that object plus its JSON path to the custom function. The function derives the provider tail by splitting a path component containing . and then /; odd tail lengths are treated as point operations and skipped. For collection-shaped tails, it reports when the property map does not contain exactly value and nextLink.

The selector's suffix exclusions run against the raw Swagger path key. Therefore, .../operations and .../default are excluded, while the same paths followed by a query suffix are not. Direct arrays, property-less objects, file responses, and multipart responses have no selected schema.properties node and are skipped. Because Swagger diagnostics are attached to emitted OpenAPI occurrences, one authored TypeSpec declaration can produce several validator diagnostics; this migration intentionally reports semantic TypeSpec targets instead of reproducing emitted-occurrence duplication.

Source TypeSpec lintdiff rule

  • Validator rule ID: GetCollectionOnlyHasValueAndNextLink
  • Local lintdiff rule: get-collection-only-has-value-and-next-link
  • Canonical validator slug: get-collection-only-has-value-and-next-link
  • Source PR: #5310
  • Source branch: feature/lintdiff-get-collection-only-value-next-link at efee405b7e91ad3774d6ec0b9e77fffa53c96e51
  • Inspected source worktree: C:\dev\worktrees\lintdiff-get-collection-only-value-next-link
  • Source lintdiff rule

The inspected source had no uncommitted rule or fixture changes and matched the merged source branch. The user-marked-done lintdiff source was not modified during promotion.

Destination analysis

The rule belongs in @azure-tools/typespec-azure-resource-manager. Its metadata and fixtures are ARM-only, its semantics depend on provider namespace and ARM collection-path conventions, and its implementation needs resolveProviderNamespace. The validation report also infers the resource-manager ruleset.

@azure-tools/typespec-azure-core was considered but rejected: this is not a shared data-plane response-envelope rule, and moving it to core would either introduce an invalid dependency on the ARM library or weaken the ARM-specific provider and path semantics.

How the promoted TypeSpec linter works

The official rule is named collection-response-only-value-and-next-link and listens to semantic operations. It:

  1. Uses resolveProviderNamespace to limit evaluation to ARM provider namespaces.
  2. Uses getHttpOperation to inspect the projected HTTP GET operation and its raw route.
  3. Reproduces the validator's provider-tail parity and raw operations/default suffix behavior.
  4. Finds a single-model 200 response body while skipping direct arrays, property-less models, file responses, and multipart responses that the Swagger selector cannot reach.
  5. Requires exactly the value and nextLink properties.
  6. Targets the first authored extra property, otherwise the response model; when the response model comes from library code, it falls back to the authored operation or interface.

The compiler invokes the rule over the active projection, so no separate version-state traversal is needed. It emits at most one semantic diagnostic per operation rather than duplicating diagnostics for every emitted Swagger occurrence. The rule is registered as available but disabled by default in the ARM ruleset.

Fixture-to-native test mapping

Original lintdiff fixture Native vitest case Coverage note
extra-collection-props it("reports an extra property on a collection response") Reports an authored extra envelope property.
extension-scope-value-only it("reports a value-only response on an extension-scope collection path") Covers provider-tail collection detection and a missing nextLink.
only-value-and-nextlink it("accepts a response containing only value and nextLink") Accepts the required two-property envelope.
array-response-body it("accepts a named array response body") Preserves the missing schema.properties exemption for a named array.
direct-array-response-body it("accepts a direct array response body") Preserves the direct-array exemption.
record-response-body it("accepts a record response body") Preserves the property-less object exemption.
file-response-body it("accepts a file response body") Preserves the Swagger file-schema exemption.
multipart-response-body it("accepts a multipart response body") Preserves the Swagger multipart/string-schema exemption.
terminal-resource-invalid-response it("accepts an invalid collection shape on a point path with a query suffix") Confirms query stripping for provider-tail point classification.
operations-suffix-invalid-response it("accepts an invalid collection shape when the raw path ends with operations") Preserves the raw suffix exclusion.
operations-query-suffix-invalid-response it("reports an invalid collection shape when operations is followed by a query suffix") Preserves the validator's raw-path query behavior.
default-suffix-invalid-response it("accepts an invalid collection shape when the raw path ends with default") Preserves the raw suffix exclusion.
default-query-suffix-invalid-response it("reports an invalid collection shape when default is followed by a query suffix") Preserves the validator's raw-path query behavior.

Migration evidence

The checked-in migration evidence records the focused fixture results, investigated real-service projects, final full-corpus comparison, compile-failure exclusions, emitted-occurrence count differences, and remaining uncertainty.

Validation

  • ARM dependency closure and target package build
  • Native rule test: 13 passed
  • ARM package lint
  • ARM documentation regeneration
  • Azure rulesets build and test: 4 passed
  • Full ARM suite: 382 passed with two unrelated timeout cases; both timeout files passed on focused rerun (29 tests)
  • Focused promotion code review: no findings
  • pnpm validate:pr --skip-build --skip-test: branch, lint, format, spelling, changeset, and diff checks passed
  • Local website build intentionally skipped; the dedicated CI Website job owns full documentation regeneration, Astro checking, and website building

Promotion sync policy

If review finds a semantic gap in the user-marked-done lintdiff source, this promotion must pause until the user explicitly reopens lintdiff repair. Promotion-only adaptations can be fixed here, but the source rule will not be changed implicitly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 38d7d6ce-7d4f-4051-bea2-e30ce2a9ac9b
@msyyc Yuchao Yan (msyyc) added the int:azure-specs Run integration tests against azure-rest-api-specs label Sep 1, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library meta:website TypeSpec.io updates linter Issues related to linter rules labels Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @azure-tools/typespec-azure-resource-manager
  • @azure-tools/typespec-azure-rulesets
Show changes

@azure-tools/typespec-azure-resource-manager - feature ✏️

Add the collection-response-only-value-and-next-link rule for ARM collection GET response envelopes.

@azure-tools/typespec-azure-rulesets - feature ✏️

Register the ARM collection response envelope rule as disabled by default.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

📦 Package size report

✅ No notable package size changes compared to the base branch.

13 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-azure-resource-manager 173.48 KB → 173.60 KB +122 B (+0.1%) 1.05 MB → 1.05 MB +975 B (+0.1%)
@azure-tools/typespec-java 13.51 MB → 13.51 MB -89 B (-0.0%) 15.03 MB → 15.03 MB
@azure-tools/typespec-azure-rulesets 5.19 KB → 5.23 KB +41 B (+0.8%) 32.38 KB → 32.61 KB +240 B (+0.7%)
@azure-tools/azure-http-specs 146.71 KB → 146.71 KB 1.16 MB → 1.16 MB
@azure-tools/typespec-autorest 80.93 KB → 80.93 KB 395.06 KB → 395.06 KB
@azure-tools/typespec-autorest-canonical 7.42 KB → 7.42 KB 26.00 KB → 26.00 KB
@azure-tools/typespec-azure-core 130.84 KB → 130.84 KB 709.84 KB → 709.84 KB
@azure-tools/typespec-azure-portal-core 42.40 KB → 42.40 KB 192.91 KB → 192.91 KB
@azure-tools/typespec-client-generator-core 229.48 KB → 229.48 KB 1.23 MB → 1.23 MB
@azure-tools/typespec-go 260.21 KB → 260.21 KB 1.33 MB → 1.33 MB
@azure-tools/typespec-metadata 15.91 KB → 15.91 KB 62.26 KB → 62.26 KB
@azure-tools/typespec-python 42.22 KB → 42.22 KB 164.91 KB → 164.91 KB
@azure-tools/typespec-ts 536.70 KB → 536.70 KB 2.58 MB → 2.58 MB

Packed = gzipped .tgz published to npm. Unpacked = total extracted size. 🆕 added, 🗑️ removed. Packages from the core/ submodule are not included.
🔴 grew · 🟢 shrank — only changes of at least 512 B and 0.5% are marked.

@pkg-pr-new

pkg-pr-new Bot commented Sep 1, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-azure-resource-manager@5358
npm i https://pkg.pr.new/@azure-tools/typespec-azure-rulesets@5358

commit: 59bb785

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library linter Issues related to linter rules meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant