Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test] contoso.widgetManager&contoso.widgetManager.shared #32814

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions eng/pipelines/templates/stages/archetype-spec-gen-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ parameters:
extends:
template: /eng/pipelines/templates/stages/1es-redirect.yml
parameters:
Use1ESOfficial: false
stages:
- stage: Build
displayName: 'SDK Generation'
jobs:
- job:
timeoutInMinutes: 2400

variables:
- template: /eng/pipelines/templates/variables/image.yml
Expand All @@ -56,12 +58,12 @@ extends:
displayName: Publish SDK artifacts to Pipeline Artifacts
condition: and(ne(variables['ValidationResult'], ''), eq(variables['HasSDKArtifact'], 'true'))
artifactName: $(sdkArtifactName)
targetPath: "$(System.DefaultWorkingDirectory)/out/generatedSdkArtifacts"
targetPath: "$(System.DefaultWorkingDirectory)/out/stagedArtifacts"
- output: pipelineArtifact
displayName: Publish API View artifacts to Pipeline Artifacts
condition: and(ne(variables['ValidationResult'], ''), eq(variables['HasApiViewArtifact'], 'true'))
artifactName: $(ArtifactName)
targetPath: "$(System.DefaultWorkingDirectory)/out/sdkApiViewArtifacts"
targetPath: "$(System.DefaultWorkingDirectory)/out/stagedArtifacts"
- output: pipelineArtifact
displayName: Publish logs to Pipeline Artifacts
condition: ne(variables['ValidationResult'], '')
Expand Down Expand Up @@ -168,7 +170,7 @@ extends:
optional_params=""
sdk_gen_info="sdk generation from Config : "

if [ "${{ parameters.ConfigType }}" = "TypeSpec" ]; then
if [ "$(Build.Reason)" != "PullRequest" ] && [ "${{ parameters.ConfigType }}" = "TypeSpec" ]; then
optional_params="$optional_params --tsp-config-relative-path ${{ parameters.ConfigPath }}"
sdk_gen_info="$sdk_gen_info '${{ parameters.ConfigPath }}',"
elif [ "${{ parameters.ConfigType }}" = "OpenAPI" ]; then
Expand All @@ -177,7 +179,7 @@ extends:
fi

if [ "$(Build.Reason)" = "PullRequest" ]; then
optional_params="$optional_params --pr-number=$(System.PullRequest.PullRequestNumber)"
optional_params="$optional_params --pr-number $(System.PullRequest.PullRequestNumber)"
specPrUrl="${{ parameters.SpecRepoUrl }}/pull/$(System.PullRequest.PullRequestNumber)"
sdk_gen_info="$sdk_gen_info spec PR: $specPrUrl"
fi
Expand Down
Empty file modified eng/tools/spec-gen-sdk-runner/cmd/spec-gen-sdk-runner.js
100644 → 100755
Empty file.
18 changes: 7 additions & 11 deletions eng/tools/spec-gen-sdk-runner/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,23 @@ const config = tseslint.config(
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/consistent-indexed-object-style": "off",
"@typescript-eslint/no-unnecessary-condition": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-dynamic-delete": "off",

// We want more flexibility with file names.
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md
"unicorn/filename-case": "off",
"unicorn/prefer-ternary": "off",
"unicorn/no-useless-undefined": "off",
"unicorn/prevent-abbreviations": "off",

// We prefer to have explicitly import at the top of the file, even if the same element is exported again,
// which we do in index.ts files.
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-export-from.md
"unicorn/prefer-export-from": ["error", { ignoreUsedVariables: true }],

// We allow some abbreviations that we like.
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md
"unicorn/prevent-abbreviations": [
"error",
{
allowList: {
args: true,
},
},
],
},
}
);
Expand Down
184 changes: 184 additions & 0 deletions eng/tools/spec-gen-sdk-runner/src/change-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import path from "node:path";
import {
getChangedFiles,
searchRelatedParentFolders,
searchSharedLibrary,
searchRelatedTypeSpecProjectBySharedLibrary,
groupPathsByService,
createCombinedSpecs,
type SpecResults,
type ChangedSpecs,
getLastPathSegment,
} from "./utils.js";
import { logMessage } from "./log.js";
import { SpecGenSdkCmdInput } from "./types.js";

const readmeMdRegex = /^readme.md$/i;
const typespecProjectRegex = /^tspconfig.yaml$/i;
const typespecProjectSharedLibraryRegex = /[^/]+\.Shared/;

