refactore, using inversify for dependency injection
9
.gitignore
vendored
@@ -1,10 +1,5 @@
|
||||
node_modules/
|
||||
*.js
|
||||
|
||||
.taskkey
|
||||
|
||||
dist/azure/task/
|
||||
!dist/azure/task/icon.png
|
||||
!dist/azure/task/task.json
|
||||
|
||||
*.vsix
|
||||
*.js
|
||||
!dist/**/*.js
|
||||
26
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "tsc: build - src/azure/tsconfig.json",
|
||||
"name": "Run Azure Pipeline Task",
|
||||
"program": "${workspaceFolder}/src/azure/main.ts",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
},
|
||||
{
|
||||
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "tsc: build - src/github/tsconfig.json",
|
||||
"name": "Run GitHub Actions",
|
||||
"program": "${workspaceFolder}/src/github/main.ts",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
dist/azure/images/build-task.png
vendored
|
Before Width: | Height: | Size: 24 KiB |
BIN
dist/azure/images/builds.png
vendored
|
Before Width: | Height: | Size: 53 KiB |
BIN
dist/azure/images/extension-icon.png
vendored
|
Before Width: | Height: | Size: 4.6 KiB |
16558
dist/azure/index.js
vendored
Normal file
14
dist/azure/lib.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"messages": {
|
||||
"TOOL_LIB_CachingTool": "Caching tool: %s %s %s",
|
||||
"_TOOL_LIB_CachingTool.comment": "This informational log message indicates that a tool, that was just downloaded, is being copied into the cache directory. %s %s %s represent the tool name, version information, and processor architecture.",
|
||||
"TOOL_LIB_Downloading": "Downloading: %s",
|
||||
"_TOOL_LIB_Downloading.comment": "This information log message indicates that a file is being downloaded. %s represents the URL being downloaded.",
|
||||
"TOOL_LIB_ExtractingArchive": "Extracting archive",
|
||||
"_TOOL_LIB_ExtractingArchive.comment": "This informational log message indicates that an archive file is being extracted. For example, a .zip file, .7z file, or .tar.gz file.",
|
||||
"TOOL_LIB_FoundInCache": "Found tool in cache: %s %s %s",
|
||||
"_TOOL_LIB_FoundInCache.comment": "This informational log message indicates that the request tool is already cached, and does not need to be downloaded again. %s %s %s represent the tool name, version information, and processor architecture.",
|
||||
"TOOL_LIB_PrependPath": "Prepending PATH environment variable with directory: %s",
|
||||
"_TOOL_LIB_PrependPath.comment": "This informational log message indicates that a directory is being prepended to the front of the PATH environment variable. The directories specified by the PATH environment variable are used to resolve the location of command line tools."
|
||||
}
|
||||
}
|
||||
36
dist/azure/lib1.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"messages": {
|
||||
"LIB_UnhandledEx": "Unhandled: %s",
|
||||
"LIB_FailOnCode": "Failure return code: %d",
|
||||
"LIB_MkdirFailed": "Unable to create directory '%s'. %s",
|
||||
"LIB_MkdirFailedFileExists": "Unable to create directory '%s'. Conflicting file exists: '%s'",
|
||||
"LIB_MkdirFailedInvalidDriveRoot": "Unable to create directory '%s'. Root directory does not exist: '%s'",
|
||||
"LIB_MkdirFailedInvalidShare": "Unable to create directory '%s'. Unable to verify the directory exists: '%s'. If directory is a file share, please verify the share name is correct, the share is online, and the current process has permission to access the share.",
|
||||
"LIB_MultilineSecret": "Secrets cannot contain multiple lines",
|
||||
"LIB_ProcessError": "There was an error when attempting to execute the process '%s'. This may indicate the process failed to start. Error: %s",
|
||||
"LIB_ProcessExitCode": "The process '%s' failed with exit code %s",
|
||||
"LIB_ProcessStderr": "The process '%s' failed because one or more lines were written to the STDERR stream",
|
||||
"LIB_ReturnCode": "Return code: %d",
|
||||
"LIB_ResourceFileNotExist": "Resource file doesn\\'t exist: %s",
|
||||
"LIB_ResourceFileAlreadySet": "Resource file has already set to: %s",
|
||||
"LIB_ResourceFileNotSet": "Resource file haven\\'t set, can\\'t find loc string for key: %s",
|
||||
"LIB_StdioNotClosed": "The STDIO streams did not close within %s seconds of the exit event from process '%s'. This may indicate a child process inherited the STDIO streams and has not yet exited.",
|
||||
"LIB_WhichNotFound_Linux": "Unable to locate executable file: '%s'. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.",
|
||||
"LIB_WhichNotFound_Win": "Unable to locate executable file: '%s'. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.",
|
||||
"LIB_LocStringNotFound": "Can\\'t find loc string for key: %s",
|
||||
"LIB_ParameterIsRequired": "%s not supplied",
|
||||
"LIB_InputRequired": "Input required: %s",
|
||||
"LIB_InvalidPattern": "Invalid pattern: '%s'",
|
||||
"LIB_EndpointNotExist": "Endpoint not present: %s",
|
||||
"LIB_EndpointDataNotExist": "Endpoint data parameter %s not present: %s",
|
||||
"LIB_EndpointAuthNotExist": "Endpoint auth data not present: %s",
|
||||
"LIB_InvalidEndpointAuth": "Invalid endpoint auth: %s",
|
||||
"LIB_InvalidSecureFilesInput": "Invalid secure file input: %s",
|
||||
"LIB_PathNotFound": "Not found %s: %s",
|
||||
"LIB_PathHasNullByte": "Path cannot contain null bytes",
|
||||
"LIB_OperationFailed": "Failed %s: %s",
|
||||
"LIB_UseFirstGlobMatch": "Multiple workspace matches. using first.",
|
||||
"LIB_MergeTestResultNotSupported": "Merging test results from multiple files to one test run is not supported on this version of build agent for OSX/Linux, each test result file will be published as a separate test run in VSO/TFS.",
|
||||
"LIB_PlatformNotSupported": "Platform not supported: %s"
|
||||
}
|
||||
}
|
||||
6
dist/azure/overview.md
vendored
@@ -1,6 +0,0 @@
|
||||
Versioning when using Git, solved. GitVersion looks at your Git history and works out the [semantic version](http://semver.org) of the commit being built.
|
||||
|
||||
It works with most branching strategies but has been designed mainly around GitFlow and GitHubFlow (pull request workflow). The calculated version numbers can then be accessed through variables such as `$(GitVersion.NuGetVersion)` and `$(GitVersion.SemVer)`. It is also very configurable to allow it to work with most release workflows!
|
||||
|
||||

|
||||

|
||||
BIN
dist/azure/task/icon.png
vendored
|
Before Width: | Height: | Size: 4.6 KiB |
106
dist/azure/task/task.json
vendored
@@ -1,106 +0,0 @@
|
||||
{
|
||||
"id": "dd065e3b-6aef-46af-845c-520195836b35",
|
||||
"name": "UseGitVersion",
|
||||
"friendlyName": "GitVersion Task$titleSuffix$",
|
||||
"description": "Easy Semantic Versioning (http://semver.org) for projects using Git",
|
||||
"author": "GitVersion Contributors",
|
||||
"helpMarkDown": "See the [documentation](http://gitversion.readthedocs.org/en/latest/) for help",
|
||||
"category": "Build",
|
||||
"demands": [],
|
||||
"version": {
|
||||
"Major": "5",
|
||||
"Minor": "1",
|
||||
"Patch": "2"
|
||||
},
|
||||
"minimumAgentVersion": "2.115.0",
|
||||
"groups": [
|
||||
{
|
||||
"name": "gitversionDetails",
|
||||
"displayName": "GitVersion details",
|
||||
"isExpanded": true
|
||||
},
|
||||
{
|
||||
"name": "additional",
|
||||
"displayName": "Additional Options",
|
||||
"isExpanded": false
|
||||
}
|
||||
],
|
||||
"instanceNameFormat": "GitVersion",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "versionSpec",
|
||||
"type": "string",
|
||||
"label": "The version spec",
|
||||
"defaultValue": "",
|
||||
"required": true,
|
||||
"helpMarkDown": "Required version in the form of 5.x or exact version like 5.0.0"
|
||||
},
|
||||
{
|
||||
"name": "includePrerelease",
|
||||
"type": "boolean",
|
||||
"label": "Include pre-release versions",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Include pre-release versions when matching a version"
|
||||
},
|
||||
{
|
||||
"name": "targetPath",
|
||||
"type": "string",
|
||||
"label": "Working directory path",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Optionally supply the path to the working directory",
|
||||
"groupName": "gitversionDetails"
|
||||
},
|
||||
{
|
||||
"name": "useConfigFile",
|
||||
"type": "boolean",
|
||||
"label": "Specify Configuration file",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Whether to use a custom configuration file"
|
||||
},
|
||||
{
|
||||
"name": "configFilePath",
|
||||
"type": "filePath",
|
||||
"label": "Configuration file",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Optional path to config file (defaults to GitVersion.yml)",
|
||||
"visibleRule": "useConfigFile = true"
|
||||
},
|
||||
{
|
||||
"name": "updateAssemblyInfo",
|
||||
"type": "boolean",
|
||||
"label": "Update AssemblyInfo files",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Whether to update versions in the AssemblyInfo files"
|
||||
},
|
||||
{
|
||||
"name": "updateAssemblyInfoFilename",
|
||||
"type": "string",
|
||||
"label": "Update Assembly File",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Update versions in specified file",
|
||||
"visibleRule": "updateAssemblyInfo = true"
|
||||
},
|
||||
{
|
||||
"name": "additionalArguments",
|
||||
"type": "string",
|
||||
"label": "Additional GitVersion arguments",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Additional arguments to send to GitVersion",
|
||||
"groupName": "additional"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"Node": {
|
||||
"target": "GitVersion.js",
|
||||
"argumentFormat": "",
|
||||
"workingDirectory": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
71
dist/azure/vss-extension.json
vendored
@@ -1,71 +0,0 @@
|
||||
{
|
||||
"manifestVersion": 1,
|
||||
"id": "usegitversion$idSuffix$",
|
||||
"name": "UseGitVersion$titleSuffix$",
|
||||
"publisher": "gittools",
|
||||
"public": true,
|
||||
"author": "GitVersion Contributors",
|
||||
"version": "$version$",
|
||||
"description": "Build task for easy semantic versioning for projects using Git.",
|
||||
"targets": [{
|
||||
"id": "Microsoft.VisualStudio.Services"
|
||||
}],
|
||||
"files": [
|
||||
{ "path": "task" }
|
||||
],
|
||||
"categories": [
|
||||
"Azure Pipelines"
|
||||
],
|
||||
"galleryFlags": [
|
||||
"$visibility$"
|
||||
],
|
||||
"icons": {
|
||||
"default": "images/extension-icon.png"
|
||||
},
|
||||
"tags": [
|
||||
"semver",
|
||||
"git",
|
||||
"versioning",
|
||||
"gitflow",
|
||||
"githubflow"
|
||||
],
|
||||
"links": {
|
||||
"learn": {
|
||||
"uri": "http://gitversion.readthedocs.org/en/stable"
|
||||
},
|
||||
"getstarted": {
|
||||
"uri": "http://gitversion.readthedocs.org/en/stable/build-server-support/build-server/tfs-build-vnext/#running-inside-tfs"
|
||||
},
|
||||
"license": {
|
||||
"uri": "https://github.com/GitTools/GitVersion/blob/master/LICENSE"
|
||||
},
|
||||
"repository": {
|
||||
"uri": "https://github.com/GitTools/GitVersion"
|
||||
},
|
||||
"support": {
|
||||
"uri": "https://github.com/GitTools/GitVersion/issues"
|
||||
}
|
||||
},
|
||||
"screenshots": [{
|
||||
"path": "images/builds.png"
|
||||
},
|
||||
{
|
||||
"path": "images/build-task.png"
|
||||
}
|
||||
],
|
||||
"content": {
|
||||
"details": {
|
||||
"path": "overview.md"
|
||||
}
|
||||
},
|
||||
"contributions": [{
|
||||
"id": "gitversion-task",
|
||||
"type": "ms.vss-distributed-task.task",
|
||||
"targets": [
|
||||
"ms.vss-distributed-task.tasks"
|
||||
],
|
||||
"properties": {
|
||||
"name": "GitVersionTask"
|
||||
}
|
||||
}]
|
||||
}
|
||||
9390
dist/github/index.js
vendored
3005
package-lock.json
generated
44
package.json
@@ -1,49 +1,37 @@
|
||||
{
|
||||
"name": "use-gitversion",
|
||||
"version": "1.0.0",
|
||||
"description": "Github Action that installs and uses the GitVersion tool",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build-github": "tsc -p src/github",
|
||||
"build-azure": "tsc -p src/azure && tsc -p src/azure/tests",
|
||||
"test-azure": "mocha src/azure/tests/test-suite.js",
|
||||
"package-github": "ncc build src/github/GitVersion.js -o dist/github",
|
||||
"package-azure": "ncc build src/github/GitVersion.js -o dist/azure/task && tfx extension create --root dist/azure --manifest-globs vss-extension.json --output-path dist/azure"
|
||||
},
|
||||
"description": "Easy Semantic Versioning (http://semver.org) for projects using Git",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/GitTools/use-gitversion.git"
|
||||
"url": "https://github.com/GitTools/use-gitversion.git"
|
||||
},
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "GitTools",
|
||||
"contributors": [
|
||||
"GitTools contributors"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/GitTools/use-gitversion/issues"
|
||||
},
|
||||
"homepage": "https://github.com/GitTools/use-gitversion#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.0",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/io": "^1.0.1",
|
||||
"@actions/tool-cache": "^1.1.2",
|
||||
"azure-pipelines-task-lib": "2.8.0",
|
||||
"azure-pipelines-task-lib": "2.9.3",
|
||||
"azure-pipelines-tool-lib": "0.12.0",
|
||||
"semver": "^6.3.0",
|
||||
"semver-compare": "^1.0.0",
|
||||
"inversify": "^5.0.1",
|
||||
"typed-rest-client": "1.5.0",
|
||||
"uuid": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^12.12.7",
|
||||
"@types/node": "12.12.11",
|
||||
"@types/q": "1.5.2",
|
||||
"@types/semver": "^6.2.0",
|
||||
"@types/uuid": "^3.4.6",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"copy-node-modules": "^1.1.1",
|
||||
"mocha": "^6.2.1",
|
||||
"mocha-xunit-reporter": "^1.1.0",
|
||||
"tfx-cli": "0.6.3",
|
||||
"typescript": "^3.7.2"
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"tslint": "^5.20.1",
|
||||
"typescript": "^3.7.2",
|
||||
"@zeit/ncc": "^0.20.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,38 @@
|
||||
export interface IProxy {
|
||||
find: (toolName: string, versionSpec: string, arch?: string) => string;
|
||||
debug: (message: string) => void;
|
||||
exportVariable: (name: string, val: string) => void;
|
||||
addPath: (inputPath: string) => void;
|
||||
which: (tool: string, check?: boolean) => Promise<string>;
|
||||
cacheDir: (sourceDir: string, tool: string, version: string, arch?: string) => Promise<string>;
|
||||
export interface IVersionManager {
|
||||
isExplicitVersion: (versionSpec: string) => boolean;
|
||||
evaluateVersions: (versions: string[], versionSpec: string) => string;
|
||||
cleanVersion: (version: string) => string;
|
||||
createTempDir: () => Promise<string>;
|
||||
executeDotNet: (args: string[]) => Promise<IExecSyncResult>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IExecSyncResult {
|
||||
/** standard output */
|
||||
export interface IBuildAgent {
|
||||
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;
|
||||
addPath: (inputPath: string) => void;
|
||||
which: (tool: string, check?: boolean) => Promise<string>;
|
||||
exec: (exec: string, args: string[]) => Promise<IExecResult>;
|
||||
}
|
||||
|
||||
export interface IDotnetTool {
|
||||
run: (args: string[]) => Promise<IExecResult>;
|
||||
toolInstall: (toolName: string, versionSpec: string, checkLatest: boolean, includePre: boolean) => Promise<string>;
|
||||
}
|
||||
|
||||
export class Argument {
|
||||
constructor(public readonly name: string, public readonly value: string) {
|
||||
}
|
||||
}
|
||||
export interface IGitVersionTool {
|
||||
install: (versionSpec: string, includePrerelease: boolean) => Promise<void>;
|
||||
run: (...params: Argument[]) => Promise<IExecResult>;
|
||||
}
|
||||
export interface IExecResult {
|
||||
stdout: string;
|
||||
/** error output */
|
||||
stderr: string;
|
||||
/** return code */
|
||||
code: number;
|
||||
/** Error on failure */
|
||||
error: Error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as httpm from 'typed-rest-client/HttpClient';
|
||||
|
||||
import { IProxy } from './Interfaces';
|
||||
|
||||
export class ToolInstaller {
|
||||
constructor(public utils: IProxy) {
|
||||
this.httpClient = new httpm.HttpClient("ToolInstaller");
|
||||
}
|
||||
|
||||
public async downloadAndInstall(toolName: string, versionSpec: string, checkLatest: boolean, includePrerelease: boolean): Promise<string> {
|
||||
console.log('');
|
||||
console.log('--------------------------');
|
||||
console.log(`Installing ${toolName} version ` + versionSpec);
|
||||
console.log('--------------------------');
|
||||
|
||||
if (this.utils.isExplicitVersion(versionSpec)) {
|
||||
checkLatest = false; // check latest doesn't make sense when explicit version
|
||||
}
|
||||
|
||||
let toolPath: string;
|
||||
if (!checkLatest) {
|
||||
//
|
||||
// Let's try and resolve the version spec locally first
|
||||
//
|
||||
toolPath = this.utils.find(toolName, versionSpec);
|
||||
}
|
||||
|
||||
if (!toolPath) {
|
||||
let version: string;
|
||||
if (this.utils.isExplicitVersion(versionSpec)) {
|
||||
//
|
||||
// Explicit version was specified. No need to query for list of versions.
|
||||
//
|
||||
version = versionSpec;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Let's query and resolve the latest version for the versionSpec.
|
||||
// If the version is an explicit version (1.1.1 or v1.1.1) then no need to query.
|
||||
// If your tool doesn't offer a mechanism to query,
|
||||
// then it can only support exact version inputs.
|
||||
//
|
||||
version = await this.queryLatestMatch(toolName, versionSpec, includePrerelease);
|
||||
if (!version) {
|
||||
throw new Error(`Unable to find ${toolName} version '${versionSpec}'.`);
|
||||
}
|
||||
|
||||
//
|
||||
// Check the cache for the resolved version.
|
||||
//
|
||||
toolPath = this.utils.find(toolName, version)
|
||||
}
|
||||
if (!toolPath) {
|
||||
//
|
||||
// Download, extract, cache
|
||||
//
|
||||
toolPath = await this.acquireTool(toolName, version);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Prepend the tools path. This prepends the PATH for the current process and
|
||||
// instructs the agent to prepend for each task that follows.
|
||||
//
|
||||
this.utils.debug(`toolPath: ${toolPath}`);
|
||||
|
||||
if (os.platform() != 'win32') {
|
||||
let dotnetRoot = path.dirname(fs.readlinkSync(await this.utils.which("dotnet")));
|
||||
this.utils.exportVariable('DOTNET_ROOT', dotnetRoot);
|
||||
}
|
||||
this.utils.addPath(toolPath);
|
||||
|
||||
return toolPath;
|
||||
}
|
||||
|
||||
private async queryLatestMatch(toolName: string, versionSpec: string, includePrerelease: boolean): Promise<string> {
|
||||
this.utils.debug(`querying tool versions for ${toolName}${versionSpec ? `@${versionSpec}` : ""} ${includePrerelease ? "including pre-releases" : ""}`);
|
||||
|
||||
var downloadPath = `https://api-v2v3search-0.nuget.org/query?q=${encodeURIComponent(toolName.toLowerCase())}&prerelease=${includePrerelease ? "true" : "false"}&semVerLevel=2.0.0`;
|
||||
var res = await this.httpClient.get(downloadPath);
|
||||
|
||||
if (!res || res.message.statusCode != 200)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
let body: string = await res.readBody();
|
||||
var data = JSON.parse(body).data;
|
||||
|
||||
const versions = (<Array<{ version: string }>>data[0].versions).map(x => x.version);
|
||||
if (!versions || !versions.length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
this.utils.debug(`got versions: ${versions.join(", ")}`);
|
||||
|
||||
return this.utils.evaluateVersions(versions, versionSpec);
|
||||
}
|
||||
|
||||
private async acquireTool(toolName: string, version: string): Promise<string> {
|
||||
|
||||
let tempDirectory = await this.utils.createTempDir();
|
||||
let args = ["tool", "install", toolName, "--tool-path", tempDirectory];
|
||||
|
||||
if (version) {
|
||||
version = this.utils.cleanVersion(version);
|
||||
args = args.concat(["--version", version]);
|
||||
}
|
||||
|
||||
let result = await this.utils.executeDotNet(args);
|
||||
let status = result.code === 0 ? "success" : "failure";
|
||||
let message = result.code === 0 ? result.stdout : result.stderr;
|
||||
|
||||
this.utils.debug(`tool install result: ${status} ${message}`);
|
||||
|
||||
if (result.code) {
|
||||
throw new Error("Error installing tool");
|
||||
}
|
||||
|
||||
return await this.utils.cacheDir(tempDirectory, toolName, version);
|
||||
}
|
||||
|
||||
private httpClient: httpm.HttpClient;
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import * as path from 'path';
|
||||
|
||||
import * as tl from 'azure-pipelines-task-lib/task';
|
||||
|
||||
import { ToolInstaller } from '../ToolInstaller';
|
||||
import { Proxy as utils } from './Proxy';
|
||||
|
||||
function isValidInputFile(input: string, file: string) {
|
||||
return tl.filePathSupplied(input) && fileExists(file);
|
||||
}
|
||||
|
||||
function fileExists(file: string) {
|
||||
return tl.exist(file) && tl.stats(file).isFile();
|
||||
}
|
||||
|
||||
function directoryExists(file: string) {
|
||||
return tl.exist(file) && tl.stats(file).isDirectory();
|
||||
}
|
||||
|
||||
export class GitVersionTask {
|
||||
versionSpec: string;
|
||||
includePrerelease: boolean;
|
||||
targetPath: string;
|
||||
|
||||
useConfigFile: boolean;
|
||||
configFilePath: string;
|
||||
|
||||
updateAssemblyInfo: boolean;
|
||||
updateAssemblyInfoFilename: string;
|
||||
|
||||
additionalArguments: string;
|
||||
|
||||
sourcesDirectory: string;
|
||||
|
||||
constructor() {
|
||||
|
||||
this.versionSpec = tl.getInput('versionSpec', true);
|
||||
this.includePrerelease = tl.getBoolInput('includePrerelease');
|
||||
this.targetPath = tl.getInput('targetPath');
|
||||
|
||||
this.useConfigFile = tl.getBoolInput('useConfigFile');
|
||||
this.configFilePath = tl.getInput('configFilePath');
|
||||
|
||||
this.updateAssemblyInfo = tl.getBoolInput('updateAssemblyInfo');
|
||||
this.updateAssemblyInfoFilename = tl.getInput('updateAssemblyInfoFilename');
|
||||
|
||||
this.additionalArguments = tl.getInput('additionalArguments');
|
||||
|
||||
this.sourcesDirectory = tl.getVariable('Build.SourcesDirectory').replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
public async execute() {
|
||||
try {
|
||||
let toolPath = await this.installTool(this.versionSpec, this.includePrerelease);
|
||||
|
||||
let workingDirectory = this.getWorkingDirectory(this.targetPath);
|
||||
let args = this.getArguments(workingDirectory);
|
||||
|
||||
let exe = tl.tool('dotnet-gitversion');
|
||||
exe.arg(args);
|
||||
if (this.additionalArguments) {
|
||||
exe.line(this.additionalArguments);
|
||||
}
|
||||
|
||||
const result = await exe.exec();
|
||||
if (result) {
|
||||
tl.setResult(tl.TaskResult.Failed, "An error occured during GitVersion execution");
|
||||
} else {
|
||||
tl.setResult(tl.TaskResult.Succeeded, "GitVersion executed successfully");
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
tl.debug(err.stack);
|
||||
tl.setResult(tl.TaskResult.Failed, err, true);
|
||||
}
|
||||
}
|
||||
|
||||
private getArguments(workingDirectory: string) {
|
||||
let args = [
|
||||
workingDirectory,
|
||||
"/output",
|
||||
"buildserver",
|
||||
"/nofetch"
|
||||
];
|
||||
|
||||
if (this.useConfigFile) {
|
||||
if (isValidInputFile('configFilePath', this.configFilePath)) {
|
||||
args.push("/config", this.configFilePath);
|
||||
}
|
||||
else {
|
||||
throw new Error('GitVersion configuration file not found at ' + this.configFilePath);
|
||||
}
|
||||
}
|
||||
if (this.updateAssemblyInfo) {
|
||||
args.push("/updateassemblyinfo");
|
||||
if (isValidInputFile('updateAssemblyInfoFilename', this.updateAssemblyInfoFilename)) {
|
||||
args.push(this.updateAssemblyInfoFilename);
|
||||
}
|
||||
else {
|
||||
throw new Error('AssemblyInfoFilename file not found at ' + this.updateAssemblyInfoFilename);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
private async installTool(version: string, includePrerelease: boolean): Promise<string> {
|
||||
let installTool = process.env["INSTALL_TOOL"];
|
||||
if (installTool === null || installTool === undefined || installTool.toUpperCase() == "TRUE") {
|
||||
return await new ToolInstaller(utils).downloadAndInstall("GitVersion.Tool", version, false, includePrerelease);
|
||||
}
|
||||
}
|
||||
|
||||
private getWorkingDirectory(targetPath: string) {
|
||||
let workDir;
|
||||
|
||||
if (!targetPath) {
|
||||
workDir = this.sourcesDirectory;
|
||||
} else {
|
||||
if (directoryExists(targetPath)) {
|
||||
workDir = path.join(this.sourcesDirectory, targetPath);
|
||||
}
|
||||
else {
|
||||
throw new Error('Directory not found at ' + targetPath);
|
||||
}
|
||||
}
|
||||
return workDir.replace(/\\/g, '/');
|
||||
}
|
||||
}
|
||||
|
||||
var task = new GitVersionTask();
|
||||
task.execute().catch((reason) => tl.setResult(tl.TaskResult.Failed, reason));
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,106 +0,0 @@
|
||||
{
|
||||
"id": "dd065e3b-6aef-46af-845c-520195836b35",
|
||||
"name": "UseGitVersion",
|
||||
"friendlyName": "GitVersion Task (Preview)",
|
||||
"description": "Easy Semantic Versioning (http://semver.org) for projects using Git",
|
||||
"author": "GitVersion Contributors",
|
||||
"helpMarkDown": "See the [documentation](http://gitversion.readthedocs.org/en/latest/) for help",
|
||||
"category": "Build",
|
||||
"demands": [],
|
||||
"version": {
|
||||
"Major": "5",
|
||||
"Minor": "1",
|
||||
"Patch": "3"
|
||||
},
|
||||
"minimumAgentVersion": "2.115.0",
|
||||
"groups": [
|
||||
{
|
||||
"name": "gitversionDetails",
|
||||
"displayName": "GitVersion details",
|
||||
"isExpanded": true
|
||||
},
|
||||
{
|
||||
"name": "additional",
|
||||
"displayName": "Additional Options",
|
||||
"isExpanded": false
|
||||
}
|
||||
],
|
||||
"instanceNameFormat": "GitVersion",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "versionSpec",
|
||||
"type": "string",
|
||||
"label": "The version spec",
|
||||
"defaultValue": "",
|
||||
"required": true,
|
||||
"helpMarkDown": "Required version in the form of 5.x or exact version like 5.0.0"
|
||||
},
|
||||
{
|
||||
"name": "includePrerelease",
|
||||
"type": "boolean",
|
||||
"label": "Include pre-release versions",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Include pre-release versions when matching a version"
|
||||
},
|
||||
{
|
||||
"name": "targetPath",
|
||||
"type": "string",
|
||||
"label": "Working directory path",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Optionally supply the path to the working directory",
|
||||
"groupName": "gitversionDetails"
|
||||
},
|
||||
{
|
||||
"name": "useConfigFile",
|
||||
"type": "boolean",
|
||||
"label": "Specify Configuration file",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Whether to use a custom configuration file"
|
||||
},
|
||||
{
|
||||
"name": "configFilePath",
|
||||
"type": "filePath",
|
||||
"label": "Configuration file",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Optional path to config file (defaults to GitVersion.yml)",
|
||||
"visibleRule": "useConfigFile = true"
|
||||
},
|
||||
{
|
||||
"name": "updateAssemblyInfo",
|
||||
"type": "boolean",
|
||||
"label": "Update AssemblyInfo files",
|
||||
"defaultValue": "false",
|
||||
"required": false,
|
||||
"helpMarkDown": "Whether to update versions in the AssemblyInfo files"
|
||||
},
|
||||
{
|
||||
"name": "updateAssemblyInfoFilename",
|
||||
"type": "string",
|
||||
"label": "Update Assembly File",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Update versions in specified file",
|
||||
"visibleRule": "updateAssemblyInfo = true"
|
||||
},
|
||||
{
|
||||
"name": "additionalArguments",
|
||||
"type": "string",
|
||||
"label": "Additional GitVersion arguments",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"helpMarkDown": "Additional arguments to send to GitVersion",
|
||||
"groupName": "additional"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"Node": {
|
||||
"target": "GitVersion.js",
|
||||
"argumentFormat": "",
|
||||
"workingDirectory": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
import { createTempDir, executeDotNet } from './ToolLib';
|
||||
import { findLocalTool, prependPath, cacheDir, isExplicitVersion, evaluateVersions, cleanVersion } from 'azure-pipelines-tool-lib/tool';
|
||||
import { debug, setVariable, which } from 'azure-pipelines-task-lib/task';
|
||||
|
||||
function _which(tool: string, check?: boolean) : Promise<string> {
|
||||
return Promise.resolve(which(tool, check));
|
||||
}
|
||||
import { IProxy } from '../Interfaces';
|
||||
|
||||
export const Proxy: IProxy = {
|
||||
find: findLocalTool,
|
||||
debug: debug,
|
||||
exportVariable: setVariable,
|
||||
addPath: prependPath,
|
||||
which: _which,
|
||||
cacheDir: cacheDir,
|
||||
isExplicitVersion: isExplicitVersion,
|
||||
evaluateVersions: evaluateVersions,
|
||||
cleanVersion: cleanVersion,
|
||||
createTempDir: createTempDir,
|
||||
executeDotNet: executeDotNet
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import * as taskLib from 'azure-pipelines-task-lib/task';
|
||||
|
||||
export interface IExecSyncResult {
|
||||
/** standard output */
|
||||
stdout: string;
|
||||
/** error output */
|
||||
stderr: string;
|
||||
/** return code */
|
||||
code: number;
|
||||
/** Error on failure */
|
||||
error: Error;
|
||||
}
|
||||
|
||||
export async function createTempDir(): Promise<string> {
|
||||
let tempDir = taskLib.getVariable('Agent.TempDirectory');
|
||||
return Promise.resolve(tempDir);
|
||||
}
|
||||
|
||||
export async function executeDotNet(args: string[]): Promise<IExecSyncResult> {
|
||||
let tr = taskLib.tool("dotnet");
|
||||
tr.arg(args);
|
||||
|
||||
var result = tr.execSync();
|
||||
return {
|
||||
code: result.code,
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr,
|
||||
error: result.error
|
||||
}
|
||||
}
|
||||
62
src/azure/build-agent.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { injectable } from "inversify";
|
||||
|
||||
import * as taskLib from "azure-pipelines-task-lib/task";
|
||||
import * as toolLib from "azure-pipelines-tool-lib/tool";
|
||||
|
||||
import { IBuildAgent, IExecResult } from "../interfaces";
|
||||
|
||||
@injectable()
|
||||
class BuildAgent implements IBuildAgent {
|
||||
public find(toolName: string, versionSpec: string, arch?: string): string {
|
||||
return toolLib.findLocalTool(toolName, versionSpec, arch);
|
||||
}
|
||||
|
||||
public cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise<string> {
|
||||
return toolLib.cacheDir(sourceDir, tool, version, arch);
|
||||
}
|
||||
|
||||
public createTempDir(): Promise<string> {
|
||||
return Promise.resolve(taskLib.getVariable("Agent.TempDirectory"));
|
||||
}
|
||||
|
||||
public debug(message: string): void {
|
||||
taskLib.debug(message);
|
||||
}
|
||||
|
||||
public setFailed(message: string, done?: boolean): void {
|
||||
taskLib.setResult(taskLib.TaskResult.Failed, message, done);
|
||||
}
|
||||
|
||||
public setSucceeded(message: string, done?: boolean): void {
|
||||
taskLib.setResult(taskLib.TaskResult.Succeeded, message, done);
|
||||
}
|
||||
|
||||
public exportVariable(name: string, val: string): void {
|
||||
taskLib.setVariable(name, val);
|
||||
}
|
||||
|
||||
public addPath(inputPath: string): void {
|
||||
toolLib.prependPath(inputPath);
|
||||
}
|
||||
|
||||
public which(tool: string, check?: boolean): Promise<string> {
|
||||
return Promise.resolve(taskLib.which(tool, check));
|
||||
}
|
||||
|
||||
public exec(exec: string, args: string[]): Promise<IExecResult> {
|
||||
const tr = taskLib.tool(exec);
|
||||
tr.arg(args);
|
||||
|
||||
const result = tr.execSync();
|
||||
return Promise.resolve({
|
||||
code: result.code,
|
||||
error: result.error,
|
||||
stderr: result.stderr,
|
||||
stdout: result.stdout,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
BuildAgent,
|
||||
};
|
||||
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
15
src/azure/ioc.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Container } from "inversify";
|
||||
|
||||
import { DotnetTool, GitVersionTool, VersionManager } from "../common";
|
||||
import { IBuildAgent, IDotnetTool, IGitVersionTool, IVersionManager } from "../interfaces";
|
||||
import { TYPES } from "../types";
|
||||
import { BuildAgent } from "./build-agent";
|
||||
|
||||
const ioc = new Container();
|
||||
|
||||
ioc.bind<IVersionManager>(TYPES.IVersionManager).to(VersionManager);
|
||||
ioc.bind<IBuildAgent>(TYPES.IBuildAgent).to(BuildAgent);
|
||||
ioc.bind<IDotnetTool>(TYPES.IDotnetTool).to(DotnetTool);
|
||||
ioc.bind<IGitVersionTool>(TYPES.IGitVersionTool).to(GitVersionTool);
|
||||
|
||||
export { ioc };
|
||||
24
src/azure/main.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import "reflect-metadata";
|
||||
|
||||
import { IBuildAgent, IGitVersionTool } from "../interfaces";
|
||||
import { TYPES } from "../types";
|
||||
import { ioc } from "./ioc";
|
||||
|
||||
const gitVersionTool = ioc.get<IGitVersionTool>(TYPES.IGitVersionTool);
|
||||
const buildAgent = ioc.get<IBuildAgent>(TYPES.IBuildAgent);
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
|
||||
const version = "5.1.2";
|
||||
const includePrerelease = false;
|
||||
|
||||
await gitVersionTool.install(version, includePrerelease);
|
||||
|
||||
buildAgent.setSucceeded("GitVersion executed successfully", true);
|
||||
} catch (error) {
|
||||
buildAgent.setFailed(error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -1,6 +0,0 @@
|
||||
Versioning when using Git, solved. GitVersion looks at your Git history and works out the [semantic version](http://semver.org) of the commit being built.
|
||||
|
||||
It works with most branching strategies but has been designed mainly around GitFlow and GitHubFlow (pull request workflow). The calculated version numbers can then be accessed through variables such as `$(GitVersion.NuGetVersion)` and `$(GitVersion.SemVer)`. It is also very configurable to allow it to work with most release workflows!
|
||||
|
||||

|
||||

|
||||
@@ -1,82 +0,0 @@
|
||||
import * as path from 'path';
|
||||
|
||||
import * as ma from 'azure-pipelines-task-lib/mock-answer';
|
||||
import * as tmrm from 'azure-pipelines-task-lib/mock-run';
|
||||
import * as shared from './test-shared';
|
||||
|
||||
let taskDir = path.join(__dirname, '..');
|
||||
let taskPath = path.join(taskDir, 'GitVersion.js');
|
||||
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);
|
||||
|
||||
process.env['BUILD_SOURCESDIRECTORY'] = shared.SharedValues.BUILD_SOURCESDIRECTORY;
|
||||
process.env["INSTALL_TOOL"] = 'false';
|
||||
|
||||
tmr.setInput('versionSpec', process.env[shared.TestEnvVars.versionSpec] || '5.x');
|
||||
tmr.setInput('includePrerelease', process.env[shared.TestEnvVars.includePrerelease] || 'false');
|
||||
tmr.setInput('targetPath', process.env[shared.TestEnvVars.targetPath] || '');
|
||||
|
||||
tmr.setInput('useConfigFile', process.env[shared.TestEnvVars.useConfigFile] || 'false');
|
||||
tmr.setInput('configFilePath', process.env[shared.TestEnvVars.configFilePath] || '');
|
||||
|
||||
tmr.setInput('updateAssemblyInfo', process.env[shared.TestEnvVars.updateAssemblyInfo] || 'false');
|
||||
tmr.setInput('updateAssemblyInfoFilename', process.env[shared.TestEnvVars.updateAssemblyInfoFilename] || '');
|
||||
|
||||
tmr.setInput('additionalArguments', process.env[shared.TestEnvVars.additionalArguments] || '');
|
||||
|
||||
console.log("Inputs have been set");
|
||||
|
||||
let a: ma.TaskLibAnswers = <ma.TaskLibAnswers>{
|
||||
"which": { "dotnet-gitversion": "dotnet-gitversion" },
|
||||
"checkPath": { "dotnet-gitversion": true },
|
||||
"exec": {},
|
||||
"exist": {
|
||||
"src": true,
|
||||
"customConfig.yml" : true,
|
||||
"GlobalAssemblyInfo.cs" : true
|
||||
},
|
||||
"stats": {
|
||||
"src" : {
|
||||
"isDirectory" : true
|
||||
},
|
||||
"customConfig.yml" : {
|
||||
"isFile": true
|
||||
},
|
||||
"GlobalAssemblyInfo.cs" : {
|
||||
"isFile": true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
a.exec["dotnet-gitversion " + shared.SharedValues.BUILD_SOURCESDIRECTORY + " /output buildserver /nofetch"] = {
|
||||
"code": 0,
|
||||
"stdout": "GitVersion run successfully with defaults",
|
||||
"stderr": ""
|
||||
};
|
||||
|
||||
a.exec["dotnet-gitversion " + shared.SharedValues.BUILD_SOURCESDIRECTORY + "/src /output buildserver /nofetch"] = {
|
||||
"code": 0,
|
||||
"stdout": "GitVersion run successfully with custom targetPath",
|
||||
"stderr": ""
|
||||
};
|
||||
|
||||
a.exec["dotnet-gitversion " + shared.SharedValues.BUILD_SOURCESDIRECTORY + " /output buildserver /nofetch /config customConfig.yml"] = {
|
||||
"code": 0,
|
||||
"stdout": "GitVersion run successfully with custom config",
|
||||
"stderr": ""
|
||||
};
|
||||
|
||||
a.exec["dotnet-gitversion " + shared.SharedValues.BUILD_SOURCESDIRECTORY + " /output buildserver /nofetch /updateassemblyinfo GlobalAssemblyInfo.cs"] = {
|
||||
"code": 0,
|
||||
"stdout": "GitVersion run successfully with custom assembly info",
|
||||
"stderr": ""
|
||||
};
|
||||
|
||||
var mt = require('azure-pipelines-task-lib/mock-task');
|
||||
mt.assertAgent = (minimum: string) =>
|
||||
{
|
||||
};
|
||||
tmr.registerMockExport('mt', mt);
|
||||
|
||||
tmr.setAnswers(a);
|
||||
|
||||
tmr.run();
|
||||
@@ -1,14 +0,0 @@
|
||||
export let TestEnvVars = {
|
||||
versionSpec: "__versionSpec__",
|
||||
includePrerelease: "__includePrerelease__",
|
||||
targetPath: "__targetPath__",
|
||||
useConfigFile: "__useConfigFile__",
|
||||
configFilePath: "__configFilePath__",
|
||||
updateAssemblyInfo: "__updateAssemblyInfo__",
|
||||
updateAssemblyInfoFilename: "__updateAssemblyInfoFilename__",
|
||||
additionalArguments: "__additionalArguments__"
|
||||
}
|
||||
|
||||
export let SharedValues = {
|
||||
BUILD_SOURCESDIRECTORY: "/user/build"
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
import * as path from 'path';
|
||||
import * as assert from 'assert';
|
||||
import * as ttm from 'azure-pipelines-task-lib/mock-test';
|
||||
import * as shared from './test-shared';
|
||||
|
||||
function runValidations(validator: () => void, tr: ttm.MockTestRunner, done: MochaDone) {
|
||||
try {
|
||||
validator();
|
||||
console.log(tr.succeeded);
|
||||
done();
|
||||
}
|
||||
catch (error) {
|
||||
console.log("STDERR", tr.stderr);
|
||||
console.log("STDOUT", tr.stdout);
|
||||
done(error);
|
||||
}
|
||||
}
|
||||
|
||||
describe('GitVersion Vsix Task tests', function () {
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env[shared.TestEnvVars.useConfigFile];
|
||||
delete process.env[shared.TestEnvVars.configFilePath];
|
||||
delete process.env[shared.TestEnvVars.updateAssemblyInfo];
|
||||
delete process.env[shared.TestEnvVars.updateAssemblyInfoFilename];
|
||||
delete process.env[shared.TestEnvVars.additionalArguments];
|
||||
delete process.env[shared.TestEnvVars.targetPath];
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
||||
});
|
||||
|
||||
it('Succeeds: Runs GitVersion default configurations', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.succeeded, 'should have succeeded');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 0, "should have no errors");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 1, 'should have invoked tool one time. actual: ' + tr.invokedToolCount);
|
||||
assert(tr.ran("dotnet-gitversion /user/build /output buildserver /nofetch"));
|
||||
|
||||
assert(tr.stdOutContained('GitVersion run successfully with defaults'), "should display 'GitVersion run successfully with defaults'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Fails: Runs GitVersion with wrong targetPath', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.targetPath] = 'wrongPath';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.failed, 'should have failed');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 1, "should have thrown an error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 0, 'should not have invoked tool. actual: ' + tr.invokedToolCount);
|
||||
|
||||
assert(tr.stdOutContained('Directory not found'), "should display 'Directory not found'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Succeeds: Runs GitVersion with correct target', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.targetPath] = 'src';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.succeeded, 'should have succeeded');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 0, "should have no errors");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 1, 'should have invoked tool one time. actual: ' + tr.invokedToolCount);
|
||||
assert(tr.ran("dotnet-gitversion /user/build/src /output buildserver /nofetch"));
|
||||
|
||||
assert(tr.stdOutContained('GitVersion run successfully with custom targetPath'), "should display 'GitVersion run successfully with custom targetPath'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Fails: Runs GitVersion with no configuration file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.useConfigFile] = 'true';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert.equal(tr.succeeded, false, 'should have failed');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 1, "should have thrown an error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 0, 'should not have invoked tool. actual: ' + tr.invokedToolCount);
|
||||
|
||||
assert(tr.stdOutContained('GitVersion configuration file not found'), "should display 'GitVersion configuration file not found'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Fails: Runs GitVersion with wrong configuration file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.useConfigFile] = 'true';
|
||||
process.env[shared.TestEnvVars.configFilePath] = 'wronfConfig.yml';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.failed, 'should have failed');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 1, "should have thrown an error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 0, 'should not have invoked tool. actual: ' + tr.invokedToolCount);
|
||||
|
||||
assert(tr.stdOutContained('GitVersion configuration file not found'), "should display 'GitVersion configuration file not found'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Succeeds: Runs GitVersion with correct custom configuration file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.useConfigFile] = 'true';
|
||||
process.env[shared.TestEnvVars.configFilePath] = 'customConfig.yml';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.succeeded, 'should have succeeded');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 0, "should have no error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 1, 'should have invoked tool one time. actual: ' + tr.invokedToolCount);
|
||||
assert(tr.ran("dotnet-gitversion /user/build /output buildserver /nofetch /config customConfig.yml"));
|
||||
|
||||
assert(tr.stdOutContained('GitVersion run successfully with custom config'), "should display 'GitVersion run successfully with custom config'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Fails: Runs GitVersion with no assembly info file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.updateAssemblyInfo] = 'true';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.failed, 'should have failed');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 1, "should have thrown an error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 0, 'should not have invoked tool. actual: ' + tr.invokedToolCount);
|
||||
|
||||
assert(tr.stdOutContained('AssemblyInfoFilename file not found'), "should display 'AssemblyInfoFilename file not found'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Fails: Runs GitVersion with wrong assembly info file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.updateAssemblyInfo] = 'true';
|
||||
process.env[shared.TestEnvVars.updateAssemblyInfoFilename] = 'wrongAssemblyInfo.cs';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.failed, 'should have failed');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 1, "should have thrown an error");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 0, 'should not have invoked tool. actual: ' + tr.invokedToolCount);
|
||||
|
||||
assert(tr.stdOutContained('AssemblyInfoFilename file not found'), "should display 'AssemblyInfoFilename file not found'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
|
||||
it('Succeeds: Runs GitVersion with correct custom assembly info file specified', function (done: MochaDone) {
|
||||
this.timeout(1000);
|
||||
|
||||
process.env[shared.TestEnvVars.updateAssemblyInfo] = 'true';
|
||||
process.env[shared.TestEnvVars.updateAssemblyInfoFilename] = 'GlobalAssemblyInfo.cs';
|
||||
|
||||
let tp = path.join(__dirname, 'test-setup.js');
|
||||
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
|
||||
|
||||
tr.run();
|
||||
|
||||
runValidations(() => {
|
||||
|
||||
assert(tr.succeeded, 'should have succeeded');
|
||||
assert(tr.warningIssues.length == 0, "should have no warnings");
|
||||
assert(tr.errorIssues.length == 0, "should have no errors");
|
||||
assert(tr.stderr.length == 0, 'should not have written to stderr');
|
||||
assert(tr.invokedToolCount == 1, 'should have invoked tool one time. actual: ' + tr.invokedToolCount);
|
||||
assert(tr.ran("dotnet-gitversion /user/build /output buildserver /nofetch /updateassemblyinfo GlobalAssemblyInfo.cs"));
|
||||
|
||||
assert(tr.stdOutContained('GitVersion run successfully with custom assembly info'), "should display 'GitVersion run successfully with custom assembly info'");
|
||||
|
||||
}, tr, done);
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"target": "es6",
|
||||
"sourceMap": false,
|
||||
"inlineSourceMap": true,
|
||||
"declaration": false
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,3 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"target": "es6",
|
||||
"sourceMap": false,
|
||||
"inlineSourceMap": true
|
||||
},
|
||||
"exclude": ["tests"]
|
||||
}
|
||||
"extends": "../tsconfig.json"
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
{
|
||||
"manifestVersion": 1,
|
||||
"id": "usegitversion-preview",
|
||||
"name": "UseGitVersion (Preview)",
|
||||
"publisher": "gittools",
|
||||
"public": true,
|
||||
"author": "GitVersion Contributors",
|
||||
"version": "5.1.3.1911100642",
|
||||
"description": "Build task for easy semantic versioning for projects using Git.",
|
||||
"targets": [{
|
||||
"id": "Microsoft.VisualStudio.Services"
|
||||
}],
|
||||
"files": [
|
||||
{ "path": "GitVersionTask" }
|
||||
],
|
||||
"categories": [
|
||||
"Azure Pipelines"
|
||||
],
|
||||
"galleryFlags": [
|
||||
"Preview"
|
||||
],
|
||||
"icons": {
|
||||
"default": "images/extension-icon.png"
|
||||
},
|
||||
"tags": [
|
||||
"semver",
|
||||
"git",
|
||||
"versioning",
|
||||
"gitflow",
|
||||
"githubflow"
|
||||
],
|
||||
"links": {
|
||||
"learn": {
|
||||
"uri": "http://gitversion.readthedocs.org/en/stable"
|
||||
},
|
||||
"getstarted": {
|
||||
"uri": "http://gitversion.readthedocs.org/en/stable/build-server-support/build-server/tfs-build-vnext/#running-inside-tfs"
|
||||
},
|
||||
"license": {
|
||||
"uri": "https://github.com/GitTools/GitVersion/blob/master/LICENSE"
|
||||
},
|
||||
"repository": {
|
||||
"uri": "https://github.com/GitTools/GitVersion"
|
||||
},
|
||||
"support": {
|
||||
"uri": "https://github.com/GitTools/GitVersion/issues"
|
||||
}
|
||||
},
|
||||
"screenshots": [{
|
||||
"path": "images/builds.png"
|
||||
},
|
||||
{
|
||||
"path": "images/build-task.png"
|
||||
}
|
||||
],
|
||||
"content": {
|
||||
"details": {
|
||||
"path": "overview.md"
|
||||
}
|
||||
},
|
||||
"contributions": [{
|
||||
"id": "gitversion-task",
|
||||
"type": "ms.vss-distributed-task.task",
|
||||
"targets": [
|
||||
"ms.vss-distributed-task.tasks"
|
||||
],
|
||||
"properties": {
|
||||
"name": "GitVersionTask"
|
||||
}
|
||||
}]
|
||||
}
|
||||
219
src/common.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as semver from "semver";
|
||||
import * as http from "typed-rest-client/HttpClient";
|
||||
|
||||
import { inject, injectable } from "inversify";
|
||||
|
||||
import { Argument, IBuildAgent, IDotnetTool, IExecResult, IGitVersionTool, IVersionManager } from "./interfaces";
|
||||
import { TYPES } from "./types";
|
||||
|
||||
@injectable()
|
||||
class DotnetTool implements IDotnetTool {
|
||||
|
||||
private buildAgent: IBuildAgent;
|
||||
private versionManager: IVersionManager;
|
||||
private httpClient: http.HttpClient;
|
||||
|
||||
constructor(
|
||||
@inject(TYPES.IBuildAgent) buildAgent: IBuildAgent,
|
||||
@inject(TYPES.IVersionManager) versionManager: IVersionManager,
|
||||
) {
|
||||
this.buildAgent = buildAgent;
|
||||
this.versionManager = versionManager;
|
||||
this.httpClient = new http.HttpClient("dotnet");
|
||||
}
|
||||
|
||||
public run(args: string[]): Promise<IExecResult> {
|
||||
return this.buildAgent.exec("dotnet", 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("--------------------------");
|
||||
|
||||
if (this.versionManager.isExplicitVersion(versionSpec)) {
|
||||
checkLatest = false; // check latest doesn't make sense when explicit version
|
||||
}
|
||||
|
||||
let toolPath: string;
|
||||
if (!checkLatest) {
|
||||
//
|
||||
// Let's try and resolve the version spec locally first
|
||||
//
|
||||
toolPath = this.buildAgent.find(toolName, versionSpec);
|
||||
}
|
||||
|
||||
if (!toolPath) {
|
||||
let version: string;
|
||||
if (this.versionManager.isExplicitVersion(versionSpec)) {
|
||||
//
|
||||
// Explicit version was specified. No need to query for list of versions.
|
||||
//
|
||||
version = versionSpec;
|
||||
} else {
|
||||
//
|
||||
// Let's query and resolve the latest version for the versionSpec.
|
||||
// If the version is an explicit version (1.1.1 or v1.1.1) then no need to query.
|
||||
// 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);
|
||||
if (!version) {
|
||||
throw new Error(`Unable to find ${toolName} version '${versionSpec}'.`);
|
||||
}
|
||||
|
||||
//
|
||||
// Check the cache for the resolved version.
|
||||
//
|
||||
toolPath = this.buildAgent.find(toolName, version);
|
||||
}
|
||||
if (!toolPath) {
|
||||
//
|
||||
// Download, extract, cache
|
||||
//
|
||||
toolPath = await this.acquireTool(toolName, version);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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") {
|
||||
const dotnetRoot = path.dirname(fs.readlinkSync(await this.buildAgent.which("dotnet")));
|
||||
this.buildAgent.exportVariable("DOTNET_ROOT", dotnetRoot);
|
||||
}
|
||||
this.buildAgent.addPath(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" : ""}`);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const body: string = await res.readBody();
|
||||
const data = JSON.parse(body).data;
|
||||
|
||||
const versions = (data[0].versions as Array<{ 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);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
const result = await this.run(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}`);
|
||||
|
||||
if (result.code) {
|
||||
throw new Error("Error installing tool");
|
||||
}
|
||||
|
||||
return await this.buildAgent.cacheDir(tempDirectory, toolName, version);
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
class GitVersionTool implements IGitVersionTool {
|
||||
|
||||
private dotnetTool: IDotnetTool;
|
||||
constructor(
|
||||
@inject(TYPES.IDotnetTool) dotnetTool: IDotnetTool,
|
||||
) {
|
||||
this.dotnetTool = dotnetTool;
|
||||
}
|
||||
|
||||
public async install(versionSpec: string, includePrerelease: boolean): Promise<void> {
|
||||
const toolPath = await this.dotnetTool.toolInstall("GitVersion.Tool", versionSpec, false, includePrerelease);
|
||||
}
|
||||
|
||||
public run(...params: Argument[]): Promise<IExecResult> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const cmp = require("semver-compare");
|
||||
|
||||
@injectable()
|
||||
class VersionManager implements IVersionManager {
|
||||
|
||||
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 valid = semver.valid(c) != null;
|
||||
this.buildAgent.debug("explicit? " + valid);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
public evaluateVersions(versions: string[], versionSpec: string): string {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (version) {
|
||||
this.buildAgent.debug("matched: " + version);
|
||||
} else {
|
||||
this.buildAgent.debug("match not found");
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public cleanVersion(version: string): string {
|
||||
this.buildAgent.debug("cleaning: " + version);
|
||||
return semver.clean(version);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
DotnetTool,
|
||||
GitVersionTool,
|
||||
VersionManager,
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import { ToolInstaller } from '../ToolInstaller';
|
||||
import { Proxy as utils } from './Proxy';
|
||||
try {
|
||||
let toolInstaller = new ToolInstaller(utils);
|
||||
toolInstaller.downloadAndInstall('GitVersion.Tool', '5.1.2', false, false);
|
||||
// `who-to-greet` input defined in action metadata file
|
||||
const nameToGreet = core.getInput('who-to-greet');
|
||||
console.log(`Hello ${nameToGreet}!`);
|
||||
const time = (new Date()).toTimeString();
|
||||
core.setOutput("time", time);
|
||||
// Get the JSON webhook payload for the event that triggered the workflow
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { find, cacheDir } from '@actions/tool-cache';
|
||||
import { debug, exportVariable, addPath } from '@actions/core';
|
||||
import { which } from '@actions/io';
|
||||
|
||||
import { isExplicitVersion, evaluateVersions, createTempDir, cleanVersion, executeDotNet } from './ToolLib';
|
||||
import { IProxy } from '../Interfaces';
|
||||
|
||||
export const Proxy: IProxy = {
|
||||
find : find,
|
||||
debug: debug,
|
||||
exportVariable: exportVariable,
|
||||
addPath: addPath,
|
||||
which: which,
|
||||
cacheDir: cacheDir,
|
||||
isExplicitVersion: isExplicitVersion,
|
||||
evaluateVersions: evaluateVersions,
|
||||
cleanVersion: cleanVersion,
|
||||
createTempDir: createTempDir,
|
||||
executeDotNet: executeDotNet
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as uuidV4 from "uuid/v4";
|
||||
|
||||
import * as io from '@actions/io';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import { IExecSyncResult } from '../Interfaces';
|
||||
|
||||
const cmp = require('semver-compare');
|
||||
|
||||
export async function createTempDir(): Promise<string> {
|
||||
const IS_WINDOWS = process.platform === "win32";
|
||||
|
||||
let tempDirectory: string = process.env["RUNNER_TEMP"] || "";
|
||||
|
||||
if (!tempDirectory) {
|
||||
let baseLocation: string;
|
||||
if (IS_WINDOWS) {
|
||||
// On Windows use the USERPROFILE env variable
|
||||
baseLocation = process.env["USERPROFILE"] || "C:\\";
|
||||
} else {
|
||||
if (process.platform === "darwin") {
|
||||
baseLocation = "/Users";
|
||||
} else {
|
||||
baseLocation = "/home";
|
||||
}
|
||||
}
|
||||
tempDirectory = path.join(baseLocation, "actions", "temp");
|
||||
}
|
||||
const dest = path.join(tempDirectory, uuidV4());
|
||||
await io.mkdirP(dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a version spec is an explicit version (e.g. 1.0.1 or v1.0.1)
|
||||
* As opposed to a version spec like 1.x
|
||||
*
|
||||
* @param versionSpec
|
||||
*/
|
||||
export function isExplicitVersion(versionSpec: string): boolean {
|
||||
let c = semver.clean(versionSpec);
|
||||
core.debug('isExplicit: ' + c);
|
||||
|
||||
let valid = semver.valid(c) != null;
|
||||
core.debug('explicit? ' + valid);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cleaned (removed leading/trailing whitespace, remove '=v' prefix)
|
||||
* and parsed version, or null if version is invalid.
|
||||
*/
|
||||
export function cleanVersion(version: string): string {
|
||||
core.debug('cleaning: ' + version);
|
||||
return semver.clean(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* evaluates a list of versions and returns the latest version matching the version spec
|
||||
*
|
||||
* @param versions an array of versions to evaluate
|
||||
* @param versionSpec a version spec (e.g. 1.x)
|
||||
*/
|
||||
export function evaluateVersions(versions: string[], versionSpec: string): string {
|
||||
let version: string;
|
||||
core.debug('evaluating ' + versions.length + ' versions');
|
||||
versions = versions.sort(cmp);
|
||||
for (let i = versions.length - 1; i >= 0; i--) {
|
||||
let potential: string = versions[i];
|
||||
let satisfied: boolean = semver.satisfies(potential, versionSpec);
|
||||
if (satisfied) {
|
||||
version = potential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (version) {
|
||||
core.debug('matched: ' + version);
|
||||
}
|
||||
else {
|
||||
core.debug('match not found');
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
export async function executeDotNet(args: string[]) : Promise<IExecSyncResult> {
|
||||
let dotnetPath = await io.which("dotnet", true);
|
||||
let resultCode = 0;
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
resultCode = await exec.exec(
|
||||
`"${dotnetPath}"`,
|
||||
args,
|
||||
{
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout += data.toString();
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
stderr += data.toString();
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
code: resultCode,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
error: null
|
||||
}
|
||||
}
|
||||
101
src/github/build-agent.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import * as path from "path";
|
||||
import * as uuidV4 from "uuid/v4";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as exe from "@actions/exec";
|
||||
import * as io from "@actions/io";
|
||||
import * as toolCache from "@actions/tool-cache";
|
||||
|
||||
import { injectable } from "inversify";
|
||||
|
||||
import { IBuildAgent, IExecResult } from "../interfaces";
|
||||
|
||||
@injectable()
|
||||
class BuildAgent implements IBuildAgent {
|
||||
|
||||
public find(toolName: string, versionSpec: string, arch?: string): string {
|
||||
return toolCache.find(toolName, versionSpec, arch);
|
||||
}
|
||||
|
||||
public cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise<string> {
|
||||
return toolCache.cacheDir(sourceDir, tool, version, arch);
|
||||
}
|
||||
|
||||
public async createTempDir(): Promise<string> {
|
||||
const IS_WINDOWS = process.platform === "win32";
|
||||
|
||||
let tempDirectory: string = process.env.RUNNER_TEMP || "";
|
||||
|
||||
if (!tempDirectory) {
|
||||
let baseLocation: string;
|
||||
if (IS_WINDOWS) {
|
||||
// On Windows use the USERPROFILE env variable
|
||||
baseLocation = process.env.USERPROFILE || "C:\\";
|
||||
} else {
|
||||
if (process.platform === "darwin") {
|
||||
baseLocation = "/Users";
|
||||
} else {
|
||||
baseLocation = "/home";
|
||||
}
|
||||
}
|
||||
tempDirectory = path.join(baseLocation, "actions", "temp");
|
||||
}
|
||||
const dest = path.join(tempDirectory, uuidV4());
|
||||
await io.mkdirP(dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
public debug(message: string): void {
|
||||
core.debug(message);
|
||||
}
|
||||
|
||||
public setFailed(message: string, done?: boolean): void {
|
||||
core.setFailed(message);
|
||||
}
|
||||
|
||||
public setSucceeded(message: string, done?: boolean): void {
|
||||
//
|
||||
}
|
||||
|
||||
public exportVariable(name: string, val: string): void {
|
||||
core.exportVariable(name, val);
|
||||
}
|
||||
|
||||
public addPath(inputPath: string): void {
|
||||
core.addPath(inputPath);
|
||||
}
|
||||
|
||||
public which(tool: string, check?: boolean): Promise<string> {
|
||||
return io.which(tool, check);
|
||||
}
|
||||
|
||||
public async exec(exec: string, args: string[]): Promise<IExecResult> {
|
||||
const dotnetPath = await io.which(exec, true);
|
||||
let resultCode = 0;
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
resultCode = await exe.exec(
|
||||
`"${dotnetPath}"`,
|
||||
args,
|
||||
{
|
||||
listeners: {
|
||||
stderr: (data: Buffer) => {
|
||||
stderr += data.toString();
|
||||
},
|
||||
stdout: (data: Buffer) => {
|
||||
stdout += data.toString();
|
||||
},
|
||||
},
|
||||
});
|
||||
return {
|
||||
code: resultCode,
|
||||
error: null,
|
||||
stderr,
|
||||
stdout,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
BuildAgent,
|
||||
};
|
||||
15
src/github/ioc.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Container } from "inversify";
|
||||
|
||||
import { DotnetTool, GitVersionTool, VersionManager } from "../common";
|
||||
import { IBuildAgent, IDotnetTool, IGitVersionTool, IVersionManager } from "../interfaces";
|
||||
import { TYPES } from "../types";
|
||||
import { BuildAgent } from "./build-agent";
|
||||
|
||||
const ioc = new Container();
|
||||
|
||||
ioc.bind<IVersionManager>(TYPES.IVersionManager).to(VersionManager);
|
||||
ioc.bind<IBuildAgent>(TYPES.IBuildAgent).to(BuildAgent);
|
||||
ioc.bind<IDotnetTool>(TYPES.IDotnetTool).to(DotnetTool);
|
||||
ioc.bind<IGitVersionTool>(TYPES.IGitVersionTool).to(GitVersionTool);
|
||||
|
||||
export { ioc };
|
||||
24
src/github/main.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import "reflect-metadata";
|
||||
|
||||
import { IBuildAgent, IGitVersionTool } from "../interfaces";
|
||||
import { TYPES } from "../types";
|
||||
import { ioc } from "./ioc";
|
||||
|
||||
const gitVersionTool = ioc.get<IGitVersionTool>(TYPES.IGitVersionTool);
|
||||
const buildAgent = ioc.get<IBuildAgent>(TYPES.IBuildAgent);
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
|
||||
const version = "5.1.2";
|
||||
const includePrerelease = false;
|
||||
|
||||
await gitVersionTool.install(version, includePrerelease);
|
||||
|
||||
buildAgent.setSucceeded("GitVersion executed successfully", true);
|
||||
} catch (error) {
|
||||
buildAgent.setFailed(error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -1,13 +1,3 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"target": "es6",
|
||||
"sourceMap": false,
|
||||
"inlineSourceMap": true,
|
||||
"declaration": false
|
||||
}
|
||||
}
|
||||
"extends": "../tsconfig.json"
|
||||
}
|
||||
13
src/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2015",
|
||||
"sourceMap": false,
|
||||
"lib": ["es2015", "dom"],
|
||||
"types": ["reflect-metadata"],
|
||||
"inlineSourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
}
|
||||
}
|
||||
8
src/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const TYPES = {
|
||||
IBuildAgent: Symbol.for("BuildAgent"),
|
||||
IDotnetTool: Symbol.for("DotnetTool"),
|
||||
IGitVersionTool: Symbol.for("GitVersionTool"),
|
||||
IVersionManager: Symbol.for("VersionManager"),
|
||||
};
|
||||
|
||||
export { TYPES };
|
||||
13
tslint.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [
|
||||
"tslint:recommended"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"max-classes-per-file":false,
|
||||
"no-console":false,
|
||||
"no-var-requires":false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||