Skip to content

Commit 47531a4

Browse files
authored
Merge branch 'main' into archidda-web-Microsoft.Web/aigatewaysrt
2 parents abe3ffd + 2490235 commit 47531a4

File tree

1,915 files changed

+198204
-39583
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,915 files changed

+198204
-39583
lines changed

eng/common/scripts/login-to-github.ps1

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,17 @@ function New-GitHubAppJwt {
5757
[Parameter(Mandatory)] [string] $AppId
5858
)
5959

60-
function Base64UrlEncode($json) {
61-
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
62-
$base64 = [Convert]::ToBase64String($bytes)
60+
function Base64UrlEncode {
61+
param(
62+
[string]$Data,
63+
[switch]$IsBase64String
64+
)
65+
if ($IsBase64String) {
66+
$base64 = $Data
67+
} else {
68+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($Data)
69+
$base64 = [Convert]::ToBase64String($bytes)
70+
}
6371
return $base64.TrimEnd('=') -replace '\+', '-' -replace '/', '_'
6472
}
6573

@@ -70,7 +78,7 @@ function New-GitHubAppJwt {
7078
}
7179
$Now = [int][double]::Parse((Get-Date -UFormat %s))
7280
$Payload = @{
73-
iat = $Now
81+
iat = $Now - 10 # 10 seconds clock skew
7482
exp = $Now + 600 # 10 minutes
7583
iss = $AppId
7684
}
@@ -97,7 +105,7 @@ function New-GitHubAppJwt {
97105
throw "Azure Key Vault response does not contain a signature. Response: $($SignResultJson | ConvertTo-Json -Compress)"
98106
}
99107

100-
$Signature = $SignResultJson.signature
108+
$Signature = Base64UrlEncode -Data $SignResultJson.signature -IsBase64String
101109
return "$UnsignedToken.$Signature"
102110
}
103111

eng/tools/typespec-migration-validation/src/compare.ts

Lines changed: 200 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { HttpMethod, OpenAPI2Document, OpenAPI2Operation, OpenAPI2Response, OpenAPI2Schema, OpenAPI2SchemaProperty, Ref, Refable } from "@azure-tools/typespec-autorest";
1+
import { HttpMethod, OpenAPI2Document, OpenAPI2Operation, OpenAPI2Parameter, OpenAPI2Response, OpenAPI2Schema, OpenAPI2SchemaProperty, Ref, Refable } from "@azure-tools/typespec-autorest";
22
import { getCommonTypeDefinition } from "./commonType.js";
3+
import { getOriginalParameter } from "./parameter.js";
34

