added prettier tool

This commit is contained in:
Artur Stolear
2020-03-10 11:42:51 +02:00
parent 5c4fb6ec6b
commit 2690f37786
32 changed files with 930 additions and 902 deletions

View File

@@ -1,68 +1,76 @@
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import * as http from "typed-rest-client/HttpClient";
import * as fs from 'fs'
import * as os from 'os'
import * as path from 'path'
import * as http from 'typed-rest-client/HttpClient'
import { inject, injectable } from "inversify";
import { TYPES, IExecResult, IBuildAgent } from "./models";
import { IVersionManager } from "./versionManager";
import {inject, injectable} from 'inversify'
import {TYPES, IExecResult, IBuildAgent} from './models'
import {IVersionManager} from './versionManager'
export interface IDotnetTool {
disableTelemetry(): void;
toolInstall(toolName: string, versionSpec: string, checkLatest: boolean, includePre: boolean): Promise<string>;
disableTelemetry(): void
toolInstall(
toolName: string,
versionSpec: string,
checkLatest: boolean,
includePre: boolean
): Promise<string>
}
@injectable()
export class DotnetTool implements IDotnetTool {
protected buildAgent: IBuildAgent;
protected versionManager: IVersionManager;
private httpClient: http.HttpClient;
protected buildAgent: IBuildAgent
protected versionManager: IVersionManager
private httpClient: http.HttpClient
constructor(
@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent,
@inject(TYPES.IVersionManager) versionManager: IVersionManager,
@inject(TYPES.IVersionManager) versionManager: IVersionManager
) {
this.buildAgent = buildAgent;
this.versionManager = versionManager;
this.httpClient = new http.HttpClient("dotnet");
this.buildAgent = buildAgent
this.versionManager = versionManager
this.httpClient = new http.HttpClient('dotnet')
}
public disableTelemetry(): void {
this.buildAgent.exportVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
this.buildAgent.exportVariable('DOTNET_CLI_TELEMETRY_OPTOUT', '1')
}
public execute(cmd: string, args: string[]): Promise<IExecResult> {
console.log(`Command: ${cmd} ${args.join(' ')}`);
return this.buildAgent.exec(cmd, args);
console.log(`Command: ${cmd} ${args.join(' ')}`)
return this.buildAgent.exec(cmd, args)
}
public async toolInstall(toolName: string, versionSpec: string, checkLatest: boolean, includePre: boolean)
: Promise<string> {
console.log("");
console.log("--------------------------");
console.log(`Installing ${toolName} version ` + versionSpec);
console.log("--------------------------");
public async toolInstall(
toolName: string,
versionSpec: string,
checkLatest: boolean,
includePre: boolean
): Promise<string> {
console.log('')
console.log('--------------------------')
console.log(`Installing ${toolName} version ` + versionSpec)
console.log('--------------------------')
if (this.versionManager.isExplicitVersion(versionSpec)) {
checkLatest = false; // check latest doesn't make sense when explicit version
checkLatest = false // check latest doesn't make sense when explicit version
}
let toolPath: string;
let toolPath: string
if (!checkLatest) {
//
// Let's try and resolve the version spec locally first
//
toolPath = this.buildAgent.find(toolName, versionSpec);
toolPath = this.buildAgent.find(toolName, versionSpec)
}
if (!toolPath) {
let version: string;
let version: string
if (this.versionManager.isExplicitVersion(versionSpec)) {
//
// Explicit version was specified. No need to query for list of versions.
//
version = versionSpec;
version = versionSpec
} else {
//
// Let's query and resolve the latest version for the versionSpec.
@@ -70,21 +78,27 @@ export class DotnetTool implements IDotnetTool {
// If your tool doesn't offer a mechanism to query,
// then it can only support exact version inputs.
//
version = await this.queryLatestMatch(toolName, versionSpec, includePre);
version = await this.queryLatestMatch(
toolName,
versionSpec,
includePre
)
if (!version) {
throw new Error(`Unable to find ${toolName} version '${versionSpec}'.`);
throw new Error(
`Unable to find ${toolName} version '${versionSpec}'.`
)
}
//
// Check the cache for the resolved version.
//
toolPath = this.buildAgent.find(toolName, version);
toolPath = this.buildAgent.find(toolName, version)
}
if (!toolPath) {
//
// Download, extract, cache
//
toolPath = await this.acquireTool(toolName, version);
toolPath = await this.acquireTool(toolName, version)
}
}
@@ -92,62 +106,79 @@ export class DotnetTool implements IDotnetTool {
// Prepend the tools path. This prepends the PATH for the current process and
// instructs the agent to prepend for each task that follows.
//
this.buildAgent.debug(`toolPath: ${toolPath}`);
this.buildAgent.debug(`toolPath: ${toolPath}`)
if (os.platform() !== "win32" && !this.buildAgent.getVariable("DOTNET_ROOT")) {
let dotnetPath = await this.buildAgent.which("dotnet");
dotnetPath = fs.readlinkSync(dotnetPath) || dotnetPath;
const dotnetRoot = path.dirname(dotnetPath);
this.buildAgent.exportVariable("DOTNET_ROOT", dotnetRoot);
if (
os.platform() !== 'win32' &&
!this.buildAgent.getVariable('DOTNET_ROOT')
) {
let dotnetPath = await this.buildAgent.which('dotnet')
dotnetPath = fs.readlinkSync(dotnetPath) || dotnetPath
const dotnetRoot = path.dirname(dotnetPath)
this.buildAgent.exportVariable('DOTNET_ROOT', dotnetRoot)
}
this.buildAgent.addPath(toolPath);
this.buildAgent.addPath(toolPath)
return toolPath;
return toolPath
}
private async queryLatestMatch(toolName: string, versionSpec: string, includePrerelease: boolean): Promise<string> {
this.buildAgent.debug(`querying tool versions for ${toolName}${versionSpec ? `@${versionSpec}` : ""} ${includePrerelease ? "including pre-releases" : ""}`);
private async queryLatestMatch(
toolName: string,
versionSpec: string,
includePrerelease: boolean
): Promise<string> {
this.buildAgent.debug(
`querying tool versions for ${toolName}${
versionSpec ? `@${versionSpec}` : ''
} ${includePrerelease ? 'including pre-releases' : ''}`
)
const downloadPath = `https://api-v2v3search-0.nuget.org/query?q=${encodeURIComponent(toolName.toLowerCase())}&prerelease=${includePrerelease ? "true" : "false"}&semVerLevel=2.0.0`;
const res = await this.httpClient.get(downloadPath);
const downloadPath = `https://api-v2v3search-0.nuget.org/query?q=${encodeURIComponent(
toolName.toLowerCase()
)}&prerelease=${includePrerelease ? 'true' : 'false'}&semVerLevel=2.0.0`
const res = await this.httpClient.get(downloadPath)
if (!res || res.message.statusCode !== 200) {
return null;
return null
}
const body: string = await res.readBody();
const data = JSON.parse(body).data;
const body: string = await res.readBody()
const data = JSON.parse(body).data
const versions = (data[0].versions as { version: string }[]).map((x) => x.version);
const versions = (data[0].versions as {version: string}[]).map(
x => x.version
)
if (!versions || !versions.length) {
return null;
return null
}
this.buildAgent.debug(`got versions: ${versions.join(", ")}`);
this.buildAgent.debug(`got versions: ${versions.join(', ')}`)
return this.versionManager.evaluateVersions(versions, versionSpec);
return this.versionManager.evaluateVersions(versions, versionSpec)
}
private async acquireTool(toolName: string, version: string): Promise<string> {
const tempDirectory = await this.buildAgent.createTempDir();
let args = ["tool", "install", toolName, "--tool-path", tempDirectory];
private async acquireTool(
toolName: string,
version: string
): Promise<string> {
const tempDirectory = await this.buildAgent.createTempDir()
let args = ['tool', 'install', toolName, '--tool-path', tempDirectory]
if (version) {
version = this.versionManager.cleanVersion(version);
args = args.concat(["--version", version]);
version = this.versionManager.cleanVersion(version)
args = args.concat(['--version', version])
}
const result = await this.execute("dotnet", args);
const status = result.code === 0 ? "success" : "failure";
const message = result.code === 0 ? result.stdout : result.stderr;
const result = await this.execute('dotnet', args)
const status = result.code === 0 ? 'success' : 'failure'
const message = result.code === 0 ? result.stdout : result.stderr
this.buildAgent.debug(`tool install result: ${status} ${message}`);
this.buildAgent.debug(`tool install result: ${status} ${message}`)
if (result.code) {
throw new Error("Error installing tool");
throw new Error('Error installing tool')
}
return await this.buildAgent.cacheDir(tempDirectory, toolName, version);
return await this.buildAgent.cacheDir(tempDirectory, toolName, version)
}
}

View File

@@ -1,11 +1,11 @@
import { Container } from "inversify";
import { IVersionManager, VersionManager } from "./versionManager";
import { TYPES, IBuildAgent } from "./models";
import { BuildAgent } from "../agent/mock/build-agent";
import {Container} from 'inversify'
import {IVersionManager, VersionManager} from './versionManager'
import {TYPES, IBuildAgent} from './models'
import {BuildAgent} from '../agent/mock/build-agent'
const container = new Container();
const container = new Container()
container.bind<IVersionManager>(TYPES.IVersionManager).to(VersionManager);
container.bind<IBuildAgent>(TYPES.IBuildAgent).to(BuildAgent);
container.bind<IVersionManager>(TYPES.IVersionManager).to(VersionManager)
container.bind<IBuildAgent>(TYPES.IBuildAgent).to(BuildAgent)
export default container;
export default container

View File

@@ -1,49 +1,54 @@
export const TYPES = {
IBuildAgent: Symbol.for("BuildAgent"),
IDotnetTool: Symbol.for("DotnetTool"),
IGitVersionTool: Symbol.for("GitVersionTool"),
IGitReleaseManagerTool: Symbol.for("GitReleaseManagerTool"),
IVersionManager: Symbol.for("VersionManager"),
};
IBuildAgent: Symbol.for('BuildAgent'),
IDotnetTool: Symbol.for('DotnetTool'),
IGitVersionTool: Symbol.for('GitVersionTool'),
IGitReleaseManagerTool: Symbol.for('GitReleaseManagerTool'),
IVersionManager: Symbol.for('VersionManager')
}
export enum SetupFields {
includePrerelease = "includePrerelease",
versionSpec = "versionSpec",
};
includePrerelease = 'includePrerelease',
versionSpec = 'versionSpec'
}
export interface ISetupSettings {
[SetupFields.versionSpec]: string;
[SetupFields.includePrerelease]: boolean;
[SetupFields.versionSpec]: string
[SetupFields.includePrerelease]: boolean
}
export interface IExecResult {
stdout: string;
stderr: string;
code: number;
error: Error;
stdout: string
stderr: string
code: number
error: Error
}
export interface IBuildAgent {
agentName: string;
find(toolName: string, versionSpec: string, arch?: string): string;
cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise<string>;
createTempDir(): Promise<string>;
debug(message: string): void;
setFailed(message: string, done?: boolean): void;
setSucceeded(message: string, done?: boolean): void;
exportVariable(name: string, val: string): void;
getVariable(name: string): string;
addPath(inputPath: string): void;
which(tool: string, check?: boolean): Promise<string>;
exec(exec: string, args: string[]): Promise<IExecResult>;
agentName: string
find(toolName: string, versionSpec: string, arch?: string): string
cacheDir(
sourceDir: string,
tool: string,
version: string,
arch?: string
): Promise<string>
createTempDir(): Promise<string>
debug(message: string): void
setFailed(message: string, done?: boolean): void
setSucceeded(message: string, done?: boolean): void
exportVariable(name: string, val: string): void
getVariable(name: string): string
addPath(inputPath: string): void
which(tool: string, check?: boolean): Promise<string>
exec(exec: string, args: string[]): Promise<IExecResult>
getSourceDir(): string;
isValidInputFile(input: string, file: string): boolean;
fileExists(file: string): boolean;
directoryExists(file: string): boolean;
getSourceDir(): string
isValidInputFile(input: string, file: string): boolean
fileExists(file: string): boolean
directoryExists(file: string): boolean
setOutput(name: string, value: string): void;
getInput(input: string, required?: boolean): string;
getListInput(input: string, required?: boolean): string[];
getBooleanInput(input: string, required?: boolean): boolean;
}
setOutput(name: string, value: string): void
getInput(input: string, required?: boolean): string
getListInput(input: string, required?: boolean): string[]
getBooleanInput(input: string, required?: boolean): boolean
}

View File

@@ -1,14 +1,15 @@
import { IBuildAgent, SetupFields, ISetupSettings } from "./models";
import {IBuildAgent, SetupFields, ISetupSettings} from './models'
export class Settings {
public static getSetupSettings(buildAgent: IBuildAgent): ISetupSettings {
const versionSpec = buildAgent.getInput(SetupFields.versionSpec);
const includePrerelease = buildAgent.getBooleanInput(SetupFields.includePrerelease);
const versionSpec = buildAgent.getInput(SetupFields.versionSpec)
const includePrerelease = buildAgent.getBooleanInput(
SetupFields.includePrerelease
)
return {
versionSpec,
includePrerelease
}
}
}
}

View File

@@ -1,59 +1,56 @@
import cmp from "semver-compare";
import * as semver from "semver";
import { injectable, inject } from "inversify";
import cmp from 'semver-compare'
import * as semver from 'semver'
import {injectable, inject} from 'inversify'
import { IBuildAgent, TYPES } from "./models";
import {IBuildAgent, TYPES} from './models'
export interface IVersionManager {
isExplicitVersion(versionSpec: string): boolean;
evaluateVersions(versions: string[], versionSpec: string): string;
cleanVersion(version: string): string;
isExplicitVersion(versionSpec: string): boolean
evaluateVersions(versions: string[], versionSpec: string): string
cleanVersion(version: string): string
}
@injectable()
export class VersionManager implements IVersionManager {
private buildAgent: IBuildAgent;
constructor(
@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent,
) {
this.buildAgent = buildAgent;
private buildAgent: IBuildAgent
constructor(@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent) {
this.buildAgent = buildAgent
}
public isExplicitVersion(versionSpec: string): boolean {
const c = semver.clean(versionSpec);
this.buildAgent.debug("isExplicit: " + c);
const c = semver.clean(versionSpec)
this.buildAgent.debug('isExplicit: ' + c)
const valid = semver.valid(c) != null;
this.buildAgent.debug("explicit? " + valid);
const valid = semver.valid(c) != null
this.buildAgent.debug('explicit? ' + valid)
return valid;
return valid
}
public evaluateVersions(versions: string[], versionSpec: string): string {
let version: string;
this.buildAgent.debug("evaluating " + versions.length + " versions");
versions = versions.sort(cmp);
let version: string
this.buildAgent.debug('evaluating ' + versions.length + ' versions')
versions = versions.sort(cmp)
for (let i = versions.length - 1; i >= 0; i--) {
const potential: string = versions[i];
const satisfied: boolean = semver.satisfies(potential, versionSpec);
if (satisfied) {
version = potential;
break;
const potential: string = versions[i]
const satisfied: boolean = semver.satisfies(potential, versionSpec)
if (satisfied) {
version = potential
break
}
}
}
if (version) {
this.buildAgent.debug("matched: " + version);
} else {
this.buildAgent.debug("match not found");
}
this.buildAgent.debug('matched: ' + version)
} else {
this.buildAgent.debug('match not found')
}
return version;
return version
}
public cleanVersion(version: string): string {
this.buildAgent.debug("cleaning: " + version);
return semver.clean(version);
this.buildAgent.debug('cleaning: ' + version)
return semver.clean(version)
}
}
}