export function detectChangedSpecConfigFiles(commandInput: SpecGenSdkCmdInput): ChangedSpecs[] {
const prChangedFiles: string[] = getChangedFiles(commandInput.localSpecRepoPath) ?? [];
if (prChangedFiles.length === 0) {
logMessage("No files changed in the PR");
}
logMessage(`Changed files in the PR: ${prChangedFiles.length}`);
for (const file of prChangedFiles) {
logMessage(`\t${file}`);
}
const fileList = prChangedFiles
.filter((p) => p.startsWith("specification/"))
.filter((p) => !p.includes("/scenarios/"));

logMessage(`Related readme.md and typespec project list:`);
const changedSpecs: ChangedSpecs[] = [];

const readmeMDResult = searchRelatedParentFolders(fileList, {
searchFileRegex: readmeMdRegex,
specRepoFolder: commandInput.localSpecRepoPath,
stopAtFolder: "specification",
});

const typespecProjectResult = searchRelatedParentFolders(fileList, {
searchFileRegex: typespecProjectRegex,
specRepoFolder: commandInput.localSpecRepoPath,
stopAtFolder: "specification",
});

const typespecProjectSharedLibraries = searchSharedLibrary(fileList, {
searchFileRegex: typespecProjectSharedLibraryRegex,
specRepoFolder: commandInput.localSpecRepoPath,
});

const typespecProjectResultSearchedBySharedLibrary = searchRelatedTypeSpecProjectBySharedLibrary(
typespecProjectSharedLibraries,
{
searchFileRegex: typespecProjectRegex,
specRepoFolder: commandInput.localSpecRepoPath,
},
);

// Merge typespec project results
for (const folderPath of Object.keys(typespecProjectResultSearchedBySharedLibrary)) {
if (typespecProjectResult[folderPath]) {
typespecProjectResult[folderPath] = [
...typespecProjectResult[folderPath],
...typespecProjectResultSearchedBySharedLibrary[folderPath],
];
} else {
typespecProjectResult[folderPath] = typespecProjectResultSearchedBySharedLibrary[folderPath];
}
}

// Group paths by service
const serviceMap = groupPathsByService(readmeMDResult, typespecProjectResult);

const results: SpecResults = { readmeMDResult, typespecProjectResult };

// Process each service
for (const [, info] of serviceMap) {
// Case: Resource Manager with .Management
if (info.managementPaths.length > 0) {
if (info.resourceManagerPaths.length === 1) {
// Single resource-manager path - match with all Management paths
const newSpecs = createCombinedSpecs(
info.resourceManagerPaths[0].path,
info.managementPaths,
results,
);
changedSpecs.push(...newSpecs);
logMessage(
`\t readme folders: ${info.resourceManagerPaths[0].path}, tspconfig folders: ${info.managementPaths}`,
);
for (const p of info.managementPaths) {
delete typespecProjectResult[p];
}
delete readmeMDResult[info.resourceManagerPaths[0].path];
} else {
// Multiple resource-manager paths - match by subfolder name
for (const rmPath of info.resourceManagerPaths) {
const matchingManagements = info.managementPaths.filter((mPath) => {
const rmSubPath = rmPath.subPath;
const managementName = getLastPathSegment(mPath).replace(".Management", "");
return rmSubPath && rmSubPath === managementName;
});
if (matchingManagements.length > 0) {
const newSpecs = createCombinedSpecs(rmPath.path, matchingManagements, results);
changedSpecs.push(...newSpecs);
logMessage(
`\t readme folders: ${rmPath.path}, tspconfig folders: ${matchingManagements}`,
);
for (const p of matchingManagements) {
delete typespecProjectResult[p];
}
delete readmeMDResult[rmPath.path];
}
}
}
}

// Case: Data Plane matching
if (info.dataPlanePaths.length > 0 && info.otherTypeSpecPaths.length > 0) {
if (info.dataPlanePaths.length === 1) {
// Single data-plane path - match with all non-Management TypeSpec paths
const newSpecs = createCombinedSpecs(
info.dataPlanePaths[0].path,
info.otherTypeSpecPaths,
results,
);
changedSpecs.push(...newSpecs);
logMessage(
`\t readme folders: ${info.dataPlanePaths[0].path}, tspconfig folders: ${info.otherTypeSpecPaths}`,
);
for (const p of info.otherTypeSpecPaths) {
delete typespecProjectResult[p];
}
delete readmeMDResult[info.dataPlanePaths[0].path];
} else {
// Multiple data-plane paths - match by subfolder name
for (const dpPath of info.dataPlanePaths) {
const matchingTypeSpecs = info.otherTypeSpecPaths.filter((tsPath) => {
const dpSubFolder = dpPath.subFolder;
const tsLastSegment = getLastPathSegment(tsPath);
return dpSubFolder && dpSubFolder === tsLastSegment;
});
if (matchingTypeSpecs.length > 0) {
const newSpecs = createCombinedSpecs(dpPath.path, matchingTypeSpecs, results);
changedSpecs.push(...newSpecs);
logMessage(
`\t readme folders: ${dpPath.path}, tspconfig folders: ${matchingTypeSpecs}`,
);
for (const p of matchingTypeSpecs) {
delete typespecProjectResult[p];
}
delete readmeMDResult[dpPath.path];
}
}
}
}
}

// Process remaining unmatched paths
for (const folderPath of new Set([
...Object.keys(readmeMDResult),
...Object.keys(typespecProjectResult),
])) {
const cs: ChangedSpecs = {
specs: [],
};

if (typespecProjectResult[folderPath]) {
cs.specs = typespecProjectResult[folderPath];
cs.typespecProject = path.join(folderPath, "tspconfig.yaml");
logMessage(`\t tspconfig: ${cs.typespecProject}`);
} else {
cs.readmeMd = path.join(folderPath, "readme.md");
cs.specs = readmeMDResult[folderPath];
logMessage(`\t readme: ${cs.readmeMd}`);
}

changedSpecs.push(cs);
}

return changedSpecs;
}
Loading
Loading