diff --git a/tools/devops-tasks/ApiCompat/media/extension-icon.png b/tools/devops-tasks/ApiCompat/media/extension-icon.png new file mode 100644 index 0000000000..2808037ea6 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/media/extension-icon.png differ diff --git a/tools/devops-tasks/ApiCompat/readme.md b/tools/devops-tasks/ApiCompat/readme.md new file mode 100644 index 0000000000..2e2d7d7a2c --- /dev/null +++ b/tools/devops-tasks/ApiCompat/readme.md @@ -0,0 +1,78 @@ + +# ApiCompat task + +API Compat tool compares two sets of assemblies and determines if the implementation has incompatibilities with the contract. + +This is an Azure Pipelines encapsulation of the ApiCompat tool. To get the latest version of this tool please visit [dotnet/arcade](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.ApiCompat) repo. + +## Configuration + +### Contracts root folder + +Path to the folder that contains the assemblies to compare *against*. + +### Contracts files name + +Space separated list of the names of the assemblies to compare to. + +### Implementation assemblies folder + +Folder that contains the assemblies that are going to be compared against the contracts. + +### Fails on Issue + +Checking this will cause the build process to fail when ApiCompat finds one or more incompatibilities. Leaving it unchecked will flag the task as *successful with issues*. For Pull Requests we recommend leaving this checked to alert the Pull Request user that his implementations caused incompatibilities. + +### Resolve Fx + +If a contract or implementation dependency cannot be found in the given directories, fallback to try to resolve against the framework directory on the machine. + +### Warn on incorrect version + +Warn if the contract version number doesn't match the found implementation version number. + +### Warn on missing assemblies + +Warn if the contract assembly cannot be found in the implementation directories. Default is to error and not do analysis. + +### Create Comparison Result Log + +If this is checked, a JSON file will be created with the comparison result. + +The JSON will contain two properties: + +- `issues`. This property contains the numeric value of the amount of found issues. +- `body`. This property contains the list of descriptions of the issues given by ApiCompat. + +Checking this will also show two additional input boxes: + +- **Output File Name.** Name and extension of the file to generate. +- **Output File Path.** Path where the generated file will be stored. + +### Use Baseline File + +A baseline file is a file that contains known incompatibilities. This comes useful whenever you want to release a new major version of the assembly, knowing beforehand that the new version will contain breaking incompatibilities. + +The content of this file is simply the same output generated by ApiCompat, either by piping the result to a text file or by using the `--out` parameter. + +Checking this option will display an input field to select a baseline file. This file will be used as `--baseline` parameter to ignore the issues in the file when running the comparison. + +## Basic Example + +If you have a build process for your assemblies, this tool can be very useful to prevent the integration of new changes that will cause incompatibilities with the current released version of your assemblies. + +To do this in your build process, add this task and configure the following fields: + +- **Contracts root folder.** Point this to the latest released version of your assemblies. One way to accomplish this is to use the NuGet task. +- **Contracts files name.** Configure the name of your assembly. If you wish to configure more than one assembly, use *multipliers variables*. +- **Implementation assemblies folder.** Point this field to the binaries produced by the *current build process*. +- **Fails on Issues.** Check this if you wish to prevent incompatibilities. + +For the build trigger configure **Pull request validation**. + +With this configuration, whenever a person opens a Pull Request introducing changes that will break compatibilities with the current released version, the build process will be marked as ***Failed***. + +## More Information + +- [Multi-Configuration](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-configuration). To configure multiple assemblies and versions without having to clone the build. +- [Conditional Tasks](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=yaml). To execute certain agents only if some conditions are met. diff --git a/tools/devops-tasks/ApiCompat/source/.eslintrc.js b/tools/devops-tasks/ApiCompat/source/.eslintrc.js new file mode 100644 index 0000000000..8351833fe9 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + plugins: [ '@typescript-eslint' ], + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + ] +}; \ No newline at end of file diff --git a/tools/devops-tasks/ApiCompat/source/.gitignore b/tools/devops-tasks/ApiCompat/source/.gitignore new file mode 100644 index 0000000000..e80c90642b --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/.gitignore @@ -0,0 +1,4 @@ +node_modules +package-lock.json +lib +!.eslintrc.js \ No newline at end of file diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/McMaster.Extensions.CommandLineUtils.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/McMaster.Extensions.CommandLineUtils.dll new file mode 100644 index 0000000000..8cfd1c9f58 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/McMaster.Extensions.CommandLineUtils.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.Extensions.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.Extensions.dll new file mode 100644 index 0000000000..fe74fde750 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.Extensions.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.dll new file mode 100644 index 0000000000..e16ba62573 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.Cci.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe new file mode 100644 index 0000000000..ffe41e3740 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe.config b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe.config new file mode 100644 index 0000000000..8f60dcb217 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/ApiCompat/Microsoft.DotNet.ApiCompat.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.AttributedModel.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.AttributedModel.dll new file mode 100644 index 0000000000..afcfa1fc9a Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.AttributedModel.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Convention.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Convention.dll new file mode 100644 index 0000000000..b902327d92 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Convention.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Hosting.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Hosting.dll new file mode 100644 index 0000000000..af80e71410 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Hosting.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Runtime.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Runtime.dll new file mode 100644 index 0000000000..730bd01cea Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.Runtime.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.TypedParts.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.TypedParts.dll new file mode 100644 index 0000000000..ab45f8ed27 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.Composition.TypedParts.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/ApiCompat/System.ValueTuple.dll b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.ValueTuple.dll new file mode 100644 index 0000000000..2e81d9c162 Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/ApiCompat/System.ValueTuple.dll differ diff --git a/tools/devops-tasks/ApiCompat/source/icon.png b/tools/devops-tasks/ApiCompat/source/icon.png new file mode 100644 index 0000000000..3e954ccf8d Binary files /dev/null and b/tools/devops-tasks/ApiCompat/source/icon.png differ diff --git a/tools/devops-tasks/ApiCompat/source/icon.svg b/tools/devops-tasks/ApiCompat/source/icon.svg new file mode 100644 index 0000000000..1104b552d2 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/icon.svg @@ -0,0 +1,39 @@ + + + + Artboard Copy + Created with Sketch. + + + + + + + + + + + + + dotnet + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/devops-tasks/ApiCompat/source/package.json b/tools/devops-tasks/ApiCompat/source/package.json new file mode 100644 index 0000000000..79630983d5 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/package.json @@ -0,0 +1,25 @@ +{ + "name": "source", + "version": "1.0.0", + "description": "", + "main": "./lib/index.js", + "scripts": { + "prebuild": "npm run lint", + "build": "tsc --p tsconfig.json", + "lint": "eslint ./src/**/*.ts", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "azure-pipelines-task-lib": "^2.7.7" + }, + "devDependencies": { + "@types/node": "^11.9.4", + "@types/q": "^1.5.1", + "eslint": "^5.16.0", + "@typescript-eslint/parser": "^1.6.0", + "@typescript-eslint/eslint-plugin": "^1.6.0", + "typescript": "^3.4.3" + } +} diff --git a/tools/devops-tasks/ApiCompat/source/src/apiCompat.ts b/tools/devops-tasks/ApiCompat/source/src/apiCompat.ts new file mode 100644 index 0000000000..dd37991799 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/src/apiCompat.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { join } from 'path' +import { execSync } from "child_process"; + +export class ApiCompat { + private apiCompatPath: string; + + public constructor() { + this.apiCompatPath = join(__dirname, '..', 'ApiCompat', 'Microsoft.DotNet.ApiCompat.exe'); + } + + public getVersion = (): string => { + return this.runCommand('--version').toString(); + } + + public compare = (contracts: string, implementation: string, optionalParameters?: string): string => { + const options = optionalParameters != undefined ? optionalParameters : ''; + const command = `"${ contracts }" --impl-dirs "${ implementation }" ${ options }`; + return this.runCommand(command); + } + + private runCommand = (command: string): string => { + return execSync(`"${this.apiCompatPath}" ` + command).toString(); + } +} diff --git a/tools/devops-tasks/ApiCompat/source/src/configuration.ts b/tools/devops-tasks/ApiCompat/source/src/configuration.ts new file mode 100644 index 0000000000..2285a844a5 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/src/configuration.ts @@ -0,0 +1,70 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { join } from 'path' +import { getInput, getBoolInput } from "azure-pipelines-task-lib"; +import { existsSync } from 'fs'; + +export class Configuration { + public contractsFolder: string; + public contract: string; + public contractList: string; + public implementationFolder: string; + public failOnIssue: boolean; + public resolveFx: boolean; + public warnOnIncorrectVersion: boolean; + public warnOnMissingAssemblies: boolean; + public generateLog: boolean; + public outputFileName: string; + public outputFolder: string; + public useBaseline: boolean; + public baselineFile: string = ''; + + public constructor() { + this.contractsFolder = this.validatePath('contractsRootFolder'); + this.contract = getInput('contractsFileName'); + this.contractList = this.getContractsName(); + this.implementationFolder = this.validatePath('implFolder'); + this.failOnIssue = getBoolInput('failOnIssue'); + this.resolveFx = getBoolInput('resolveFx'); + this.warnOnIncorrectVersion = getBoolInput('warnOnIncorrectVersion'); + this.warnOnMissingAssemblies = getBoolInput('warnOnMissingAssemblies'); + this.generateLog = getBoolInput('generateLog'); + this.outputFileName = getInput('outputFilename'); + this.outputFolder = getInput('outputFolder'); + + this.useBaseline = getBoolInput('useBaseline'); + if (this.useBaseline) { + this.baselineFile = this.validatePath('baselineFile'); + } + } + + private validatePath = (inputName: string): string => { + const path = getInput(inputName); + + if (!existsSync(path)) { + throw new Error(`The file or directory "${ path }" specified in "${ inputName }" does not exist.`); + } + + return path; + } + + private getContractsName = (): string => { + const filesName: string[] = []; + + getInput('contractsFileName').split(' ').forEach(file => { + const fullFilePath: string = join(this.validatePath('contractsRootFolder'), file); + if (existsSync(fullFilePath)) { + filesName.push(fullFilePath); + } + }); + + if (filesName.length == 0) { + throw new Error('The specified contracts were not found.'); + } + + return filesName.join(','); + } +} diff --git a/tools/devops-tasks/ApiCompat/source/src/index.ts b/tools/devops-tasks/ApiCompat/source/src/index.ts new file mode 100644 index 0000000000..81f4337adc --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/src/index.ts @@ -0,0 +1,70 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { setResult, TaskResult } from 'azure-pipelines-task-lib'; +import { ApiCompat } from './ApiCompat' +import { Configuration } from './Configuration' +import { Result } from './Result'; +import { existsSync, writeFileSync, mkdirSync } from 'fs'; +import { EOL } from 'os'; +import { join } from 'path' + +const getOptionalParameters = (configuration: Configuration): string => { + let command = configuration.resolveFx ? ' --resolve-fx' : ''; + command += configuration.warnOnIncorrectVersion ? ' --warn-on-incorrect-version' : ''; + command += configuration.warnOnMissingAssemblies ? ' --warn-on-missing-assemblies' : ''; + command += configuration.useBaseline ? ` --baseline "${ configuration.baselineFile }"` : ''; + + return command; +} + +const resultText = (result: Result): string => { + return result.issuesCount != 0 + ? `There were ${ result.issuesCount } differences between the assemblies` + : 'No differences were found between the assemblies'; +} + +const writeResult = (result: Result, configuration: Configuration): void => { + const fileName: string = configuration.outputFileName; + const directory: string = configuration.outputFolder; + + const resultText: string = result.issuesCount === 0 + ? `:heavy_check_mark: No Binary Compatibility issues for **${ configuration.contract }**` + : result.getFormattedResult() + + if (!existsSync(directory)) { + mkdirSync(directory, { recursive: true }); + } + + writeFileSync(`${join(directory, fileName)}`, resultText ); +} + +const run = (): void => { + try { + const apiCompat: ApiCompat = new ApiCompat(); + const configuration: Configuration = new Configuration(); + + console.log(apiCompat.getVersion()); + + const optionalParameters = getOptionalParameters(configuration); + const comparisonResult = apiCompat.compare( + configuration.contractList, + configuration.implementationFolder, + optionalParameters); + const result: Result = new Result(comparisonResult); + + console.log(comparisonResult.concat(EOL)); + + if (configuration.generateLog) { + writeResult(result, configuration); + } + + setResult(result.checkResult(configuration), resultText(result)); + } catch (error) { + setResult(TaskResult.Failed, error); + } +} + +run(); diff --git a/tools/devops-tasks/ApiCompat/source/src/result.ts b/tools/devops-tasks/ApiCompat/source/src/result.ts new file mode 100644 index 0000000000..f161130376 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/src/result.ts @@ -0,0 +1,45 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { EOL } from 'os'; +import { Configuration } from './Configuration'; +import { TaskResult } from "azure-pipelines-task-lib"; + +export class Result { + public assemblyName: string; + public issues: string; + public issuesCount: number; + + public constructor(result: string) { + let resultLines: string[] = result.split(EOL); + this.assemblyName = this.getAssemblyName(resultLines[0]); + resultLines = resultLines.slice(1, -2); + this.issues = resultLines.join(EOL); + this.issuesCount = resultLines.length; + } + + public checkResult = (configuration: Configuration): TaskResult => { + if (this.issuesCount === 0) { + return TaskResult.Succeeded; + } else if (configuration.failOnIssue) { + return TaskResult.Failed; + } else { + return TaskResult.SucceededWithIssues; + } + } + + public getFormattedResult = (): string => { + const icon: string = this.issuesCount == 0 ? ':heavy_check_mark:' : ':x:'; + const codeFence = '```'; + const title = `${ icon } ${ this.issuesCount } Binary Compatibility issues for **${ this.assemblyName }**`; + const body = `
${ EOL + EOL + codeFence + EOL + this.issues + EOL + codeFence + EOL + EOL }
${ EOL }`; + + return (title.concat(EOL).concat(body)); + } + + private getAssemblyName = (line: string): string => { + return line.replace('Compat issues with assembly ', '').replace(':', ''); + } +} diff --git a/tools/devops-tasks/ApiCompat/source/task.json b/tools/devops-tasks/ApiCompat/source/task.json new file mode 100644 index 0000000000..57d020fbd8 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/task.json @@ -0,0 +1,111 @@ +{ + "id": "497d08a2-f608-45a0-b442-93d150ee8261", + "name": "binaries-comparer", + "friendlyName": "Binaries Comparer", + "description": "Binaries Comparer", + "helpMarkDown": "", + "category": "Utility", + "author": "Microsoft", + "version": { + "Major": 0, + "Minor": 2, + "Patch": 2 + }, + "instanceNameFormat": "Compare Binaries", + "inputs": [ + { + "name": "contractsRootFolder", + "type": "filepath", + "label": "Contracts root folder", + "required": true, + "helpMarkDown": "Path to the folder that contains the input binaries" + }, + { + "name": "contractsFileName", + "type": "text", + "label": "Contracts files name", + "required": true, + "helpMarkDown": "List of the names of the binaries to compare, separated by space" + }, + { + "name": "implFolder", + "type": "filepath", + "label": "Implementation assemblies folder", + "required": true, + "helpMarkDown": "Sub directory inside the package folder where the binary can be found" + }, + { + "name": "failOnIssue", + "type": "boolean", + "label": "Fails on Issues", + "required": true, + "helpMarkDown": "If issues are found when comparing, the task will fail" + }, + { + "name": "resolveFx", + "type": "boolean", + "label": "Resolve Fx", + "required": true, + "helpMarkDown": "If a contract or implementation dependency cannot be found in the given directories, fallback to try to resolve against the framework directory on the machine" + }, + { + "name": "warnOnIncorrectVersion", + "type": "boolean", + "label": "Warn on incorrect version", + "required": true, + "defaultValue": false, + "helpMarkDown": "Warn if the contract version number doesn't match the found implementation version number" + }, + { + "name": "warnOnMissingAssemblies", + "type": "boolean", + "label": "Warn on missing assemblies", + "required": true, + "defaultValue": false, + "helpMarkDown": "Warn if the contract assembly cannot be found in the implementation directories. Default is to error and not do anlysis" + }, + { + "name": "generateLog", + "type": "boolean", + "label": "Create Comparison result log", + "required": true, + "helpMarkDown": "If selected, a log will be created with the result of the comparisson" + }, + { + "name": "outputFilename", + "type": "text", + "label": "Output file name", + "required": true, + "helpMarkDown": "Path to the folder that will contain the output files", + "visibleRule": "generateLog = TRUE" + }, + { + "name": "outputFolder", + "type": "filepath", + "label": "Output file path", + "required": true, + "helpMarkDown": "Path to the folder that will contain the output files", + "visibleRule": "generateLog = TRUE" + }, + { + "name": "useBaseline", + "type": "boolean", + "label": "Use baseline file", + "required": true, + "helpMarkDown": "Allows the use of a file with known differences to ignore when comparing" + }, + { + "name": "baselineFile", + "type": "filepath", + "label": "Baseline file path", + "required": true, + "helpMarkDown": "Path to the baseline file", + "visibleRule": "useBaseline = TRUE" + } + ], + "execution": { + "Node": { + "target": "./lib/index.js" + } + } +} diff --git a/tools/devops-tasks/ApiCompat/source/tsconfig.json b/tools/devops-tasks/ApiCompat/source/tsconfig.json new file mode 100644 index 0000000000..495fcd6acd --- /dev/null +++ b/tools/devops-tasks/ApiCompat/source/tsconfig.json @@ -0,0 +1,60 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./lib", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + } +} diff --git a/tools/devops-tasks/ApiCompat/vss-extension.json b/tools/devops-tasks/ApiCompat/vss-extension.json new file mode 100644 index 0000000000..ced6798831 --- /dev/null +++ b/tools/devops-tasks/ApiCompat/vss-extension.json @@ -0,0 +1,56 @@ +{ + "manifestVersion": 1, + "id": "binaries-comparer", + "name": "Binaries Comparer", + "version": "0.2.2", + "publisher": "Microsoft", + "targets": [ + { + "id": "Microsoft.VisualStudio.Services" + } + ], + "description": "Compares binaries to test incompatibilities", + "categories": [ + "Azure Pipelines" + ], + "icons": { + "default": "media/extension-icon.png" + }, + "content": { + "details": { + "path": "readme.md" + } + }, + "links": { + "repository": { + "uri": "https://github.com/microsoft/botframework-sdk/tree/main/tools/devops-tasks/ApiCompat" + }, + "issues": { + "uri": "https://github.com/microsoft/botframework-sdk/issues" + } + }, + "repository": { + "type": "git", + "uri": "https://github.com/microsoft/botframework-sdk/tree/main/tools/devops-tasks/ApiCompat" + }, + "files": [ + { + "path": "source" + } + ], + "contributions": [ + { + "id": "custom-build-release-task", + "type": "ms.vss-distributed-task.task", + "targets": [ + "ms.vss-distributed-task.tasks" + ], + "properties": { + "name": "source" + } + } + ], + "galleryFlags": [ + "Public" + ] +}