Skip to content

Commit bce66ff

Browse files
authored
[TypeSpec Validation] Add rule to require specifying a linter ruleset (#25804)
1 parent a48dbfd commit bce66ff

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

eng/tools/TypeSpecValidation/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
},
1010
"dependencies": {
1111
"debug": "^4.3.4",
12-
"simple-git": "^3.16.0"
12+
"simple-git": "^3.16.0",
13+
"yaml": "^2.3.2"
1314
},
1415
"devDependencies": {
1516
"globby": "^13.1.1",

eng/tools/TypeSpecValidation/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CompileRule } from "./rules/compile.js";
33
import { FolderStructureRule } from "./rules/folder-structure.js";
44
import { FormatRule } from "./rules/format.js";
55
import { GitDiffRule } from "./rules/git-diff.js";
6+
import { LinterRulesetRule } from "./rules/linter-ruleset.js";
67
import { NpmPrefixRule } from "./rules/npm-prefix.js";
78

89
export async function main() {
@@ -20,6 +21,7 @@ export async function main() {
2021
let rules = [
2122
new FolderStructureRule(),
2223
new NpmPrefixRule(),
24+
new LinterRulesetRule(),
2325
new CompileRule(),
2426
new FormatRule(),
2527
new GitDiffRule(),
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { readFile } from "fs/promises";
2+
import { join } from "path";
3+
import { parse as yamlParse } from "yaml";
4+
import { Rule } from "../rule.js";
5+
import { RuleResult } from "../rule-result.js";
6+
import { checkFileExists } from "../utils.js";
7+
8+
export class LinterRulesetRule implements Rule {
9+
readonly name = "LinterRuleset";
10+
11+
readonly description =
12+
"Ensures each spec includes the correct linter ruleset (data-plane or management-plane)";
13+
14+
async execute(folder: string): Promise<RuleResult> {
15+
let success = true;
16+
let stdOutput = "";
17+
let errorOutput = "";
18+
19+
const configFile = join(folder, "tspconfig.yaml");
20+
const configText = await readFile(configFile, "utf8");
21+
const config = yamlParse(configText);
22+
23+
const rpFolder =
24+
config.options?.["@azure-tools/typespec-autorest"]?.["azure-resource-provider-folder"];
25+
stdOutput += `azure-resource-provider-folder: ${JSON.stringify(rpFolder)}\n`;
26+
27+
const mainTspExists = await checkFileExists(join(folder, "main.tsp"));
28+
const clientTspExists = await checkFileExists(join(folder, "client.tsp"));
29+
let files = [];
30+
if (mainTspExists) {
31+
files.push("main.tsp");
32+
}
33+
if (clientTspExists) {
34+
files.push("client.tsp");
35+
}
36+
stdOutput += `files: ${JSON.stringify(files)}\n`;
37+
38+
const linterExtends = config.linter?.extends;
39+
stdOutput += `linter.extends: ${JSON.stringify(linterExtends)}`;
40+
41+
let requiredRuleset = "";
42+
if (rpFolder?.trim()?.endsWith("resource-manager")) {
43+
requiredRuleset = "@azure-tools/typespec-azure-resource-manager/all";
44+
} else if (rpFolder?.trim()?.endsWith("data-plane")) {
45+
requiredRuleset = "@azure-tools/typespec-azure-core/all";
46+
} else if (clientTspExists && !mainTspExists) {
47+
// Assume folders with no autorest setting, containing only "client.tsp" but no "main.tsp",
48+
// are data-plane (e.g. HealthInsights.TrialMatcher)
49+
requiredRuleset = "@azure-tools/typespec-azure-core/all";
50+
} else {
51+
// Cannot determine if spec is data-plane or resource-manager, so cannot know
52+
// which linter ruleset is required.
53+
success = false;
54+
errorOutput +=
55+
"tspconfig.yaml must define the following property:\n" +
56+
"\n" +
57+
"options:\n" +
58+
' "@azure-tools/typespec-autorest":\n' +
59+
' azure-resource-provider-folder: "data-plane" | "resource-manager"\n';
60+
}
61+
62+
if (requiredRuleset && !linterExtends?.includes(requiredRuleset)) {
63+
success = false;
64+
errorOutput +=
65+
"tspconfig.yaml must define the following property:\n" +
66+
"\n" +
67+
"linter:\n" +
68+
" extends:\n" +
69+
` - "${requiredRuleset}"`;
70+
}
71+
72+
return {
73+
success: success,
74+
stdOutput: stdOutput,
75+
errorOutput: errorOutput,
76+
};
77+
}
78+
}

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)