45
interface Diff {
56
before: any;
@@ -10,17 +11,21 @@ interface Diff {
1011
/**
1112
* path: path for the same operationId should be the same
1213
* parameters: parameters for the same operationId should have the same count
14+
* parameter: individual parameter comparison (name, type, location, required, schema)
1315
* pageable: whether the operation is pageable or not for the same operationId should be the same
1416
* longrunning: whether the operation is long-running or not for the same operationId should be the same
1517
* finalstate: whether the final state of the long-running operation is the same for the same operationId
1618
* finalresult: the final result schema of the long-running operation should be the same as the schema of 200 response
1719
* responses: the response codes for the same operationId should have the same count and same response code
1820
* response: the response schema for the same response code should be the same
1921
* tags: the tags for the same operationId should be the same
22+
* summary: the summary for the same operationId should be the same
2023
*/
2124
interface PathDiff extends Diff {
2225
operationId: string;
23-
type: "path" | "parameters" | "pageable" | "longrunning" | "finalstate" | "finalresult" | "responses" | "response" | "tags";
26+
type: "path" | "parameters" | "parameter" | "pageable" | "longrunning" | "finalstate" | "finalresult" | "responses" | "response" | "tags" | "summary" | "operationId" | "externalDocs";
27+
parameterName?: string;
28+
changeType?: string;
2429
}
2530

2631
/**
@@ -45,10 +50,14 @@ export function printDiff(diff: PathDiff | DefinitionDiff): string {
4550

4651
function getPathDiffMessage(diff: PathDiff): string {
4752
switch (diff.type) {
53+
case "operationId":
54+
return `The operationId "${diff.operationId}" is missing in ${diff.after === null ? "new" : "old"} document:`;
4855
case "path":
4956
return `The path for operation "${diff.operationId}" changed:`;
5057
case "parameters":
5158
return `The number of parameters for operation "${diff.operationId}" changed:`;
59+
case "parameter":
60+
return `The ${diff.changeType} of parameter "${diff.parameterName}" for operation "${diff.operationId}" changed:`;
5261
case "pageable":
5362
return `The pageable for operation "${diff.operationId}" changed:`;
5463
case "longrunning":
@@ -63,6 +72,10 @@ function getPathDiffMessage(diff: PathDiff): string {
6372
return `The response schema for operation "${diff.operationId}" changed:`;
6473
case "tags":
6574
return `The tags for operation "${diff.operationId}" changed:`;
75+
case "summary":
76+
return `The summary for operation "${diff.operationId}" changed:`;
77+
case "externalDocs":
78+
return `The external docs for operation "${diff.operationId}" changed:`;
6679
default:
6780
return `The ${diff.type} for operation "${diff.operationId}" changed:`;
6881
}
@@ -187,26 +200,43 @@ function compareNamedDefinition(oldDefinition: OpenAPI2Schema, oldDocument: Open
187200
}
188201

189202
function compareDefinitionProperty(oldProperty: OpenAPI2SchemaProperty, newProperty: OpenAPI2SchemaProperty, oldDocument: OpenAPI2Document, newDocument: OpenAPI2Document, propertyName: string, modelName: string): DefinitionDiff[] {
203+
const diffs: DefinitionDiff[] = [];
204+
205+
// Compare x-ms-client-flatten
206+
const oldFlatten = (oldProperty as any)["x-ms-client-flatten"] ?? false;
207+
const newFlatten = (newProperty as any)["x-ms-client-flatten"] ?? false;
208+
if (oldFlatten !== newFlatten) {
209+
diffs.push({
210+
before: oldFlatten,
211+
after: newFlatten,
212+
name: modelName,
213+
propertyName,
214+
type: "property",
215+
changeType: "x-ms-client-flatten",
216+
level: "error"
217+
});
218+
}
219+
190220
const oldPropertySchema = resolveCommonType(oldProperty);
191221
const newPropertySchema = resolveCommonType(newProperty);
192222
if (isRef(oldPropertySchema) && isRef(newPropertySchema)) {
193223
if (oldPropertySchema.$ref !== newPropertySchema.$ref) {
194-
return [{
224+
diffs.push({
195225
before: oldPropertySchema.$ref,
196226
after: newPropertySchema.$ref,
197227
name: modelName,
198228
propertyName,
199229
type: "property",
200230
changeType: "reference",
201231
level: "warning"
202-
}];
232+
});
203233
}
204234
}
205235
else if (!isRef(oldPropertySchema) && !isRef(newPropertySchema)) {
206-
return compareNamedDefinition(oldPropertySchema, oldDocument, newPropertySchema, newDocument, `${modelName}.${propertyName}`);
236+
diffs.push(...compareNamedDefinition(oldPropertySchema, oldDocument, newPropertySchema, newDocument, `${modelName}.${propertyName}`));
207237
}
208238

209-
return [];
239+
return diffs;
210240
}
211241

212242
function comparePaths(oldDocument: OpenAPI2Document, newDocument: OpenAPI2Document): PathDiff[] {
@@ -217,53 +247,155 @@ function comparePaths(oldDocument: OpenAPI2Document, newDocument: OpenAPI2Docume
217247
for (const operationId in oldOperations) {
218248
if (!newOperations[operationId]) {
219249
pathDiffs.push({
220-
before: oldOperations[operationId][0],
250+
before: operationId,
221251
after: null,
222252
operationId,
223-
type: "path",
253+
type: "operationId",
224254
level: "error"
225255
});
226256
}
227257
else {
228-
pathDiffs.push(...compareOperation(oldOperations[operationId][1], newOperations[operationId][1], operationId));
258+
if (oldOperations[operationId][0] !== newOperations[operationId][0]) {
259+
pathDiffs.push({
260+
before: oldOperations[operationId][0],
261+
after: newOperations[operationId][0],
262+
operationId,
263+
type: "path",
264+
level: "error"
265+
});
266+
}
267+
pathDiffs.push(...compareOperation(oldOperations[operationId][1], newOperations[operationId][1], operationId, oldDocument, newDocument));
229268
}
230269
}
231270
for (const operationId in newOperations) {
232271
if (!oldOperations[operationId]) {
233272
pathDiffs.push({
234273
before: null,
235-
after: newOperations[operationId][0],
274+
after: operationId,
236275
operationId,
237-
type: "path",
276+
type: "operationId",
238277
level: "error"
239278
});
240279
}
241280
}
242281
return pathDiffs;
243282
}
244283

245-
function compareOperation(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string): PathDiff[] {
284+
function compareOperation(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string, oldDocument: OpenAPI2Document, newDocument: OpenAPI2Document): PathDiff[] {
246285
const pathDiffs: PathDiff[] = [];
247286

248-
if (oldOperation.parameters.length !== newOperation.parameters.length) {
287+
if (oldOperation.parameters?.length !== newOperation.parameters?.length) {
249288
pathDiffs.push({
250-
before: oldOperation.parameters.length,
251-
after: newOperation.parameters.length,
289+
before: oldOperation.parameters?.length,
290+
after: newOperation.parameters?.length,
252291
operationId: operationId,
253292
type: "parameters",
254293
level: "error"
255294
});
256295
}
257296

258297
pathDiffs.push(...compareTags(oldOperation, newOperation, operationId));
298+
pathDiffs.push(...compareSummary(oldOperation, newOperation, operationId));
299+
pathDiffs.push(...compareExternalDocs(oldOperation, newOperation, operationId));
259300
pathDiffs.push(...comparePagination(oldOperation, newOperation, operationId));
260301
pathDiffs.push(...compareLongRunning(oldOperation, newOperation, operationId));
261302
pathDiffs.push(...compareResponses(oldOperation, newOperation, operationId));
303+
pathDiffs.push(...compareBodyParameter(oldOperation, newOperation, operationId, oldDocument, newDocument));
262304

263-
// TO-DO: Compare parameters in detail
264305
return pathDiffs;
265306
}
266307

308+
function compareBodyParameter(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string, oldDocument: OpenAPI2Document, newDocument: OpenAPI2Document): PathDiff[] {
309+
const pathDiffs: PathDiff[] = [];
310+
311+
const oldBodyParam = getBodyParameter(oldOperation, oldDocument);
312+
const newBodyParam = getBodyParameter(newOperation, newDocument);
313+
314+
// Check if body parameter presence changed
315+
if ((oldBodyParam === undefined) !== (newBodyParam === undefined)) {
316+
pathDiffs.push({
317+
before: oldBodyParam ? "present" : "absent",
318+
after: newBodyParam ? "present" : "absent",
319+
operationId,
320+
type: "parameter",
321+
parameterName: "body",
322+
changeType: "presence",
323+
level: "error"
324+
});
325+
return pathDiffs;
326+
}
327+
328+
// If neither has a body parameter, no diff
329+
if (!oldBodyParam || !newBodyParam) {
330+
return pathDiffs;
331+
}
332+
333+
// Compare required status
334+
if ((oldBodyParam.required ?? false) !== (newBodyParam.required ?? false)) {
335+
pathDiffs.push({
336+
before: oldBodyParam.required ?? false,
337+
after: newBodyParam.required ?? false,
338+
operationId,
339+
type: "parameter",
340+
parameterName: "body",
341+
changeType: "required",
342+
level: "error"
343+
});
344+
}
345+
346+
// Compare schema references
347+
const oldSchema = (oldBodyParam as any).schema;
348+
const newSchema = (newBodyParam as any).schema;
349+
350+
if (oldSchema && newSchema) {
351+
const oldSchemaRef = isRef(oldSchema) ? oldSchema.$ref : undefined;
352+
const newSchemaRef = isRef(newSchema) ? newSchema.$ref : undefined;
353+
354+
if (oldSchemaRef && newSchemaRef) {
355+
const oldSchemaName = oldSchemaRef.split("/").pop();
356+
const newSchemaName = newSchemaRef.split("/").pop();
357+
358+
if (oldSchemaName !== newSchemaName) {
359+
pathDiffs.push({
360+
before: oldSchemaName,
361+
after: newSchemaName,
362+
operationId,
363+
type: "parameter",
364+
parameterName: "body",
365+
changeType: "schema",
366+
level: "error"
367+
});
368+
}
369+
} else if (oldSchemaRef !== newSchemaRef) {
370+
pathDiffs.push({
371+
before: oldSchemaRef ?? "inline schema",
372+
after: newSchemaRef ?? "inline schema",
373+
operationId,
374+
type: "parameter",
375+
parameterName: "body",
376+
changeType: "schema",
377+
level: "warning"
378+
});
379+
}
380+
}
381+
382+
return pathDiffs;
383+
}
384+
385+
function getBodyParameter(operation: OpenAPI2Operation, document: OpenAPI2Document): OpenAPI2Parameter | undefined {
386+
for (const param of operation.parameters ?? []) {
387+
if (isRef(param)) {
388+
const resolvedParam = getOriginalParameter(param.$ref, document);
389+
if (resolvedParam && resolvedParam.in === "body") {
390+
return resolvedParam;
391+
}
392+
} else if (param.in === "body") {
393+
return param;
394+
}
395+
}
396+
return undefined;
397+
}
398+
267399
function compareTags(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string): PathDiff[] {
268400
const oldTags = oldOperation.tags || [];
269401
const newTags = newOperation.tags || [];
@@ -284,6 +416,58 @@ function compareTags(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Oper
284416
return [];
285417
}
286418

419+
function compareSummary(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string): PathDiff[] {
420+
const oldSummary = oldOperation.summary ?? "";
421+
const newSummary = newOperation.summary ?? "";
422+
423+
if (oldSummary !== newSummary) {
424+
return [{
425+
before: oldSummary,
426+
after: newSummary,
427+
operationId: operationId,
428+
type: "summary",
429+
level: "error"
430+
}];
431+
}
432+
433+
return [];
434+
}
435+
436+
function compareExternalDocs(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string): PathDiff[] {
437+
const oldExternalDocs = oldOperation.externalDocs;
438+
const newExternalDocs = newOperation.externalDocs;
439+
440+
// Both undefined - no diff
441+
if (!oldExternalDocs && !newExternalDocs) {
442+
return [];
443+
}
444+
445+
// One is undefined, the other is not
446+
if ((!oldExternalDocs && newExternalDocs) || (oldExternalDocs && !newExternalDocs)) {
447+
return [{
448+
before: oldExternalDocs ?? null,
449+
after: newExternalDocs ?? null,
450+
operationId,
451+
type: "externalDocs",
452+
level: "error"
453+
}];
454+
}
455+
456+
// Compare url and description
457+
if (oldExternalDocs!.url !== newExternalDocs!.url ||
458+
oldExternalDocs!.description !== newExternalDocs!.description) {
459+
return [{
460+
before: oldExternalDocs,
461+
after: newExternalDocs,
462+
operationId,
463+
type: "externalDocs",
464+
level: "error"
465+
}];
466+
}
467+
468+
return [];
469+
}
470+
287471
function compareResponses(oldOperation: OpenAPI2Operation, newOperation: OpenAPI2Operation, operationId: string): PathDiff[] {
288472
const pathDiffs: PathDiff[] = [];
289473

eng/tools/typespec-migration-validation/src/document.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ export function processDocument(document: OpenAPI2Document): OpenAPI2Document {
4444
if (document.securityDefinitions) {
4545
delete newDocument.securityDefinitions;
4646
}
47+
if (document.tags) {
48+
delete newDocument.tags;
49+
}
4750
if (document.info && document.info["x-typespec-generated"]) {
4851
delete newDocument.info["x-typespec-generated"];
4952
}

0 commit comments

Comments
 (0)