Merge pull request #812 from GitTools/bug/prerelease

Made possible to install a pre-release version
This commit is contained in:
Artur
2023-03-11 13:44:42 +01:00
parent efc58b37fa
commit 1a99526cb9
60 changed files with 182481 additions and 61375 deletions

View File

@@ -4,16 +4,13 @@ import * as path from 'path'
import * as http from 'typed-rest-client/HttpClient'
import { inject, injectable } from 'inversify'
import { TYPES, IExecResult, IBuildAgent, ISetupSettings } from './models'
import { TYPES, IExecResult, IBuildAgent } from './models'
import { IVersionManager } from './versionManager'
import { ISetupSettings } from '../tools/common/models'
export interface IDotnetTool {
disableTelemetry(): void
toolInstall(
toolName: string,
checkLatest: boolean,
setupSettings: ISetupSettings
): Promise<string>
toolInstall(toolName: string, checkLatest: boolean, setupSettings: ISetupSettings): Promise<string>
}
@injectable()
@@ -22,20 +19,12 @@ export class DotnetTool implements IDotnetTool {
protected versionManager: IVersionManager
private httpClient: http.HttpClient
private static readonly nugetRoot: string =
'https://api-v2v3search-0.nuget.org/'
private static readonly nugetRoot: string = 'https://azuresearch-usnc.nuget.org/'
constructor(
@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent,
@inject(TYPES.IVersionManager) versionManager: IVersionManager
) {
constructor(@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent, @inject(TYPES.IVersionManager) versionManager: IVersionManager) {
this.buildAgent = buildAgent
this.versionManager = versionManager
this.httpClient = new http.HttpClient(
'dotnet',
undefined,
this.buildAgent.proxyConfiguration(DotnetTool.nugetRoot)
)
this.httpClient = new http.HttpClient('dotnet', undefined, this.buildAgent.proxyConfiguration(DotnetTool.nugetRoot))
}
public disableTelemetry(): void {
@@ -48,20 +37,16 @@ export class DotnetTool implements IDotnetTool {
return this.buildAgent.exec(cmd, args)
}
public async toolInstall(
toolName: string,
checkLatest: boolean,
setupSettings: ISetupSettings
): Promise<string> {
public async toolInstall(toolName: string, checkLatest: boolean, setupSettings: ISetupSettings): Promise<string> {
console.log('')
console.log('--------------------------')
console.log(
`Installing ${toolName} version ` + setupSettings.versionSpec
)
console.log(`Acquiring ${toolName} version spec: ${setupSettings.versionSpec}`)
console.log('--------------------------')
let version: string
if (this.versionManager.isExplicitVersion(setupSettings.versionSpec)) {
checkLatest = false // check latest doesn't make sense when explicit version
version = setupSettings.versionSpec
}
let toolPath: string
@@ -73,10 +58,7 @@ export class DotnetTool implements IDotnetTool {
}
if (!toolPath) {
let version: string
if (
this.versionManager.isExplicitVersion(setupSettings.versionSpec)
) {
if (this.versionManager.isExplicitVersion(setupSettings.versionSpec)) {
//
// Explicit version was specified. No need to query for list of versions.
//
@@ -88,15 +70,9 @@ 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,
setupSettings.versionSpec,
setupSettings.includePrerelease
)
version = await this.queryLatestMatch(toolName, setupSettings.versionSpec, setupSettings.includePrerelease)
if (!version) {
throw new Error(
`Unable to find ${toolName} version '${setupSettings.versionSpec}'.`
)
throw new Error(`Unable to find ${toolName} version '${setupSettings.versionSpec}'.`)
}
//
@@ -108,24 +84,20 @@ export class DotnetTool implements IDotnetTool {
//
// Download, extract, cache
//
toolPath = await this.acquireTool(
toolName,
version,
setupSettings.ignoreFailedSources
)
toolPath = await this.acquireTool(toolName, version, setupSettings.ignoreFailedSources)
}
}
console.log('--------------------------')
console.log(`${toolName} version: ${version} installed.`)
console.log('--------------------------')
//
// 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}`)
if (
os.platform() !== 'win32' &&
!this.buildAgent.getVariable('DOTNET_ROOT')
) {
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)
@@ -136,22 +108,14 @@ export class DotnetTool implements IDotnetTool {
return toolPath
}
private async queryLatestMatch(
toolName: string,
versionSpec: string,
includePrerelease: boolean
): Promise<string> {
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' : ''}`
`querying tool versions for ${toolName}${versionSpec ? `@${versionSpec}` : ''} ${includePrerelease ? 'including pre-releases' : ''}`
)
const downloadPath = `${
DotnetTool.nugetRoot
}query?q=${encodeURIComponent(toolName.toLowerCase())}&prerelease=${
includePrerelease ? 'true' : 'false'
}&semVerLevel=2.0.0`
const toolNameParam = encodeURIComponent(toolName.toLowerCase())
const prereleaseParam = includePrerelease ? 'true' : 'false'
const downloadPath = `${DotnetTool.nugetRoot}query?q=${toolNameParam}&prerelease=${prereleaseParam}&semVerLevel=2.0.0&take=1`
const res = await this.httpClient.get(downloadPath)
@@ -162,23 +126,19 @@ export class DotnetTool implements IDotnetTool {
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
}
this.buildAgent.debug(`got versions: ${versions.join(', ')}`)
return this.versionManager.evaluateVersions(versions, versionSpec)
return this.versionManager.evaluateVersions(versions, versionSpec, {
includePrerelease
})
}
private async acquireTool(
toolName: string,
version: string,
ignoreFailedSources: boolean
): Promise<string> {
private async acquireTool(toolName: string, version: string, ignoreFailedSources: boolean): Promise<string> {
const tempDirectory = await this.buildAgent.createTempDir()
let args = ['tool', 'install', toolName, '--tool-path', tempDirectory]

View File

@@ -5,19 +5,9 @@ export const TYPES = {
IDotnetTool: Symbol.for('DotnetTool'),
IGitVersionTool: Symbol.for('GitVersionTool'),
IGitReleaseManagerTool: Symbol.for('GitReleaseManagerTool'),
IVersionManager: Symbol.for('VersionManager')
}
export enum SetupFields {
includePrerelease = 'includePrerelease',
versionSpec = 'versionSpec',
ignoreFailedSources = 'ignoreFailedSources'
}
export interface ISetupSettings {
[SetupFields.versionSpec]: string
[SetupFields.includePrerelease]: boolean
[SetupFields.ignoreFailedSources]: boolean
IVersionManager: Symbol.for('VersionManager'),
IGitVersionSettingsProvider: Symbol.for('GitVersionSettingsProvider'),
IGitReleaseManagerSettingsProvider: Symbol.for('GitReleaseManagerSettingsProvider')
}
export interface IExecResult {
@@ -26,17 +16,11 @@ export interface IExecResult {
code: number
error: Error
}
export interface IBuildAgent {
agentName: string
proxyConfiguration(url: string): IRequestOptions
find(toolName: string, versionSpec: string, arch?: string): string
cacheDir(
sourceDir: string,
tool: string,
version: string,
arch?: string
): Promise<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

View File

@@ -1,19 +0,0 @@
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 ignoreFailedSources = buildAgent.getBooleanInput(
SetupFields.ignoreFailedSources
)
return {
versionSpec,
includePrerelease,
ignoreFailedSources
}
}
}

View File

@@ -1,4 +1,3 @@
import cmp from 'semver-compare'
import * as semver from 'semver'
import { injectable, inject } from 'inversify'
@@ -6,7 +5,7 @@ import { IBuildAgent, TYPES } from './models'
export interface IVersionManager {
isExplicitVersion(versionSpec: string): boolean
evaluateVersions(versions: string[], versionSpec: string): string
evaluateVersions(versions: string[], versionSpec: string, optionsOrLoose?: boolean | semver.RangeOptions): string
cleanVersion(version: string): string
}
@@ -27,13 +26,13 @@ export class VersionManager implements IVersionManager {
return valid
}
public evaluateVersions(versions: string[], versionSpec: string): string {
public evaluateVersions(versions: string[], versionSpec: string, optionsOrLoose?: boolean | semver.RangeOptions): string {
let version: string
this.buildAgent.debug('evaluating ' + versions.length + ' versions')
versions = versions.sort(cmp)
versions = semver.sort(versions)
for (let i = versions.length - 1; i >= 0; i--) {
const potential: string = versions[i]
const satisfied: boolean = semver.satisfies(potential, versionSpec)
const satisfied: boolean = semver.satisfies(potential, versionSpec, optionsOrLoose)
if (satisfied) {
version = potential
break