Skip to content

[Swagger Linter Migration] NonApplicationJsonType - #5302

Open
Yuchao Yan (msyyc) wants to merge 4 commits into
Azure:mainfrom
msyyc:promote-non-application-json-type-to-arm
Open

[Swagger Linter Migration] NonApplicationJsonType#5302
Yuchao Yan (msyyc) wants to merge 4 commits into
Azure:mainfrom
msyyc:promote-non-application-json-type-to-arm

Conversation

@msyyc

@msyyc Yuchao Yan (msyyc) commented Aug 25, 2026

Copy link
Copy Markdown
Member

Original Swagger linter

The original rule is an ARM warning that requires Swagger request and response content types to contain application/json.

The original rule performs these checks:

  • Checks every root-level produces entry.
  • Checks every root-level consumes entry.
  • Checks every operation-level produces entry under paths.
  • Checks every operation-level consumes entry under paths.
  • Checks the same operation-level entries under x-ms-paths.
  • Reports each entry whose value does not match the application/json pattern.

How the Swagger linter works

The Spectral rule traverses $[produces,consumes].* and
$[paths,'x-ms-paths'].*.*[produces,consumes].* with resolved references enabled. It applies
Spectral's pattern function to each individual array entry and reports at that Swagger JSON path
when the string does not contain application/json.

The validator's pattern is a substring match rather than exact media-type equality. The migrated
rule preserves that behavior. Root-level Swagger arrays are emitter-controlled and cannot be
authored independently in current TypeSpec OpenAPI2 output, so the TypeSpec rule checks the
authorable semantic source: resolved request and response bodies. Validator diagnostics are tied to
emitted array occurrences; the promoted rule instead targets authored TypeSpec declarations.

Source TypeSpec lintdiff rule

  • Validator rule ID: NonApplicationJsonType
  • Local lintdiff rule: non-application-json-type
  • Canonical validator slug: non-application-json-type
  • Source branch: feature/lintdiff-non-application-json-type
  • Source commit: 5d6bc319579aeec5fde116dbd2018a5f2f58ac43
  • Source worktree: C:\dev\worktrees\lintdiff-non-application-json-type
  • Uncommitted source-rule changes: none
  • Source rule: packages/typespec-lintdiff/src/rules/non-application-json-type.ts

The source branch was merged by PR #5286. The user-marked done source rule was treated as immutable
and was not modified during promotion.

Destination analysis

The rule belongs in @azure-tools/typespec-azure-resource-manager:

  • its fixture documentation says it applies to ARM;
  • catalog metadata records applicability: ARM and sources: ["arm"];
  • the lintdiff implementation depends on isArmProviderNamespace;
  • its production evidence consists of ARM service projects and ARM operations;
  • no equivalent official ARM or Azure Core rule exists.

Azure Core was considered but rejected because removing ARM provider scoping would broaden the rule
to data-plane APIs and materially change its semantics. The public TypeSpec rule name is shortened
from the validator-derived non-application-json-type to the convention-aligned
use-application-json-content-type.

How the promoted TypeSpec linter works

The promoted rule visits operations in ARM provider namespaces and resolves each operation with
getHttpOperation. It checks the resolved request body and every resolved response body, reporting
once for each content type that does not contain application/json.

Diagnostics target an authored content-type property when available, then an authored body
property. For library-instantiated bodies such as ArmResponse<string>, the rule falls back to the
authored operation so the compiler surfaces the project lint diagnostic. This preserves the source
rule's fix for scalar ARM responses. There is no version-specific projection in the rule itself;
ordinary TypeSpec linting evaluates the program presented by the compiler. The migration evidence
separately attributes corpus results to selected Swagger versions.

The promotion adapts package imports, rule variable and public rule names, documentation metadata,
native tests, linter registration, and ARM ruleset registration. It does not change source
semantics.

Fixture-to-native test mapping

Original lintdiff fixture Native vitest case Coverage note
json-only-content-type/main.tsp it("accepts ARM operations with only application/json content types") Compliant JSON request and response bodies.
non-json-content-type/main.tsp it("reports an explicit non-JSON response content type") Explicit application/octet-stream response.
scalar-response-content-type/main.tsp it("reports an implicit scalar response content type") Library-instantiated scalar response and authored-operation target fallback.
non-json-request-content-type/main.tsp it("reports an explicit non-JSON request content type") Explicit text/plain request.
patch-merge-patch-content-type/main.tsp it("reports application/merge-patch+json request content type") Explicit application/merge-patch+json PATCH request.

These are direct native TypeSpec assertions; validator and OpenAPI snapshots were not copied.

Migration evidence

The checked-in
migration.md
records the focused fixtures, real-service comparison, latest full-corpus counts, selected-version
attribution, compile failures, diagnostic-target regression, and remaining uncertainty.

Validation

  • ARM dependency-closure build
  • Focused native rule test: 5 tests passed
  • ARM package build and lint
  • ARM documentation regeneration
  • Azure rulesets build and tests
  • Full ARM package tests
  • Website dependency build
  • Repository format check and git diff --check
  • Required pre-commit pnpm format and pnpm lint
  • Chronus change validation
  • Two focused promotion reviews; the only finding was a Chronus CRLF parsing issue, which was fixed

Validation blocker

pnpm validate:pr passed its branch-up-to-date check in 3.7 seconds, then produced no additional
progress for more than five minutes. It was stopped after approximately 5 minutes 10 seconds under
the bounded-validation policy. The targeted and broad validations listed above completed
successfully.

Promotion sync policy

If review discovers a semantic gap in the completed lintdiff rule, this promotion must pause until
the user explicitly reopens lintdiff repair. Source-rule changes are not part of this promotion PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@msyyc Yuchao Yan (msyyc) added the int:azure-specs Run integration tests against azure-rest-api-specs label Aug 25, 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 Aug 25, 2026
@github-actions

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 use-application-json-content-type rule to require JSON request and response bodies for ARM operations.

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

Add the use-application-json-content-type rule to require JSON request and response bodies for ARM operations.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

📦 Package size report

1 package changed size, +4.94 KB (+0.0%) packed overall.

Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-ts 532.67 KB → 536.71 KB +4.04 KB (+0.8%) 🔴 2.56 MB → 2.58 MB +17.91 KB (+0.7%) 🔴
12 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-go 259.66 KB → 260.21 KB +564 B (+0.2%) 1.33 MB → 1.33 MB +2.02 KB (+0.1%)
@azure-tools/typespec-client-generator-core 229.25 KB → 229.48 KB +229 B (+0.1%) 1.23 MB → 1.23 MB +937 B (+0.1%)
@azure-tools/typespec-azure-resource-manager 172.83 KB → 172.93 KB +101 B (+0.1%) 1.05 MB → 1.05 MB +664 B (+0.1%)
@azure-tools/azure-http-specs 146.63 KB → 146.71 KB +80 B (+0.1%) 1.16 MB → 1.16 MB +415 B (+0.0%)
@azure-tools/typespec-java 13.51 MB → 13.51 MB -74 B (-0.0%) 15.03 MB → 15.03 MB
@azure-tools/typespec-azure-rulesets 5.16 KB → 5.19 KB +26 B (+0.5%) 32.09 KB → 32.30 KB +218 B (+0.7%)
@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 129.43 KB → 129.43 KB 702.77 KB → 702.77 KB
@azure-tools/typespec-azure-portal-core 42.40 KB → 42.40 KB 192.91 KB → 192.91 KB
@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

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 Aug 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 8b8fca1

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Yuchao Yan (msyyc) and others added 2 commits August 26, 2026 10:08
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: cf125def-85b2-462d-8902-7ac7beb588a3
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