diff --git a/.github/workflows/autoAssignABTT.yml b/.github/workflows/autoAssignABTT.yml new file mode 100644 index 000000000000..addd720fae88 --- /dev/null +++ b/.github/workflows/autoAssignABTT.yml @@ -0,0 +1,20 @@ +name: Auto Assign ABTT to Project Board + +on: + issues: + types: [opened, labeled] +env: + MY_GITHUB_TOKEN: ${{ secrets.ABTT_TOKEN }} + +jobs: + assign_one_project: + runs-on: ubuntu-latest + name: Assign to ABTT Project + steps: + - name: "Assign issues with 'Area: ABTT' label to project board" + uses: srggrs/assign-one-project-github-action@1.2.0 + if: | + contains(github.event.issue.labels.*.name, 'Area: ABTT') + with: + project: 'https://github.com/orgs/microsoft/projects/48' + column_name: 'Ready for work' diff --git a/Tasks/ACRTaskV0/Strings/resources.resjson/en-US/resources.resjson b/Tasks/ACRTaskV0/Strings/resources.resjson/en-US/resources.resjson index 05410891f7c3..bd6d54a6e6d7 100644 --- a/Tasks/ACRTaskV0/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/ACRTaskV0/Strings/resources.resjson/en-US/resources.resjson @@ -35,6 +35,8 @@ "loc.input.help.architecture": "Architecture", "loc.input.label.cwd": "Working Directory", "loc.input.help.cwd": "Current working directory where the script(not ACR) is run. Empty is the root of the repo (build) or artifacts (release), which is $(System.DefaultWorkingDirectory)", + "loc.input.label.pat": "PAT for updating the baseimage trigger", + "loc.input.help.pat": "This PAT would be passed down to the baseImageTrigger field to trigger this pipeline whenever the base image is updated", "loc.messages.InvalidEndpointAuthScheme": "Invalid GitHub service connection scheme: %s. Only Token, OAuth and GitHub personal access token connections are allowed.", "loc.messages.InvalidGithubEndpoint": "Invalid GitHub service endpoint: %s.", "loc.messages.TaskConstructorFailed": "Task failed while initializing. Error: %s", diff --git a/Tasks/ACRTaskV0/models/acrtaskrequestbody.ts b/Tasks/ACRTaskV0/models/acrtaskrequestbody.ts index 7aa865e29f52..b5935c09fb94 100644 --- a/Tasks/ACRTaskV0/models/acrtaskrequestbody.ts +++ b/Tasks/ACRTaskV0/models/acrtaskrequestbody.ts @@ -63,6 +63,8 @@ export interface IBaseImageTrigger { status: string; baseImageTriggerType: string; name: string; + updateTriggerEndpoint: string; + updateTriggerPayloadType: string; } export interface ITrigger { diff --git a/Tasks/ACRTaskV0/operations/acrtaskclient.ts b/Tasks/ACRTaskV0/operations/acrtaskclient.ts index d6de30673ed6..693f64eb8502 100644 --- a/Tasks/ACRTaskV0/operations/acrtaskclient.ts +++ b/Tasks/ACRTaskV0/operations/acrtaskclient.ts @@ -1,6 +1,6 @@ import msRestAzure = require('azure-arm-rest-v2/azure-arm-common'); import webClient = require("azure-arm-rest-v2/webClient"); -import { ApiResult, ApiCallback, ToError } from "azure-arm-rest-v2/AzureServiceClientBase" ; +import { ApiResult, ApiCallback, ToError } from "azure-arm-rest-v2/AzureServiceClientBase"; import { ServiceClient } from "azure-arm-rest-v2/AzureServiceClient" import tl = require("azure-pipelines-task-lib/task"); import * as yaml from "js-yaml"; @@ -10,25 +10,24 @@ import { AcrTask } from "../models/acrtaskparameters"; import * as semver from 'semver'; import { tinyGuid } from 'utility-common-v2/tinyGuidUtility' -const acrTaskbaseUri : string = "//subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerRegistry/registries/{registryName}" ; -const dummyContextUrl : string = tl.getVariable('system.TeamFoundationCollectionUri'); +const acrTaskbaseUri: string = "//subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerRegistry/registries/{registryName}"; +const dummyContextUrl: string = tl.getVariable('system.TeamFoundationCollectionUri'); export class AcrTaskClient extends ServiceClient { - public createTask : boolean = false; - public updateTask : boolean = false; + public createTask: boolean = false; + public updateTask: boolean = false; public acrTask: AcrTask; - constructor(credentials: msRestAzure.ApplicationTokenCredentials, + constructor(credentials: msRestAzure.ApplicationTokenCredentials, subscriptionId: string, acrTask: AcrTask) { super(credentials, subscriptionId); - + this.acrTask = acrTask; this.apiVersion = '2019-06-01-preview'; } - public async getBuildSourceUploadUrl(callback?: ApiCallback) - { + public async getBuildSourceUploadUrl(callback?: ApiCallback) { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -38,7 +37,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + var requestUri = this.getRequestUri( `${acrTaskbaseUri}/listBuildSourceUploadUrl`, { @@ -61,11 +60,10 @@ export class AcrTaskClient extends ServiceClient { return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); + (error) => callback(error)); } - public async getTask(callback?: ApiCallback) - { + public async getTask(callback?: ApiCallback) { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -76,7 +74,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + var requestUri = this.getRequestUri( `${acrTaskbaseUri}/tasks/{taskName}`, { @@ -96,8 +94,7 @@ export class AcrTaskClient extends ServiceClient { console.log(tl.loc("UpdateAcrTask", this.acrTask.name)); return new ApiResult(null, response.body); } - else if (statusCode === 404) - { + else if (statusCode === 404) { this.createTask = true; console.log(tl.loc("CreateAcrTask", this.acrTask.name, this.acrTask.name)); return new ApiResult(null); @@ -107,11 +104,10 @@ export class AcrTaskClient extends ServiceClient { return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); + (error) => callback(error)); } - public async createOrUpdateTask(callback?: ApiCallback) - { + public async createOrUpdateTask(callback?: ApiCallback) { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -131,14 +127,13 @@ export class AcrTaskClient extends ServiceClient { '{taskName}': acrTaskName }); - var requestMethod = "PUT"; - if (this.updateTask) - { + var requestMethod = "PUT"; + if (this.updateTask) { requestMethod = 'PATCH'; } var httpRequest = this._createHttpRequest(requestMethod, requestUri); - let requestBody : AcrTaskRequest.IAcrTaskRequestBody = this._getRequestBodyForAddOrUpdateTask(); + let requestBody: AcrTaskRequest.IAcrTaskRequestBody = this._getRequestBodyForAddOrUpdateTask(); tl.debug(JSON.stringify(requestBody)); httpRequest.body = JSON.stringify(requestBody); @@ -146,16 +141,14 @@ export class AcrTaskClient extends ServiceClient { var statusCode = response.statusCode; if (statusCode === 200) { // Generate Response - if(this.createTask) - { + if (this.createTask) { console.log(tl.loc("CreatedAcrTask", this.acrTask.name)); } - else - { + else { console.log(tl.loc("UpdatedAcrTask", this.acrTask.name)); } - return new ApiResult(null, response); + return new ApiResult(null, response); } else { // Generate exception @@ -165,8 +158,7 @@ export class AcrTaskClient extends ServiceClient { (error) => callback(error)); } - public runTask(taskId: string, callback?: ApiCallback): void - { + public runTask(taskId: string, callback?: ApiCallback): void { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -177,7 +169,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + const requestMethod = "POST"; var requestUri = this.getRequestUri( `${acrTaskbaseUri}/scheduleRun`, @@ -188,13 +180,12 @@ export class AcrTaskClient extends ServiceClient { var httpRequest = this._createHttpRequest(requestMethod, requestUri); let requestbody = { - "type" : "TaskRunRequest", + "type": "TaskRunRequest", taskId: taskId, taskName: acrTaskName } as AcrTaskRequest.ITaskRunRequest; - - if (this.acrTask.contextType == "file") - { + + if (this.acrTask.contextType == "file") { let overrideTaskStepProperties = {} as AcrTaskRequest.IOverrideTaskStepProperties; // override contextPath overrideTaskStepProperties = { @@ -202,15 +193,14 @@ export class AcrTaskClient extends ServiceClient { contextPath: this.acrTask.context } as AcrTaskRequest.IOverrideTaskStepProperties; - if (this.acrTask.taskRequestStepType == AcrTaskRequest.TaskRequestStepType.EncodedTask) - { + if (this.acrTask.taskRequestStepType == AcrTaskRequest.TaskRequestStepType.EncodedTask) { var runValues = TaskUtil.getListOfTagValuesForImageNames(this.acrTask); overrideTaskStepProperties.values = runValues; } requestbody.overrideTaskStepProperties = overrideTaskStepProperties; - } - + } + httpRequest.body = JSON.stringify(requestbody); console.log(tl.loc("RunAcrTask", acrTaskName)); console.log(JSON.stringify(requestbody)); @@ -227,11 +217,10 @@ export class AcrTaskClient extends ServiceClient { return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); + (error) => callback(error)); } - public cancelRun(runId: string, callback?: ApiCallback): void - { + public cancelRun(runId: string, callback?: ApiCallback): void { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -242,7 +231,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + const requestMethod = "POST"; var requestUri = this.getRequestUri( `${acrTaskbaseUri}/runs/{runId}/cancel`, @@ -257,21 +246,19 @@ export class AcrTaskClient extends ServiceClient { console.log(tl.loc("CancelAcrTaskRun", runId, acrTaskName)); this.beginRequest(httpRequest).then(async (response: webClient.WebResponse) => { var statusCode = response.statusCode; - if (statusCode === 200 || statusCode === 202) - { + if (statusCode === 200 || statusCode === 202) { console.log(tl.loc("CancelledAcrTaskRun", runId, acrTaskName)); return new ApiResult(null); } else { // Generate exception - return new ApiResult(ToError(response)); + return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); + (error) => callback(error)); } - public getLogLink(runId:string, callback?: ApiCallback): void - { + public getLogLink(runId: string, callback?: ApiCallback): void { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -281,7 +268,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + const requestMethod = "POST"; var requestUri = this.getRequestUri( `${acrTaskbaseUri}/runs/{runId}/listLogSasUrl`, @@ -306,11 +293,10 @@ export class AcrTaskClient extends ServiceClient { return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); + (error) => callback(error)); } - public getRun(runId:string, callback?: ApiCallback): void - { + public getRun(runId: string, callback?: ApiCallback): void { if (!callback) { throw new Error(tl.loc("CallbackCannotBeNull")); } @@ -320,7 +306,7 @@ export class AcrTaskClient extends ServiceClient { // Validate this._validateAcrInputs(); - + const requestMethod = "GET"; var requestUri = this.getRequestUri( `${acrTaskbaseUri}/runs/{runId}`, @@ -339,15 +325,14 @@ export class AcrTaskClient extends ServiceClient { } else { // Generate exception - return new ApiResult(ToError(response)); + return new ApiResult(ToError(response)); } }).then((apiResult: ApiResult) => callback(apiResult.error, apiResult.result), - (error) => callback(error)); - + (error) => callback(error)); + } - private _createHttpRequest(method: string, requestUri): webClient.WebRequest - { + private _createHttpRequest(method: string, requestUri): webClient.WebRequest { var httpRequest = new webClient.WebRequest(); httpRequest.method = method; httpRequest.headers = {}; @@ -355,47 +340,53 @@ export class AcrTaskClient extends ServiceClient { return httpRequest; } - private _getRequestBodyForAddOrUpdateTask() : AcrTaskRequest.IAcrTaskRequestBody - { - let tags: {[key: string]: string} = {}; + private _getRequestBodyForAddOrUpdateTask(): AcrTaskRequest.IAcrTaskRequestBody { + let tags: { [key: string]: string } = {}; tags["taskVersion"] = this._getTaskVersion(); let platform = { - os : tl.getInput("os"), - architecture : tl.getInput("architecture") - } as AcrTaskRequest.IPlatformProperties ; + os: tl.getInput("os"), + architecture: tl.getInput("architecture") + } as AcrTaskRequest.IPlatformProperties; let step = {} as AcrTaskRequest.ITaskStepProperties; - if (this.acrTask.taskRequestStepType === AcrTaskRequest.TaskRequestStepType.EncodedTask) - { + if (this.acrTask.taskRequestStepType === AcrTaskRequest.TaskRequestStepType.EncodedTask) { step = this._getEncodedTaskStep(); } - else - { + else { step = this._getFileTaskStep(); } var requestBody = { location: this.acrTask.registry.location, identity: { - "type" : "SystemAssigned" + "type": "SystemAssigned" }, - tags: tags, - properties: { + tags: tags, + properties: { "status": "Enabled", - platform : platform, + platform: platform, step: step as AcrTaskRequest.ITaskStepProperties - } - } as AcrTaskRequest.IAcrTaskRequestBody; - - if (this.acrTask.contextType == "git") - { + } + } as AcrTaskRequest.IAcrTaskRequestBody; + + if (this.acrTask.contextType == "git") { + const pat = tl.getInput("pat", false); + let triggerPipelineUrl = ""; + let triggerPayloadType = ""; + if (pat) { + triggerPipelineUrl = this.getPipelineUrl(pat); + triggerPayloadType = "token" + } + let triggerName = this.acrTask.name + tinyGuid(); - let baseImageTrigger = { + let baseImageTrigger = { status: "Enabled", baseImageTriggerType: "Runtime", - name: triggerName + name: triggerName, + updateTriggerEndpoint: triggerPipelineUrl, + updateTriggerPayloadType: triggerPayloadType } as AcrTaskRequest.IBaseImageTrigger - + let trigger = { baseImageTrigger: baseImageTrigger } as AcrTaskRequest.ITrigger @@ -408,96 +399,102 @@ export class AcrTaskClient extends ServiceClient { requestBody.properties.trigger = trigger; } - + return requestBody; } - private _getEncodedTaskStep(): AcrTaskRequest.EncodedTaskStep{ - try{ + private getPipelineUrl(pat: string) { + const orgUrl = tl.getVariable('System.TeamFoundationCollectionUri').replace("://", `://:${pat}@`); // this would convert https://dev.azure.com/mseng to https://:pat@dev.azure.com + + if (tl.getVariable('SYSTEM_HOSTTYPE').toLowerCase() === 'release') { + const definitionId = tl.getVariable('Release.DefinitionId'); + return `${orgUrl}_apis/release/releases?api-version=5.1&definitionId=${definitionId}` + } else { + const definitionId = tl.getVariable('System.DefinitionId'); + return `${orgUrl}_apis/build/builds?api-version=5.1&definitionId=${definitionId}` + } + } + + private _getEncodedTaskStep(): AcrTaskRequest.EncodedTaskStep { + try { var buildString = TaskUtil.createBuildCommand(this.acrTask); let imageNames: string[] = TaskUtil.getImageNames(this.acrTask); - var taskSteps : AcrTaskRequest.TaskStep[] = [] - + var taskSteps: AcrTaskRequest.TaskStep[] = [] + //add build step - var buildTaskStep = new AcrTaskRequest.TaskStep(); + var buildTaskStep = new AcrTaskRequest.TaskStep(); buildTaskStep.build = buildString; taskSteps.push(buildTaskStep); - + //add push step - var pushTaskStep = new AcrTaskRequest.TaskStep(); + var pushTaskStep = new AcrTaskRequest.TaskStep(); pushTaskStep.push = imageNames; taskSteps.push(pushTaskStep); - + // create task json var taskJson = new AcrTaskRequest.TaskJson(); taskJson.version = "v1.0.0"; taskJson.steps = taskSteps; - + //convert to yaml var yamlFile = yaml.safeDump(taskJson, ({ lineWidth: -1 } as any)); var encodedTaskContent = (new Buffer(yamlFile.toString())).toString('base64'); - + var encodedTask = { - type : AcrTaskRequest.TaskRequestStepType.EncodedTask, + type: AcrTaskRequest.TaskRequestStepType.EncodedTask, encodedTaskContent: encodedTaskContent } as AcrTaskRequest.EncodedTaskStep; - - if (this.acrTask.contextType == "git") - { + + if (this.acrTask.contextType == "git") { encodedTask.contextPath = this.acrTask.context; encodedTask.contextAccessToken = this.acrTask.contextAccessToken; } - else - { + else { encodedTask.contextPath = null; encodedTask.contextAccessToken = null; } - if (!!this.acrTask.valuesFilePath) - { + if (!!this.acrTask.valuesFilePath) { var encodedValuesContent = (new Buffer(this.acrTask.valuesFilePath)).toString('base64'); encodedTask.encodedValuesContent = encodedValuesContent } - + return encodedTask; } - catch(error) - { + catch (error) { throw new Error(tl.loc("FailedToCreateEncodedTaskStep", error)); } } private _getFileTaskStep(): AcrTaskRequest.IFileTaskStep { var fileTask = { - type : AcrTaskRequest.TaskRequestStepType.FileTask, - taskFilePath : this.acrTask.taskFile, + type: AcrTaskRequest.TaskRequestStepType.FileTask, + taskFilePath: this.acrTask.taskFile, } as AcrTaskRequest.IFileTaskStep; - if (this.acrTask.contextType == "git") - { + if (this.acrTask.contextType == "git") { fileTask.contextPath = this.acrTask.context; fileTask.contextAccessToken = this.acrTask.contextAccessToken; } - else - { + else { fileTask.contextPath = dummyContextUrl; fileTask.contextAccessToken = null; } - if(!!this.acrTask.valuesFilePath) { + if (!!this.acrTask.valuesFilePath) { fileTask.valuesFilePath = this.acrTask.valuesFilePath; } - return fileTask; + return fileTask; } private _validateAcrInputs() { try { this.isValidResourceGroupName(this.acrTask.registry.resourceGroup); - if(!this.isNameValid(this.acrTask.registry.name)) { + if (!this.isNameValid(this.acrTask.registry.name)) { throw new Error(tl.loc("AcrRegNameCannotBeEmpty")); } - if(!this.isNameValid(this.acrTask.name)) { + if (!this.isNameValid(this.acrTask.name)) { throw new Error(tl.loc("AcrTaskNameCannotBeEmpty")); } } @@ -508,9 +505,8 @@ export class AcrTaskClient extends ServiceClient { private _getTaskVersion() { var version = this.acrTask.version; - if(this.updateTask) - { - version = semver.inc(this.acrTask.version, 'patch'); + if (this.updateTask) { + version = semver.inc(this.acrTask.version, 'patch'); } return version diff --git a/Tasks/ACRTaskV0/task.json b/Tasks/ACRTaskV0/task.json index a01821fac854..12ff7c19de8e 100644 --- a/Tasks/ACRTaskV0/task.json +++ b/Tasks/ACRTaskV0/task.json @@ -15,8 +15,8 @@ "demands": [], "version": { "Major": 0, - "Minor": 162, - "Patch": 9 + "Minor": 169, + "Patch": 10 }, "instanceNameFormat": "acrTask", "showEnvironmentVariables": true, @@ -189,6 +189,15 @@ "required": false, "helpMarkDown": "Current working directory where the script(not ACR) is run. Empty is the root of the repo (build) or artifacts (release), which is $(System.DefaultWorkingDirectory)", "groupName": "advanced" + }, + { + "name": "pat", + "type": "string", + "label": "PAT for updating the baseimage trigger", + "defaultValue": "", + "required": false, + "helpMarkDown": "This PAT would be passed down to the baseImageTrigger field to trigger this pipeline whenever the base image is updated", + "groupName": "advanced" } ], "dataSourceBindings": [ diff --git a/Tasks/ACRTaskV0/task.loc.json b/Tasks/ACRTaskV0/task.loc.json index 28684317c5e0..242cb7f324a9 100644 --- a/Tasks/ACRTaskV0/task.loc.json +++ b/Tasks/ACRTaskV0/task.loc.json @@ -16,7 +16,7 @@ "version": { "Major": 0, "Minor": 162, - "Patch": 9 + "Patch": 10 }, "instanceNameFormat": "ms-resource:loc.instanceNameFormat", "showEnvironmentVariables": true, @@ -189,6 +189,15 @@ "required": false, "helpMarkDown": "ms-resource:loc.input.help.cwd", "groupName": "advanced" + }, + { + "name": "pat", + "type": "string", + "label": "ms-resource:loc.input.label.pat", + "defaultValue": "", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.pat", + "groupName": "advanced" } ], "dataSourceBindings": [ diff --git a/Tasks/AzureCLIV2/task.json b/Tasks/AzureCLIV2/task.json index c347a6186d24..86f86fbcfebe 100644 --- a/Tasks/AzureCLIV2/task.json +++ b/Tasks/AzureCLIV2/task.json @@ -16,12 +16,11 @@ "Agent", "DeploymentGroup" ], - "preview": true, "demands": [], "version": { "Major": 2, "Minor": 0, - "Patch": 9 + "Patch": 10 }, "minimumAgentVersion": "2.0.0", "instanceNameFormat": "Azure CLI $(scriptPath)", diff --git a/Tasks/AzureCLIV2/task.loc.json b/Tasks/AzureCLIV2/task.loc.json index 68771a49943f..18332f4c8301 100644 --- a/Tasks/AzureCLIV2/task.loc.json +++ b/Tasks/AzureCLIV2/task.loc.json @@ -16,12 +16,11 @@ "Agent", "DeploymentGroup" ], - "preview": true, "demands": [], "version": { "Major": 2, "Minor": 0, - "Patch": 9 + "Patch": 10 }, "minimumAgentVersion": "2.0.0", "instanceNameFormat": "ms-resource:loc.instanceNameFormat", diff --git a/Tasks/AzureResourceManagerTemplateDeploymentV3/task.json b/Tasks/AzureResourceManagerTemplateDeploymentV3/task.json index bfe99a54f575..99c19cb0eb24 100644 --- a/Tasks/AzureResourceManagerTemplateDeploymentV3/task.json +++ b/Tasks/AzureResourceManagerTemplateDeploymentV3/task.json @@ -15,9 +15,8 @@ "version": { "Major": 3, "Minor": 2, - "Patch": 2 + "Patch": 3 }, - "preview": "true", "demands": [], "minimumAgentVersion": "2.119.1", "groups": [ diff --git a/Tasks/AzureResourceManagerTemplateDeploymentV3/task.loc.json b/Tasks/AzureResourceManagerTemplateDeploymentV3/task.loc.json index 035a89f6e0ad..301fac2cfd55 100644 --- a/Tasks/AzureResourceManagerTemplateDeploymentV3/task.loc.json +++ b/Tasks/AzureResourceManagerTemplateDeploymentV3/task.loc.json @@ -15,9 +15,8 @@ "version": { "Major": 3, "Minor": 2, - "Patch": 2 + "Patch": 3 }, - "preview": "true", "demands": [], "minimumAgentVersion": "2.119.1", "groups": [ diff --git a/Tasks/Common/ServiceFabricHelpers/Connect-ServiceFabricClusterFromServiceEndpoint.ps1 b/Tasks/Common/ServiceFabricHelpers/Connect-ServiceFabricClusterFromServiceEndpoint.ps1 index 89fc17c90f3c..ce1bb90f2746 100644 --- a/Tasks/Common/ServiceFabricHelpers/Connect-ServiceFabricClusterFromServiceEndpoint.ps1 +++ b/Tasks/Common/ServiceFabricHelpers/Connect-ServiceFabricClusterFromServiceEndpoint.ps1 @@ -214,9 +214,9 @@ function Connect-ServiceFabricClusterFromServiceEndpoint } else { - if ($ConnectedServiceEndpoint.Auth.Parameters.UseWindowsSecurity -eq "true") + if ($ConnectedServiceEndpoint.Auth.Parameters.Unsecured -ne "true") { - Write-Debug (Get-VstsLocString -Key UseWindowsSecurity) + Write-Debug (Get-VstsLocString -Key Unsecured) $clusterConnectionParameters["WindowsCredential"] = $true $clusterSpn = $ConnectedServiceEndpoint.Auth.Parameters.ClusterSpn diff --git a/Tasks/Common/ServiceFabricHelpers/Strings/resources.resjson/en-US/resources.resjson b/Tasks/Common/ServiceFabricHelpers/Strings/resources.resjson/en-US/resources.resjson index 5b910e138d8a..fb926f2794f8 100644 --- a/Tasks/Common/ServiceFabricHelpers/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/Common/ServiceFabricHelpers/Strings/resources.resjson/en-US/resources.resjson @@ -8,8 +8,9 @@ "loc.messages.ErrorOnAcquireToken": "An error occurred attempting to acquire an Azure Active Directory token. Ensure that your service endpoint is configured properly with valid credentials. Error message: {0}", "loc.messages.ErrorOnCertificateImport": "An error occurred attempting to import the certificate. Ensure that your service endpoint is configured properly with a correct certificate value and, if the certificate is password-protected, a valid password. Error message: {0}", "loc.messages.ImportedCertificate": "Imported cluster client certificate with thumbprint '{0}'.", + "loc.messages.MultipleCertPresentInLocalStoreWarningMsg": "Multiple certificates with common name {0} are present in the local certificate store. Please re-try after providing server certificate thumbprint value when setting up service endpoint.", "loc.messages.ServiceFabricSDKNotInstalled": "Service Fabric SDK is not installed on the build agent. Go to https://aka.ms/servicefabric to download and install it.", - "loc.messages.UseWindowsSecurity": "Windows security is specified. -WindowsCredential switch will be used while connecting.", + "loc.messages.Unsecured": "Unsecured option is not specified. -WindowsCredential switch will be used while connecting.", "loc.messages.ServerCertificateNotFoundForTextEncrypt": "The cluster's server certificate with thumbprint '{0}' is required in order to encrypt text but the certificate could not be found on the agent machine in the 'CurrentUser\\My' certificate store location.", "loc.messages.RetryingClusterConnection": "Retrying to connect to cluster..", "loc.messages.WarningOnRemoveCertificate": "An error occurred attempting to remove the client certificate. Error message: {0}", diff --git a/Tasks/Common/ServiceFabricHelpers/module.json b/Tasks/Common/ServiceFabricHelpers/module.json index dda4a61c05db..491e26ea9918 100644 --- a/Tasks/Common/ServiceFabricHelpers/module.json +++ b/Tasks/Common/ServiceFabricHelpers/module.json @@ -11,7 +11,7 @@ "ImportedCertificate": "Imported cluster client certificate with thumbprint '{0}'.", "MultipleCertPresentInLocalStoreWarningMsg": "Multiple certificates with common name {0} are present in the local certificate store. Please re-try after providing server certificate thumbprint value when setting up service endpoint.", "ServiceFabricSDKNotInstalled": "Service Fabric SDK is not installed on the build agent. Go to https://aka.ms/servicefabric to download and install it.", - "UseWindowsSecurity": "Windows security is specified. -WindowsCredential switch will be used while connecting.", + "Unsecured": "Unsecured option is not specified. -WindowsCredential switch will be used while connecting.", "ServerCertificateNotFoundForTextEncrypt": "The cluster's server certificate with thumbprint '{0}' is required in order to encrypt text but the certificate could not be found on the agent machine in the 'CurrentUser\\My' certificate store location.", "RetryingClusterConnection": "Retrying to connect to cluster..", "WarningOnRemoveCertificate": "An error occurred attempting to remove the client certificate. Error message: {0}", diff --git a/Tasks/CopyFilesOverSSHV0/copyfilesoverssh.ts b/Tasks/CopyFilesOverSSHV0/copyfilesoverssh.ts index 3db9d752f994..c8e11703352c 100644 --- a/Tasks/CopyFilesOverSSHV0/copyfilesoverssh.ts +++ b/Tasks/CopyFilesOverSSHV0/copyfilesoverssh.ts @@ -109,7 +109,7 @@ function getCleanTargetFolderCmd(targetFolder: string): string { // delete all files in specified folder and then delete all nested folders return `del /q "${targetFolder}\\*" && FOR /D %p IN ("${targetFolder}\\*.*") DO rmdir "%p" /s /q`; } else { - return 'rm -rf "' + targetFolder + '"/*'; + return `bash -c "rm -rf '${targetFolder}'/*"`; } } diff --git a/Tasks/CopyFilesOverSSHV0/task.json b/Tasks/CopyFilesOverSSHV0/task.json index 8e1c6665e43d..1240ce1448db 100644 --- a/Tasks/CopyFilesOverSSHV0/task.json +++ b/Tasks/CopyFilesOverSSHV0/task.json @@ -17,8 +17,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 169, - "Patch": 2 + "Minor": 170, + "Patch": 0 }, "demands": [], "minimumAgentVersion": "2.102.0", diff --git a/Tasks/CopyFilesOverSSHV0/task.loc.json b/Tasks/CopyFilesOverSSHV0/task.loc.json index d21bf3b6d833..de44ff7fcf0c 100644 --- a/Tasks/CopyFilesOverSSHV0/task.loc.json +++ b/Tasks/CopyFilesOverSSHV0/task.loc.json @@ -17,8 +17,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 169, - "Patch": 2 + "Minor": 170, + "Patch": 0 }, "demands": [], "minimumAgentVersion": "2.102.0", diff --git a/Tasks/DownloadGitHubNpmPackageV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DownloadGitHubNpmPackageV1/Strings/resources.resjson/en-US/resources.resjson new file mode 100644 index 000000000000..dc5c56843199 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/Strings/resources.resjson/en-US/resources.resjson @@ -0,0 +1,41 @@ +{ + "loc.friendlyName": "Download Github Npm Package", + "loc.helpMarkDown": "[Learn more about this task](https://go.microsoft.com/fwlink/?LinkID=613746) or [see the npm documentation](https://docs.npmjs.com/)", + "loc.description": "Install npm packages from GitHub.", + "loc.instanceNameFormat": "Download GitHub Npm Package", + "loc.group.displayName.customRegistries": "Custom registries and authentication", + "loc.input.label.packageName": "Package Name", + "loc.input.help.packageName": "Name of the package to download from github", + "loc.input.label.version": "Package Version", + "loc.input.help.version": "Version of the package to download from github", + "loc.input.label.externalEndpoints": "Credentials for registry from GitHub", + "loc.input.help.externalEndpoints": "Credentials to use for external registry from GitHub", + "loc.input.label.packagesDirectory": "Destination directory", + "loc.input.help.packagesDirectory": "Specifies the folder in which packages are installed. If no folder is specified, packages are restored into the default system working directory.", + "loc.messages.FoundBuildCredentials": "Found build credentials", + "loc.messages.NoBuildCredentials": "Could not find build credentials", + "loc.messages.UnknownCommand": "Unknown command: %s", + "loc.messages.MultipleProjectConfigs": "More than one project .npmrc found in $s", + "loc.messages.ServiceEndpointNotDefined": "Couldn't find the service connection. Make sure the selected service connection still exists.", + "loc.messages.ServiceEndpointUrlNotDefined": "Couldn't find the URL for the service connection. Make sure the service connection is correctly configured.", + "loc.messages.SavingFile": "Saving file %s", + "loc.messages.RestoringFile": "Restoring file %s", + "loc.messages.PublishFeed": "Publishing to internal feed", + "loc.messages.PublishExternal": "Publishing to external registry", + "loc.messages.PackageFailedToInstall": "Package failed to install", + "loc.messages.UseFeed": "Using internal feed", + "loc.messages.UseNpmrc": "Using registries in .npmrc", + "loc.messages.PublishRegistry": "Publishing to registry: %s", + "loc.messages.UsingRegistry": "Using registry: %s", + "loc.messages.AddingAuthRegistry": "Adding auth for registry: %s", + "loc.messages.FoundLocalRegistries": "Found %d registries in this organization/collection", + "loc.messages.ForcePackagingUrl": "Packaging collection URL forced to: %s", + "loc.messages.DebugLogNotFound": "Couldn't find a debug log in the cache or working directory", + "loc.messages.NpmFailed": "Npm failed with return code: %s", + "loc.messages.FoundNpmDebugLog": "Found npm debug log, make sure the path matches with the one in npm's output: %s", + "loc.messages.TestDebugLog": "Trying debug log location: %s", + "loc.messages.OverridingProjectNpmrc": "Overriding project .npmrc: %s", + "loc.messages.RestoringProjectNpmrc": "Restoring project .npmrc", + "loc.messages.WorkingDirectoryNotDirectory": "Please change your working directory to a valid directory", + "loc.messages.NGCommon_AreaNotFoundInSps": "Unable to locate the '%s' [%s] area. The service containing that area may not be available in your region." +} \ No newline at end of file diff --git a/Tasks/DownloadGitHubNpmPackageV1/make.json b/Tasks/DownloadGitHubNpmPackageV1/make.json new file mode 100644 index 000000000000..d2028214f63a --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/make.json @@ -0,0 +1,22 @@ +{ + "common": [ + { + "module": "../Common/utility-common", + "type": "node", + "compile": true + }, + { + "module": "../Common/packaging-common", + "type": "node", + "compile": true + } + ], + "rm": [ + { + "items": [ + "node_modules/packaging-common/node_modules/azure-pipelines-task-lib" + ], + "options": "-Rf" + } + ] +} diff --git a/Tasks/DownloadGitHubNpmPackageV1/npm.ts b/Tasks/DownloadGitHubNpmPackageV1/npm.ts new file mode 100644 index 000000000000..6dcdc0102d43 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/npm.ts @@ -0,0 +1,35 @@ +import * as path from 'path'; + +import {IExecSyncResult} from 'azure-pipelines-task-lib/toolrunner'; +import * as tl from 'azure-pipelines-task-lib/task'; + +import * as npminstall from './npminstall'; +import * as util from 'packaging-common/util'; + +async function main(): Promise { + tl.setResourcePath(path.join(__dirname, 'task.json')); + await _logNpmStartupVariables(); + npminstall.run(); +} + +async function _logNpmStartupVariables() { + try { + // Log the NPM version + let version: string; + try { + const syncResult: IExecSyncResult = tl.execSync('npm', '--version'); + if (syncResult.stdout) { + version = syncResult.stdout.trim(); + } + } catch (err) { + tl.debug(`Unable to get NPM config info. Err:( ${err} )`); + } + } catch (err) { + tl.debug(`Unable to log NPM task telemetry. Err:( ${err} )`); + } +} + +main().catch(error => { + tl.rmRF(util.getTempPath()); + tl.setResult(tl.TaskResult.Failed, error); +}); \ No newline at end of file diff --git a/Tasks/DownloadGitHubNpmPackageV1/npminstall.ts b/Tasks/DownloadGitHubNpmPackageV1/npminstall.ts new file mode 100644 index 000000000000..f1ea85425a07 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/npminstall.ts @@ -0,0 +1,149 @@ +import * as tl from 'azure-pipelines-task-lib/task'; + +import { NpmToolRunner } from './npmtoolrunner'; +import * as util from 'packaging-common/util'; +import * as npmutil from 'packaging-common/npm/npmutil'; +import * as path from 'path'; +import * as request from 'request'; + +export async function run(): Promise { + try { + const npmrc = npmutil.getTempNpmrcPath(); + let owner: string = ""; + let token: string = ""; + + const endpointName = tl.getInput("externalEndpoints"); + if (!endpointName) { + tl.error("Couldn't find the specified service connection."); + tl.setResult(tl.TaskResult.Failed, tl.loc('PackageFailedToInstall')); + } + + let packageNameInput: string = tl.getInput("packageName"); + let packageVersion: string = tl.getInput("version") || ""; + + if (!packageNameInput || packageNameInput.indexOf("/") < 0) + { + throw Error(tl.loc('Error_InvalidPackageName')); + } + else { + packageNameInput = packageNameInput.split("/")[1]; + } + + owner = await GetGitHubUser(endpointName); // we will always have a single connection + token = getEndpointAuthData(endpointName); + + const url = "https://npm.pkg.github.com/" + owner; + let authDetails = "//npm.pkg.github.com/:_authToken=" + token; + tl.debug(tl.loc('UsingRegistry', url)); + tl.mkdirP + + npmutil.appendToNpmrc(npmrc, `registry=${url}\n`); + npmutil.appendToNpmrc(npmrc, `${authDetails}\n`); + + const packageDownloadPath = getProjectPath(packageNameInput); + + const npm = new NpmToolRunner(path.dirname(npmrc), npmrc, false); + let packageName = owner.toLowerCase() + "/" + packageNameInput.toLowerCase(); + let command: string = ""; + if (packageVersion == "" || packageVersion == undefined) { + command = "install --prefix " + packageDownloadPath + " @" + packageName; + } else { + command = "install --prefix " + packageDownloadPath + " @" + packageName + "@" + packageVersion; + } + + npm.line(command); + npm.execSync(); + + tl.rmRF(npmrc); + } catch (err) { + tl.setResult(tl.TaskResult.Failed, "Some error occurred:" + err); + } +} + +export function getProjectPath(packageName: string): string { + const tempNpmrcDir + = tl.getVariable('Agent.BuildDirectory') + || tl.getVariable('Agent.TempDirectory'); + const tempPath = path.join(tempNpmrcDir, packageName); + if (tl.exist(tempPath) === false) { + tl.mkdirP(tempPath); + } + + return tempPath; +} + +function createProjectFile(projectDirectory: string, owner: string): string { + let version: string = tl.getInput("version"); + let packageNameInput : string = tl.getInput("packageName"); + let packageName = owner.toLowerCase() + "/" + packageNameInput.split('/')[1].toLowerCase(); + let projectFile: string = ` +{ + "name": "testProject", + "version": "${version}", + "main": "index.js", + "author": "", + "license": "MIT", + "dependencies": { + "@${packageName}": "${version}" + } +}` + + tl.writeFile(path.join(projectDirectory, "package.json"), projectFile); + console.log("npmrc = " + path.join(projectDirectory, "package.json")); + return path.join(projectDirectory, "package.json"); +} + +function GetGitHubUser(endpointId: string): Promise { + let externalAuth = tl.getEndpointAuthorization(endpointId, true); + let scheme = tl.getEndpointAuthorizationScheme(endpointId, true).toLowerCase(); + + if (!(scheme == "token" || scheme == "personalaccesstoken")) { + return new Promise((resolve, reject) => { + resolve(""); + }); + } + + let token = ""; + if (scheme == "token") { + token = externalAuth.parameters["AccessToken"]; + } else if (scheme == "personalaccesstoken") { + token = externalAuth.parameters["accessToken"]; + } + + var url = "https://api.github.com/user"; + + return new Promise((resolve, reject) => { + request.get({ + url : url, + headers : { + "Authorization": "Token " + token, + "User-Agent": "azure-pipelines" + } + }, function(error, response, body) { + if (error) reject(error); + let responseJson = JSON.parse(body); + resolve(responseJson["login"]); + }); + }); +} + +function getEndpointAuthData(endpointName: string): string { + let externalAuth = tl.getEndpointAuthorization(endpointName, true); + let scheme = tl.getEndpointAuthorizationScheme(endpointName, true).toLowerCase(); + let token = ""; + switch(scheme) { + case "token": + token = externalAuth.parameters["AccessToken"]; + break; + case "personalaccesstoken": + token = externalAuth.parameters["accessToken"]; + break; + case "usernamepassword": + case "none": + break; + default: + break; + } + + return token; +} \ No newline at end of file diff --git a/Tasks/DownloadGitHubNpmPackageV1/npmtoolrunner.ts b/Tasks/DownloadGitHubNpmPackageV1/npmtoolrunner.ts new file mode 100644 index 000000000000..1c346319c304 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/npmtoolrunner.ts @@ -0,0 +1,255 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { format, parse, Url } from 'url'; +import * as Q from 'q'; + +import * as tl from 'azure-pipelines-task-lib/task'; +import * as tr from 'azure-pipelines-task-lib/toolrunner'; + +import * as util from 'packaging-common/util'; +import * as npmutil from 'packaging-common/npm/npmutil'; +import * as telemetry from 'utility-common/telemetry'; + +export class NpmToolRunner extends tr.ToolRunner { + private cacheLocation: string; + private dbg: boolean; + private projectNpmrc: () => string = () => path.join(this.workingDirectory, '.npmrc'); + + constructor(private workingDirectory: string, private npmrc: string, private overrideProjectNpmrc: boolean) { + super('npm'); + + this.on('debug', (message: string) => { + tl.debug(message); + }); + + let debugVar = tl.getVariable('System.Debug') || ''; + if (debugVar.toLowerCase() === 'true') { + this.dbg = true; + } + + let cacheOptions = { silent: true } as tr.IExecSyncOptions; + if (!tl.stats(workingDirectory).isDirectory()) { + throw new Error(tl.loc('WorkingDirectoryNotDirectory')); + } + this.cacheLocation = tl.execSync('npm', 'config get cache', this._prepareNpmEnvironment(cacheOptions)).stdout.trim(); + } + + public exec(options?: tr.IExecOptions): Q.Promise { + options = this._prepareNpmEnvironment(options) as tr.IExecOptions; + + this._saveProjectNpmrc(); + return super.exec(options).then( + (code: number): number => { + this._restoreProjectNpmrc(); + return code; + }, + (reason: any) => { + this._restoreProjectNpmrc(); + return this._printDebugLog(this._getDebugLogPath(options)).then((value: void): number => { + throw reason; + }); + } + ); + } + + public execSync(options?: tr.IExecSyncOptions): tr.IExecSyncResult { + options = this._prepareNpmEnvironment(options); + + this._saveProjectNpmrc(); + const execResult = super.execSync(options); + this._restoreProjectNpmrc(); + if (execResult.code !== 0) { + telemetry.logResult('Packaging', 'npm', execResult.code); + this._printDebugLogSync(this._getDebugLogPath(options)); + throw new Error(tl.loc('NpmFailed', execResult.code)); + } + + return execResult; + } + + public static _getProxyFromEnvironment(): string { + let proxyUrl: string = tl.getVariable('agent.proxyurl'); + if (proxyUrl) { + let proxy: Url = parse(proxyUrl); + let proxyUsername: string = tl.getVariable('agent.proxyusername') || ''; + let proxyPassword: string = tl.getVariable('agent.proxypassword') || ''; + + if (proxyUsername !== '') { + proxy.auth = proxyUsername; + } + + if (proxyPassword !== '') { + proxy.auth = `${proxyUsername}:${proxyPassword}`; + } + + const authProxy = format(proxy); + + // register the formatted proxy url as a secret if it contains a password + if (proxyPassword !== '') { + tl.setSecret(authProxy); + } + + return authProxy; + } + + return undefined; + } + + private _prepareNpmEnvironment(options?: tr.IExecSyncOptions): tr.IExecSyncOptions { + options = options || {}; + options.cwd = this.workingDirectory; + + if (options.env === undefined) { + options.env = process.env; + } + + if (this.dbg) { + options.env['NPM_CONFIG_LOGLEVEL'] = 'verbose'; + } + + if (this.npmrc) { + options.env['NPM_CONFIG_USERCONFIG'] = this.npmrc; + } + + function sanitizeUrl(url: string): string { + const parsed = parse(url); + if(parsed.auth) { + parsed.auth = "***:***"; + } + return format(parsed); + } + + let proxy = NpmToolRunner._getProxyFromEnvironment(); + if (proxy) { + tl.debug(`Using proxy "${sanitizeUrl(proxy)}" for npm`); + options.env['NPM_CONFIG_PROXY'] = proxy; + options.env['NPM_CONFIG_HTTPS-PROXY'] = proxy; + + let proxybypass = this._getProxyBypass(); + if (proxybypass != null) { + + // check if there are any existing NOPROXY values + let existingNoProxy = process.env["NO_PROXY"]; + if (existingNoProxy) { + existingNoProxy = existingNoProxy.trimRight(); + // trim trailing comma + existingNoProxy = existingNoProxy.endsWith(',') ? existingNoProxy.slice(0,-1) : existingNoProxy; + // append our bypass list + proxybypass = existingNoProxy + ',' + proxybypass; + } + + tl.debug(`Setting NO_PROXY for npm: "${proxybypass}"`); + options.env['NO_PROXY'] = proxybypass; + } + } + + let config = tl.execSync('npm', `config list ${this.dbg ? '-l' : ''}`, options); + return options; + } + + private _getProxyBypass(): string { + // check if there are any proxy bypass hosts + const proxyBypassHosts: string[] = JSON.parse(tl.getVariable('Agent.ProxyBypassList') || '[]'); + if (proxyBypassHosts == null || proxyBypassHosts.length == 0) { + return undefined; + } + + // get the potential package sources + let registries: string[] = npmutil.getAllNpmRegistries(this.projectNpmrc()); + + // convert to urls + let registryUris = registries.reduce(function(result: Url[], currentRegistry: string): Url[] { + try { + const uri = parse(currentRegistry); + if (uri.hostname != null) { + result.push(uri); + } + } + finally { + return result; + } + }, []); + + const bypassDomainSet = new Set(); + + proxyBypassHosts.forEach((bypassHost => { + // if there are no more registries, stop processing regexes + if (registryUris == null || registryUris.length == 0) { + return; + } + + let regex = new RegExp(bypassHost, 'i'); + + // filter out the registries that match the current regex + registryUris = registryUris.filter(registryUri => { + if (regex.test(registryUri.href)) { + bypassDomainSet.add(registryUri.hostname); + return false; + } + return true; + }); + })); + + // return a comma separated list of the bypass domains + if (bypassDomainSet.size > 0) { + const bypassDomainArray = Array.from(bypassDomainSet); + return bypassDomainArray.join(','); + } + return undefined; + } + + private _getDebugLogPath(options?: tr.IExecSyncOptions): string { + // check cache + const logs = tl.findMatch(path.join(this.cacheLocation, '_logs'), '*-debug.log'); + if (logs && logs.length > 0) { + const debugLog = logs[logs.length - 1]; + console.log(tl.loc('FoundNpmDebugLog', debugLog)); + return debugLog; + } + + // check working dir + const cwd = options && options.cwd ? options.cwd : process.cwd(); + const debugLog = path.join(cwd, 'npm-debug.log'); + tl.debug(tl.loc('TestDebugLog', debugLog)); + if (tl.exist(debugLog)) { + console.log(tl.loc('FoundNpmDebugLog', debugLog)); + return debugLog; + } + + tl.warning(tl.loc('DebugLogNotFound')); + return undefined; + } + + private _printDebugLog(log: string): Q.Promise { + if (!log) { + return Q.fcall(() => {}); + } + + return Q.nfcall(fs.readFile, log, 'utf-8').then((data: string) => { + console.log(data); + }); + } + + private _printDebugLogSync(log: string): void { + if (!log) { + return; + } + + console.log(fs.readFileSync(log, 'utf-8')); + } + + private _saveProjectNpmrc(): void { + if (this.overrideProjectNpmrc) { + tl.debug(tl.loc('OverridingProjectNpmrc', this.projectNpmrc())); + util.saveFile(this.projectNpmrc()); + tl.rmRF(this.projectNpmrc()); + } + } + + private _restoreProjectNpmrc(): void { + if (this.overrideProjectNpmrc) { + tl.debug(tl.loc('RestoringProjectNpmrc')); + util.restoreFile(this.projectNpmrc()); + } + } +} diff --git a/Tasks/DownloadGitHubNpmPackageV1/package-lock.json b/Tasks/DownloadGitHubNpmPackageV1/package-lock.json new file mode 100644 index 000000000000..4b0f8b27102a --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/package-lock.json @@ -0,0 +1,755 @@ +{ + "name": "downloadgithubnpmpackagev1", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/ini": { + "version": "1.3.30", + "resolved": "https://registry.npmjs.org/@types/ini/-/ini-1.3.30.tgz", + "integrity": "sha512-2+iF8zPSbpU83UKE+PNd4r/MhwNAdyGpk3H+VMgEH3EhjFZq1kouLgRoZrmIcmoGX97xFvqdS44DkICR5Nz3tQ==" + }, + "@types/ltx": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@types/ltx/-/ltx-2.8.0.tgz", + "integrity": "sha512-qHnPVD0FFquypl7Yy8qqvDjhnX3c7toUYjjALK+bug7MfR2WCRTIjw+GUMfehRi/Mbhj5rLAQerPTnTCUzSCWg==", + "requires": { + "@types/node": "*" + } + }, + "@types/mocha": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", + "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==" + }, + "@types/mockery": { + "version": "1.4.29", + "resolved": "https://registry.npmjs.org/@types/mockery/-/mockery-1.4.29.tgz", + "integrity": "sha1-m6It838H43gP/4Ux0aOOYz+UV6U=" + }, + "@types/node": { + "version": "10.12.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.9.tgz", + "integrity": "sha512-eajkMXG812/w3w4a1OcBlaTwsFPO5F7fJ/amy+tieQxEMWBlbV1JGSjkFM+zkHNf81Cad+dfIRA+IBkvmvdAeA==" + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" + }, + "@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" + }, + "@types/uuid": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.9.tgz", + "integrity": "sha512-XDwyIlt/47l2kWLTzw/mtrpLdB+GPSskR2n/PIcPn+VYhVO77rGhRncIR5GPU0KRzXuqkDO+J5qqrG0Y8P6jzQ==" + }, + "adm-zip": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", + "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "azure-devops-node-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-8.0.0.tgz", + "integrity": "sha512-QkIzphuE3y/hZVMB6ONN0Dev5r9+CIAiopWulwoYx1Er0kYcsbXsKXKynuLSxsVPocMppbr4YPhTsX2eHY/Mjw==", + "requires": { + "tunnel": "0.0.4", + "typed-rest-client": "1.2.0", + "underscore": "1.8.3" + } + }, + "azure-pipelines-task-lib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/azure-pipelines-task-lib/-/azure-pipelines-task-lib-2.8.0.tgz", + "integrity": "sha512-PR8oap9z2j+o455W3PwAfB4SX1p4GdJc9OHQaQV0V+iQS1IBY6dVgcNSQMkHAXb0V1bbuLOFBLanXPe5eSgGTQ==", + "requires": { + "minimatch": "3.0.4", + "mockery": "^1.7.0", + "q": "^1.1.2", + "semver": "^5.1.0", + "shelljs": "^0.3.0", + "uuid": "^3.0.1" + } + }, + "azure-pipelines-tool-lib": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/azure-pipelines-tool-lib/-/azure-pipelines-tool-lib-0.12.0.tgz", + "integrity": "sha512-JAlFvMTtEXISrnJY/kgq0LecLi089RqXRf/gMsXYbflmzszklkc+LUJpR0A7NDmJ+9/MWpKY/ZX+Q/zirYa7gw==", + "requires": { + "@types/semver": "^5.3.0", + "@types/uuid": "^3.0.1", + "azure-pipelines-task-lib": "^2.8.0", + "semver": "^5.3.0", + "semver-compare": "^1.0.0", + "typed-rest-client": "1.0.9", + "uuid": "^3.0.1" + }, + "dependencies": { + "typed-rest-client": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.0.9.tgz", + "integrity": "sha512-iOdwgmnP/tF6Qs+oY4iEtCf/3fnCDl7Gy9LGPJ4E3M4Wj3uaSko15FVwbsaBmnBqTJORnXBWVY5306D4HH8oiA==", + "requires": { + "tunnel": "0.0.4", + "underscore": "1.8.3" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.x.x" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.x.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "ip-address": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz", + "integrity": "sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==", + "requires": { + "jsbn": "1.1.0", + "lodash": "^4.17.15", + "sprintf-js": "1.1.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } + }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "ltx": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/ltx/-/ltx-2.9.2.tgz", + "integrity": "sha512-llB7HflFhlfsYYT1SAe80elCBO5C20ryLdwPB/A/BZk38hhVeZztDlWQ9uTyvKNPX4aK6sA+JfS1f/mfzp5cxA==", + "requires": { + "inherits": "^2.0.4" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mockery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-1.7.0.tgz", + "integrity": "sha1-9O3g2HUMHJcnwnLqLGBiniyaHE8=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "packaging-common": { + "version": "file:../../_build/Tasks/Common/packaging-common-1.0.1.tgz", + "requires": { + "@types/ini": "1.3.30", + "@types/ltx": "2.8.0", + "@types/mocha": "5.2.6", + "@types/mockery": "1.4.29", + "@types/node": "10.12.9", + "@types/q": "1.5.2", + "adm-zip": "^0.4.11", + "azure-devops-node-api": "8.0.0", + "azure-pipelines-task-lib": "2.8.0", + "azure-pipelines-tool-lib": "0.12.0", + "ini": "^1.3.4", + "ip-address": "^5.8.9", + "ltx": "^2.6.2", + "q": "^1.5.0", + "semver": "^5.5.0", + "typed-rest-client": "1.2.0" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.x.x" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + } + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "^1.4.1" + } + }, + "tunnel": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", + "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "typed-rest-client": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.2.0.tgz", + "integrity": "sha512-FrUshzZ1yxH8YwGR29PWWnfksLEILbWJydU7zfIRkyH7kAEzB62uMAl2WY6EyolWpLpVHeJGgQm45/MaruaHpw==", + "requires": { + "tunnel": "0.0.4", + "underscore": "1.8.3" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utility-common": { + "version": "file:../../_build/Tasks/Common/utility-common-1.0.2.tgz", + "requires": { + "js-yaml": "3.6.1", + "semver": "^5.4.1", + "vso-node-api": "6.5.0", + "vsts-task-lib": "2.6.0", + "vsts-task-tool-lib": "0.4.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "vso-node-api": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/vso-node-api/-/vso-node-api-6.5.0.tgz", + "integrity": "sha512-hFjPLMJkq02zF8U+LhZ4airH0ivaiKzGdlNAQlYFB3lWuGH/UANUrl63DVPUQOyGw+7ZNQ+ufM44T6mWN92xyg==", + "requires": { + "tunnel": "0.0.4", + "typed-rest-client": "^0.12.0", + "underscore": "1.8.3" + }, + "dependencies": { + "typed-rest-client": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.12.0.tgz", + "integrity": "sha1-Y3b1Un9CfaEh3K/f1+QeEyHgcgw=", + "requires": { + "tunnel": "0.0.4", + "underscore": "1.8.3" + } + } + } + }, + "vsts-task-lib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/vsts-task-lib/-/vsts-task-lib-2.6.0.tgz", + "integrity": "sha512-ja2qX4BIUvswcNbGtIoGo1SM5mRVc3Yaf7oM4oY64bNHs04chKfvH6f3cDDG0pd44OrZIGQE9LgECzeau6z2wA==", + "requires": { + "minimatch": "3.0.4", + "mockery": "^1.7.0", + "q": "^1.1.2", + "semver": "^5.1.0", + "shelljs": "^0.3.0", + "uuid": "^3.0.1" + } + }, + "vsts-task-tool-lib": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/vsts-task-tool-lib/-/vsts-task-tool-lib-0.4.0.tgz", + "integrity": "sha1-zOtRxyh3yWTI5E3p7eovZfyKyPk=", + "requires": { + "semver": "^5.3.0", + "semver-compare": "^1.0.0", + "typed-rest-client": "^0.9.0", + "uuid": "^3.0.1", + "vsts-task-lib": "2.0.4-preview" + }, + "dependencies": { + "typed-rest-client": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.9.0.tgz", + "integrity": "sha1-92jMDcP06VDwbgSCXDaz54NKofI=", + "requires": { + "tunnel": "0.0.4", + "underscore": "1.8.3" + } + }, + "vsts-task-lib": { + "version": "2.0.4-preview", + "resolved": "https://registry.npmjs.org/vsts-task-lib/-/vsts-task-lib-2.0.4-preview.tgz", + "integrity": "sha1-nU63UAoL2a1Z429w8iqtxuK6+NI=", + "requires": { + "minimatch": "^3.0.0", + "mockery": "^1.7.0", + "q": "^1.1.2", + "semver": "^5.1.0", + "shelljs": "^0.3.0", + "uuid": "^3.0.1" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tasks/DownloadGitHubNpmPackageV1/package.json b/Tasks/DownloadGitHubNpmPackageV1/package.json new file mode 100644 index 000000000000..5e85ea3a4ae9 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/package.json @@ -0,0 +1,27 @@ +{ + "name": "downloadgithubnpmpackagev1", + "version": "1.0.0", + "description": "", + "main": "npm.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/azure-pipelines-tasks.git" + }, + "author": "rogoyal@microsoft.com", + "license": "ISC", + "bugs": { + "url": "https://github.com/microsoft/azure-pipelines-tasks/issues" + }, + "homepage": "https://github.com/microsoft/azure-pipelines-tasks#readme", + "dependencies": { + "azure-pipelines-task-lib": "2.8.0", + "ini": "^1.3.4", + "mockery": "^1.7.0", + "packaging-common": "file:../../_build/Tasks/Common/packaging-common-1.0.1.tgz", + "request": "2.81.0", + "utility-common": "file:../../_build/Tasks/Common/utility-common-1.0.2.tgz" + } +} diff --git a/Tasks/DownloadGitHubNpmPackageV1/task.json b/Tasks/DownloadGitHubNpmPackageV1/task.json new file mode 100644 index 000000000000..29f5e59a93d0 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/task.json @@ -0,0 +1,107 @@ +{ + "id": "97411e3d-0241-4b1f-9607-2d2c04b4df51", + "name": "DownloadGithubNpmPackage", + "friendlyName": "Download Github Npm Package", + "description": "Install npm packages from GitHub.", + "helpUrl": "https://docs.microsoft.com/azure/devops/pipelines/tasks/package/npm", + "helpMarkDown": "[Learn more about this task](https://go.microsoft.com/fwlink/?LinkID=613746) or [see the npm documentation](https://docs.npmjs.com/)", + "category": "Package", + "author": "Microsoft Corporation", + "version": { + "Major": 1, + "Minor": 0, + "Patch": 0 + }, + "runsOn": [ + "Agent", + "DeploymentGroup" + ], + "demands": [ + "npm" + ], + "minimumAgentVersion": "2.115.0", + "instanceNameFormat": "Download GitHub Npm Package", + "groups": [ + { + "displayName": "Custom registries and authentication", + "name": "customRegistries", + "isExpanded": false, + "visibleRule": "command = install || command = ci || command = custom" + } + ], + "inputs": [ + { + "name": "packageName", + "type": "string", + "label": "Package Name", + "required": true, + "helpMarkDown": "Name of the package to download from github" + }, + { + "name": "version", + "type": "string", + "label": "Package Version", + "required": true, + "helpMarkDown": "Version of the package to download from github" + }, + { + "name": "externalEndpoints", + "aliases": [ + "externalRegistryCredentials" + ], + "type": "connectedService:github:PersonalAccessToken,Token", + "label": "Credentials for registry from GitHub", + "required": true, + "helpMarkDown": "Credentials to use for external registry from GitHub", + "properties": { + "EditableOptions": "False", + "MultiSelectFlatList": "False" + } + }, + { + "name": "packagesDirectory", + "aliases": [ + "installDirectory" + ], + "type": "string", + "label": "Destination directory", + "defaultValue": "", + "helpMarkDown": "Specifies the folder in which packages are installed. If no folder is specified, packages are restored into the default system working directory.", + "required": "false" + } + ], + "execution": { + "Node": { + "target": "npm.js", + "argumentFormat": "" + } + }, + "messages": { + "FoundBuildCredentials": "Found build credentials", + "NoBuildCredentials": "Could not find build credentials", + "UnknownCommand": "Unknown command: %s", + "MultipleProjectConfigs": "More than one project .npmrc found in $s", + "ServiceEndpointNotDefined": "Couldn't find the service connection. Make sure the selected service connection still exists.", + "ServiceEndpointUrlNotDefined": "Couldn't find the URL for the service connection. Make sure the service connection is correctly configured.", + "SavingFile": "Saving file %s", + "RestoringFile": "Restoring file %s", + "PublishFeed": "Publishing to internal feed", + "PublishExternal": "Publishing to external registry", + "PackageFailedToInstall": "Package failed to install", + "UseFeed": "Using internal feed", + "UseNpmrc": "Using registries in .npmrc", + "PublishRegistry": "Publishing to registry: %s", + "UsingRegistry": "Using registry: %s", + "AddingAuthRegistry": "Adding auth for registry: %s", + "FoundLocalRegistries": "Found %d registries in this organization/collection", + "ForcePackagingUrl": "Packaging collection URL forced to: %s", + "DebugLogNotFound": "Couldn't find a debug log in the cache or working directory", + "NpmFailed": "Npm failed with return code: %s", + "FoundNpmDebugLog": "Found npm debug log, make sure the path matches with the one in npm's output: %s", + "TestDebugLog": "Trying debug log location: %s", + "OverridingProjectNpmrc": "Overriding project .npmrc: %s", + "RestoringProjectNpmrc": "Restoring project .npmrc", + "WorkingDirectoryNotDirectory": "Please change your working directory to a valid directory", + "NGCommon_AreaNotFoundInSps": "Unable to locate the '%s' [%s] area. The service containing that area may not be available in your region." + } +} diff --git a/Tasks/DownloadGitHubNpmPackageV1/task.loc.json b/Tasks/DownloadGitHubNpmPackageV1/task.loc.json new file mode 100644 index 000000000000..a0ef214ebca5 --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/task.loc.json @@ -0,0 +1,107 @@ +{ + "id": "97411e3d-0241-4b1f-9607-2d2c04b4df51", + "name": "DownloadGithubNpmPackage", + "friendlyName": "ms-resource:loc.friendlyName", + "description": "ms-resource:loc.description", + "helpUrl": "https://docs.microsoft.com/azure/devops/pipelines/tasks/package/npm", + "helpMarkDown": "ms-resource:loc.helpMarkDown", + "category": "Package", + "author": "Microsoft Corporation", + "version": { + "Major": 1, + "Minor": 0, + "Patch": 0 + }, + "runsOn": [ + "Agent", + "DeploymentGroup" + ], + "demands": [ + "npm" + ], + "minimumAgentVersion": "2.115.0", + "instanceNameFormat": "ms-resource:loc.instanceNameFormat", + "groups": [ + { + "displayName": "ms-resource:loc.group.displayName.customRegistries", + "name": "customRegistries", + "isExpanded": false, + "visibleRule": "command = install || command = ci || command = custom" + } + ], + "inputs": [ + { + "name": "packageName", + "type": "string", + "label": "ms-resource:loc.input.label.packageName", + "required": true, + "helpMarkDown": "ms-resource:loc.input.help.packageName" + }, + { + "name": "version", + "type": "string", + "label": "ms-resource:loc.input.label.version", + "required": true, + "helpMarkDown": "ms-resource:loc.input.help.version" + }, + { + "name": "externalEndpoints", + "aliases": [ + "externalRegistryCredentials" + ], + "type": "connectedService:github:PersonalAccessToken,Token", + "label": "ms-resource:loc.input.label.externalEndpoints", + "required": true, + "helpMarkDown": "ms-resource:loc.input.help.externalEndpoints", + "properties": { + "EditableOptions": "False", + "MultiSelectFlatList": "False" + } + }, + { + "name": "packagesDirectory", + "aliases": [ + "installDirectory" + ], + "type": "string", + "label": "ms-resource:loc.input.label.packagesDirectory", + "defaultValue": "", + "helpMarkDown": "ms-resource:loc.input.help.packagesDirectory", + "required": "false" + } + ], + "execution": { + "Node": { + "target": "npm.js", + "argumentFormat": "" + } + }, + "messages": { + "FoundBuildCredentials": "ms-resource:loc.messages.FoundBuildCredentials", + "NoBuildCredentials": "ms-resource:loc.messages.NoBuildCredentials", + "UnknownCommand": "ms-resource:loc.messages.UnknownCommand", + "MultipleProjectConfigs": "ms-resource:loc.messages.MultipleProjectConfigs", + "ServiceEndpointNotDefined": "ms-resource:loc.messages.ServiceEndpointNotDefined", + "ServiceEndpointUrlNotDefined": "ms-resource:loc.messages.ServiceEndpointUrlNotDefined", + "SavingFile": "ms-resource:loc.messages.SavingFile", + "RestoringFile": "ms-resource:loc.messages.RestoringFile", + "PublishFeed": "ms-resource:loc.messages.PublishFeed", + "PublishExternal": "ms-resource:loc.messages.PublishExternal", + "PackageFailedToInstall": "ms-resource:loc.messages.PackageFailedToInstall", + "UseFeed": "ms-resource:loc.messages.UseFeed", + "UseNpmrc": "ms-resource:loc.messages.UseNpmrc", + "PublishRegistry": "ms-resource:loc.messages.PublishRegistry", + "UsingRegistry": "ms-resource:loc.messages.UsingRegistry", + "AddingAuthRegistry": "ms-resource:loc.messages.AddingAuthRegistry", + "FoundLocalRegistries": "ms-resource:loc.messages.FoundLocalRegistries", + "ForcePackagingUrl": "ms-resource:loc.messages.ForcePackagingUrl", + "DebugLogNotFound": "ms-resource:loc.messages.DebugLogNotFound", + "NpmFailed": "ms-resource:loc.messages.NpmFailed", + "FoundNpmDebugLog": "ms-resource:loc.messages.FoundNpmDebugLog", + "TestDebugLog": "ms-resource:loc.messages.TestDebugLog", + "OverridingProjectNpmrc": "ms-resource:loc.messages.OverridingProjectNpmrc", + "RestoringProjectNpmrc": "ms-resource:loc.messages.RestoringProjectNpmrc", + "WorkingDirectoryNotDirectory": "ms-resource:loc.messages.WorkingDirectoryNotDirectory", + "NGCommon_AreaNotFoundInSps": "ms-resource:loc.messages.NGCommon_AreaNotFoundInSps" + } +} \ No newline at end of file diff --git a/Tasks/DownloadGitHubNpmPackageV1/tsconfig.json b/Tasks/DownloadGitHubNpmPackageV1/tsconfig.json new file mode 100644 index 000000000000..ab5587c7412d --- /dev/null +++ b/Tasks/DownloadGitHubNpmPackageV1/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs" + } +} \ No newline at end of file diff --git a/Tasks/DownloadGitHubNugetPackageV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DownloadGitHubNugetPackageV1/Strings/resources.resjson/en-US/resources.resjson index 6f9260a954ce..d2202a5b8f59 100644 --- a/Tasks/DownloadGitHubNugetPackageV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DownloadGitHubNugetPackageV1/Strings/resources.resjson/en-US/resources.resjson @@ -1,5 +1,5 @@ { - "loc.friendlyName": "Download Nuget GitHub Packages", + "loc.friendlyName": "Download GitHub Nuget Packages", "loc.helpMarkDown": "[See the .NET Core documentation](https://docs.microsoft.com/dotnet/core/)", "loc.description": "Restore your nuget packages using dotnet CLI", "loc.instanceNameFormat": "dotnet restore", diff --git a/Tasks/DownloadGitHubNugetPackageV1/package-lock.json b/Tasks/DownloadGitHubNugetPackageV1/package-lock.json index 79c99170a95e..cd43180b150a 100644 --- a/Tasks/DownloadGitHubNugetPackageV1/package-lock.json +++ b/Tasks/DownloadGitHubNugetPackageV1/package-lock.json @@ -43,9 +43,9 @@ "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" }, "@types/uuid": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.8.tgz", - "integrity": "sha512-zHWce3allXWSmRx6/AGXKCtSOA7JjeWd2L3t4aHfysNk8mouQnWCocveaT7a4IEIlPVHp81jzlnknqTgCjCLXA==" + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.9.tgz", + "integrity": "sha512-XDwyIlt/47l2kWLTzw/mtrpLdB+GPSskR2n/PIcPn+VYhVO77rGhRncIR5GPU0KRzXuqkDO+J5qqrG0Y8P6jzQ==" }, "adm-zip": { "version": "0.4.14", @@ -485,6 +485,7 @@ "ip-address": "^5.8.9", "ltx": "^2.6.2", "q": "^1.5.0", + "semver": "^5.5.0", "typed-rest-client": "1.2.0" }, "dependencies": { diff --git a/Tasks/DownloadGitHubNugetPackageV1/task.json b/Tasks/DownloadGitHubNugetPackageV1/task.json index 5c4cf76b2714..6ecb290b5139 100644 --- a/Tasks/DownloadGitHubNugetPackageV1/task.json +++ b/Tasks/DownloadGitHubNugetPackageV1/task.json @@ -1,7 +1,7 @@ { "id": "9fac244b-8d7c-4d8e-a003-2097daa3270f", "name": "DownloadGitHubNugetPackage", - "friendlyName": "Download Nuget GitHub Packages", + "friendlyName": "Download GitHub Nuget Packages", "description": "Restore your nuget packages using dotnet CLI", "author": "Microsoft Corporation", "helpUrl": "https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/?view=azure-devops", @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 2 + "Patch": 3 }, "minimumAgentVersion": "2.115.0", "instanceNameFormat": "dotnet restore", diff --git a/Tasks/DownloadGitHubNugetPackageV1/task.loc.json b/Tasks/DownloadGitHubNugetPackageV1/task.loc.json index 80045ca706af..0b0b2020fb14 100644 --- a/Tasks/DownloadGitHubNugetPackageV1/task.loc.json +++ b/Tasks/DownloadGitHubNugetPackageV1/task.loc.json @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 2 + "Patch": 3 }, "minimumAgentVersion": "2.115.0", "instanceNameFormat": "ms-resource:loc.instanceNameFormat", diff --git a/Tasks/DownloadGitHubReleaseV0/task.json b/Tasks/DownloadGitHubReleaseV0/task.json index 35e7cd2bbc2c..2e409d1f9819 100644 --- a/Tasks/DownloadGitHubReleaseV0/task.json +++ b/Tasks/DownloadGitHubReleaseV0/task.json @@ -19,7 +19,7 @@ "inputs": [ { "name": "connection", - "type": "connectedService:github:OAuth,OAuth2,PersonalAccessToken,Token", + "type": "connectedService:github", "label": "GitHub Connection", "defaultValue": "", "required": true, diff --git a/Tasks/DownloadGitHubReleaseV0/task.loc.json b/Tasks/DownloadGitHubReleaseV0/task.loc.json index b90beab8954a..e533d6e41555 100644 --- a/Tasks/DownloadGitHubReleaseV0/task.loc.json +++ b/Tasks/DownloadGitHubReleaseV0/task.loc.json @@ -19,7 +19,7 @@ "inputs": [ { "name": "connection", - "type": "connectedService:github:OAuth,OAuth2,PersonalAccessToken,Token", + "type": "connectedService:github", "label": "ms-resource:loc.input.label.connection", "defaultValue": "", "required": true, diff --git a/Tasks/DownloadPackageV0/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DownloadPackageV0/Strings/resources.resjson/en-US/resources.resjson index 8a24c3fe2980..b37c85172356 100644 --- a/Tasks/DownloadPackageV0/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DownloadPackageV0/Strings/resources.resjson/en-US/resources.resjson @@ -13,6 +13,7 @@ "loc.input.help.downloadPath": "Path on the agent machine where the package will be downloaded", "loc.messages.FailedToGetPackageMetadata": "Failed to get package metadata with error %s", "loc.messages.FailedToDownloadNugetPackage": "Failed to download NuGet package from %s got the following error: %s", + "loc.messages.Info_ResolvedToolFromCache": "Resolved from tool cache: %s", "loc.messages.PackageDownloadSuccessful": "Package download successful", "loc.messages.CredentialsNotFound": "Could not determine credentials to connect to Azure Artifacts service.", "loc.messages.StartingDownloadOfPackage": "Starting download of NuGet package %s to location %s", diff --git a/Tasks/DownloadPackageV0/task.json b/Tasks/DownloadPackageV0/task.json index 26bfe1ab099b..303c7319b593 100644 --- a/Tasks/DownloadPackageV0/task.json +++ b/Tasks/DownloadPackageV0/task.json @@ -105,6 +105,7 @@ "ExtractionFailed": "Failed to extract package with error %s", "RetryingOperation": "Error: in %s, so retrying => retries pending: %s", "OperationFailed": "Failed in %s with error: %s", + "Info_ResolvedToolFromCache": "Resolved from tool cache: %s", "UnsupportedProjectScopedFeeds": "Project-scoped feeds are not supported by this version of the \"Download Package\" task. Please use version 1 or higher." } } \ No newline at end of file diff --git a/Tasks/DownloadPackageV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DownloadPackageV1/Strings/resources.resjson/en-US/resources.resjson index 6d34acd6944a..c2c44e814ac9 100644 --- a/Tasks/DownloadPackageV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DownloadPackageV1/Strings/resources.resjson/en-US/resources.resjson @@ -31,6 +31,7 @@ "loc.messages.RedirectUrlError": "Unable to get redirect URL with error %.", "loc.messages.UnsupportedArchiveType": "Unsupported archive type: %s", "loc.messages.Error_UnexpectedErrorArtifactToolDownload": "An unexpected error occurred while trying to download the package. Exit code(%s) and error(%s)", + "loc.messages.Info_ResolvedToolFromCache": "Resolved from tool cache: %s", "loc.messages.Info_DownloadingArtifactTool": "Downloading artifact tool from %s", "loc.messages.Info_Downloading": "Downloading package: %s, version: %s using feed id: %s, project: %s", "loc.messages.Info_UsingArtifactToolDownload": "Using artifact tool to download the package" diff --git a/Tasks/DownloadPackageV1/task.json b/Tasks/DownloadPackageV1/task.json index 156f7283ffbe..75afa6840881 100644 --- a/Tasks/DownloadPackageV1/task.json +++ b/Tasks/DownloadPackageV1/task.json @@ -182,6 +182,7 @@ "RedirectUrlError": "Unable to get redirect URL with error %.", "UnsupportedArchiveType": "Unsupported archive type: %s", "Error_UnexpectedErrorArtifactToolDownload": "An unexpected error occurred while trying to download the package. Exit code(%s) and error(%s)", + "Info_ResolvedToolFromCache": "Resolved from tool cache: %s", "Info_DownloadingArtifactTool": "Downloading artifact tool from %s", "Info_Downloading": "Downloading package: %s, version: %s using feed id: %s, project: %s", "Info_UsingArtifactToolDownload": "Using artifact tool to download the package" diff --git a/Tasks/KubernetesManifestV0/Tests/L0.ts b/Tasks/KubernetesManifestV0/Tests/L0.ts index ebe847bddb99..4aff5a282ad8 100644 --- a/Tasks/KubernetesManifestV0/Tests/L0.ts +++ b/Tasks/KubernetesManifestV0/Tests/L0.ts @@ -32,6 +32,7 @@ describe('Kubernetes Manifests Suite', function () { delete process.env[shared.TestEnvVars.releaseName]; delete process.env[shared.TestEnvVars.baselineAndCanaryReplicas]; delete process.env[shared.TestEnvVars.trafficSplitMethod]; + delete process.env[shared.TestEnvVars.containers]; delete process.env.RemoveNamespaceFromEndpoint; }); @@ -357,6 +358,21 @@ describe('Kubernetes Manifests Suite', function () { done(); }); + it('Run should succeed with helm bake with image substituion', (done: MochaDone) => { + const tp = path.join(__dirname, 'TestSetup.js'); + const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + process.env[shared.TestEnvVars.action] = shared.Actions.bake; + process.env[shared.TestEnvVars.namespace] = 'namespacefrominput'; + process.env[shared.TestEnvVars.helmChart] = 'helmChart'; + process.env[shared.TestEnvVars.renderType] = 'helm'; + process.env[shared.TestEnvVars.helmVersion] = "v2"; + process.env[shared.TestEnvVars.containers] = 'nginx:1.1.1'; + tr.run(); + assert(tr.succeeded, 'task should have succeeded'); + assert(tr.stdout.indexOf('set manifestsBundle') > -1, 'task should have set manifestsBundle output variable'); + done(); + }); + it('Run should successfully create secret', (done: MochaDone) => { const tp = path.join(__dirname, 'TestSetup.js'); const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); @@ -451,6 +467,20 @@ describe('Kubernetes Manifests Suite', function () { done(); }); + it('Run should bake docker-compose files using kompose with image substituion', (done: MochaDone) => { + const tp = path.join(__dirname, 'TestSetup.js'); + const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + process.env[shared.TestEnvVars.action] = shared.Actions.bake; + process.env[shared.TestEnvVars.renderType] = 'kompose'; + process.env[shared.TestEnvVars.dockerComposeFile] = 'dockerComposeFilePath'; + process.env[shared.TestEnvVars.containers] = 'nginx:1.1.1'; + tr.run(); + assert(tr.succeeded, 'task should have succeeded'); + assert(tr.stdout.indexOf('Kubernetes files created') > 0, 'task should have succeeded'); + assert(tr.stdout.indexOf('set manifestsBundle') > -1, 'task should have set manifestsBundle output variable'); + done(); + }); + it('Run should fail when docker-compose file path is not supplied', (done: MochaDone) => { const tp = path.join(__dirname, 'TestSetup.js'); const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); @@ -506,4 +536,18 @@ describe('Kubernetes Manifests Suite', function () { assert(tr.stdOutContained('kustomize kustomizationPath'), 'task should have invoked tool: kustomize'); done(); }); + + it('Kustomize bake should pass with image substituition', (done: MochaDone) => { + const tp = path.join(__dirname, 'TestSetup.js'); + const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + process.env[shared.TestEnvVars.action] = shared.Actions.bake; + process.env[shared.TestEnvVars.renderType] = 'kustomize'; + process.env[shared.TestEnvVars.kustomizationPath] = 'kustomizationPath'; + process.env[shared.TestEnvVars.containers] = 'nginx:1.1.1\nalpine'; + process.env.KubectlMinorVersion = '14'; + tr.run(); + assert(tr.succeeded, 'task should have succeeded'); + assert(tr.stdOutContained('kustomize kustomizationPath'), 'task should have invoked tool: kustomize'); + done(); + }); }); diff --git a/Tasks/KubernetesManifestV0/src/actions/bake.ts b/Tasks/KubernetesManifestV0/src/actions/bake.ts index 4b8e13573cad..caf7024078f7 100644 --- a/Tasks/KubernetesManifestV0/src/actions/bake.ts +++ b/Tasks/KubernetesManifestV0/src/actions/bake.ts @@ -3,6 +3,7 @@ import * as tl from 'azure-pipelines-task-lib/task'; import * as path from 'path'; import * as fs from 'fs'; +import * as yaml from 'js-yaml'; import * as helmutility from 'kubernetes-common-v2/helmutility'; import * as uuidV4 from 'uuid/v4'; import { IExecOptions } from 'azure-pipelines-task-lib/toolrunner'; @@ -12,12 +13,25 @@ import { Helm, NameValuePair } from 'kubernetes-common-v2/helm-object-model'; import * as TaskParameters from '../models/TaskInputParameters'; import { KomposeInstaller } from '../utils/installers'; import * as utils from '../utils/utilities'; +import * as DeploymentHelper from '../utils/DeploymentHelper'; +import * as TaskInputParameters from '../models/TaskInputParameters'; abstract class RenderEngine { public bake: () => Promise; protected getTemplatePath = () => { return path.join(getTempDirectory(), 'baked-template-' + uuidV4() + '.yaml'); } + protected updateImages(filePath: string) { + if (TaskInputParameters.containers.length > 0 && fs.existsSync(filePath)) { + const updatedFilesPaths: string[] = DeploymentHelper.updateResourceObjects([filePath], [], TaskInputParameters.containers); + let fileContents: string[] = []; + updatedFilesPaths.forEach((path) => { + const content = yaml.safeDump(JSON.parse(fs.readFileSync(path).toString())); + fileContents.push(content); + }); + fs.writeFileSync(filePath, fileContents.join("\n---\n")); + } + } } class HelmRenderEngine extends RenderEngine { @@ -32,6 +46,7 @@ class HelmRenderEngine extends RenderEngine { } const pathToBakedManifest = this.getTemplatePath(); fs.writeFileSync(pathToBakedManifest, result.stdout); + this.updateImages(pathToBakedManifest); tl.setVariable('manifestsBundle', pathToBakedManifest); } @@ -71,6 +86,7 @@ class KomposeRenderEngine extends RenderEngine { if (result.code !== 0 || result.error) { throw result.error; } + this.updateImages(pathToBakedManifest); tl.setVariable('manifestsBundle', pathToBakedManifest); } } @@ -86,6 +102,7 @@ class KustomizeRenderEngine extends RenderEngine { const result = command.execSync({ silent: true } as IExecOptions); const pathToBakedManifest = this.getTemplatePath(); fs.writeFileSync(pathToBakedManifest, result.stdout); + this.updateImages(pathToBakedManifest); tl.setVariable('manifestsBundle', pathToBakedManifest); }; diff --git a/Tasks/KubernetesManifestV0/src/utils/DeploymentHelper.ts b/Tasks/KubernetesManifestV0/src/utils/DeploymentHelper.ts index bba116dc79a6..7dc007f5ada0 100644 --- a/Tasks/KubernetesManifestV0/src/utils/DeploymentHelper.ts +++ b/Tasks/KubernetesManifestV0/src/utils/DeploymentHelper.ts @@ -135,7 +135,7 @@ function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Res utils.checkForErrors(annotateResults, true); } -function updateResourceObjects(filePaths: string[], imagePullSecrets: string[], containers: string[]): string[] { +export function updateResourceObjects(filePaths: string[], imagePullSecrets: string[], containers: string[]): string[] { const newObjectsList = []; const updateResourceObject = (inputObject) => { if (!!imagePullSecrets && imagePullSecrets.length > 0) { diff --git a/Tasks/KubernetesManifestV0/task.json b/Tasks/KubernetesManifestV0/task.json index 2ca58a263f80..95d7a35d7ca9 100644 --- a/Tasks/KubernetesManifestV0/task.json +++ b/Tasks/KubernetesManifestV0/task.json @@ -13,8 +13,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 167, - "Patch": 1 + "Minor": 169, + "Patch": 0 }, "demands": [], "groups": [], @@ -121,7 +121,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "Containers", - "visibleRule": "action = deploy || action = promote" + "visibleRule": "action = deploy || action = promote || action = bake" }, { "name": "imagePullSecrets", @@ -162,7 +162,7 @@ "required": true, "defaultValue": "", "helpMarkDown": "Helm chart path to bake", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "releaseName", @@ -171,7 +171,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "Helm release name to use", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "overrideFiles", @@ -180,7 +180,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "Override files to set", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "overrides", @@ -189,7 +189,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "Override values to set", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "kustomizationPath", diff --git a/Tasks/KubernetesManifestV0/task.loc.json b/Tasks/KubernetesManifestV0/task.loc.json index a5168c58f11c..c15717e2efa6 100644 --- a/Tasks/KubernetesManifestV0/task.loc.json +++ b/Tasks/KubernetesManifestV0/task.loc.json @@ -13,8 +13,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 167, - "Patch": 1 + "Minor": 169, + "Patch": 0 }, "demands": [], "groups": [], @@ -121,7 +121,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "ms-resource:loc.input.help.containers", - "visibleRule": "action = deploy || action = promote" + "visibleRule": "action = deploy || action = promote || action = bake" }, { "name": "imagePullSecrets", @@ -162,7 +162,7 @@ "required": true, "defaultValue": "", "helpMarkDown": "ms-resource:loc.input.help.helmChart", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "releaseName", @@ -171,7 +171,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "ms-resource:loc.input.help.releaseName", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "overrideFiles", @@ -180,7 +180,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "ms-resource:loc.input.help.overrideFiles", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "overrides", @@ -189,7 +189,7 @@ "required": false, "defaultValue": "", "helpMarkDown": "ms-resource:loc.input.help.overrides", - "visibleRule": "action = bake && renderType = helm2" + "visibleRule": "action = bake && renderType = helm" }, { "name": "kustomizationPath", diff --git a/Tasks/ServiceFabricComposeDeployV0/task.json b/Tasks/ServiceFabricComposeDeployV0/task.json index 5ae13be0ef67..ea57203b7539 100644 --- a/Tasks/ServiceFabricComposeDeployV0/task.json +++ b/Tasks/ServiceFabricComposeDeployV0/task.json @@ -18,7 +18,7 @@ "version": { "Major": 0, "Minor": 5, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/Tasks/ServiceFabricComposeDeployV0/task.loc.json b/Tasks/ServiceFabricComposeDeployV0/task.loc.json index 69dbf4049f5c..28ea48787387 100644 --- a/Tasks/ServiceFabricComposeDeployV0/task.loc.json +++ b/Tasks/ServiceFabricComposeDeployV0/task.loc.json @@ -18,7 +18,7 @@ "version": { "Major": 0, "Minor": 5, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/Tasks/ServiceFabricDeployV1/Tests/WindowsAuthDeploy.ps1 b/Tasks/ServiceFabricDeployV1/Tests/WindowsAuthDeploy.ps1 index 67f39dc2a5a4..1b85ab6f9c4d 100644 --- a/Tasks/ServiceFabricDeployV1/Tests/WindowsAuthDeploy.ps1 +++ b/Tasks/ServiceFabricDeployV1/Tests/WindowsAuthDeploy.ps1 @@ -39,7 +39,7 @@ $vstsEndpoint = @{ "Auth" = @{ "Scheme" = "None" "Parameters" = @{ - "UseWindowsSecurity" = "true" + "Unsecured" = "" "ClusterSpn" = $clusterFqdn } } @@ -47,7 +47,7 @@ $vstsEndpoint = @{ Register-Mock Get-VstsEndpoint { $vstsEndpoint } -- -Name $serviceConnectionName -Require # Setup mock for connection to cluster -$connectArgs = @("-ConnectionEndpoint:", $connectionEndpoint, "-WindowsCredential:", "True", "-ClusterSpn:", $clusterFqdn) +$connectArgs = @("-ConnectionEndpoint:", $connectionEndpoint, "-WindowsCredential:", "true", "-ClusterSpn:", $clusterFqdn) Register-Mock Connect-ServiceFabricCluster { $null } -Arguments $connectArgs # Setup mock registry settings diff --git a/Tasks/ServiceFabricDeployV1/task.json b/Tasks/ServiceFabricDeployV1/task.json index 0d13f913df26..eefab7097f2a 100644 --- a/Tasks/ServiceFabricDeployV1/task.json +++ b/Tasks/ServiceFabricDeployV1/task.json @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 9, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/Tasks/ServiceFabricDeployV1/task.loc.json b/Tasks/ServiceFabricDeployV1/task.loc.json index 93de683de969..30b11a3bc2e5 100644 --- a/Tasks/ServiceFabricDeployV1/task.loc.json +++ b/Tasks/ServiceFabricDeployV1/task.loc.json @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 9, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/Tasks/ServiceFabricPowerShellV1/task.json b/Tasks/ServiceFabricPowerShellV1/task.json index 075b0e60473d..16e882fa3642 100644 --- a/Tasks/ServiceFabricPowerShellV1/task.json +++ b/Tasks/ServiceFabricPowerShellV1/task.json @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 2, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/Tasks/ServiceFabricPowerShellV1/task.loc.json b/Tasks/ServiceFabricPowerShellV1/task.loc.json index 317dcd49eae4..61d8849d5a32 100644 --- a/Tasks/ServiceFabricPowerShellV1/task.loc.json +++ b/Tasks/ServiceFabricPowerShellV1/task.loc.json @@ -18,7 +18,7 @@ "version": { "Major": 1, "Minor": 2, - "Patch": 1 + "Patch": 2 }, "demands": [ "Cmd" diff --git a/ci/courtesy-push/courtesy-push.js b/ci/courtesy-push/courtesy-push.js index 1bb05fa107c9..4ae31c1fb01f 100644 --- a/ci/courtesy-push/courtesy-push.js +++ b/ci/courtesy-push/courtesy-push.js @@ -33,16 +33,15 @@ versionReplace = function(pathToUnifiedDeps, pathToNewUnifiedDeps, outputPath) { depDetails[3] = newDepsDict[newDepsKey]; updatedDeps.push(depDetails.join('\"')); } else { - if (currentDep.indexOf('') <= -1) { - updatedDeps.push(currentDep); - } + updatedDeps.push(currentDep); console.log(`"${currentDep}"`); } } + else { + updatedDeps.push(currentDep); + } }); - updatedDeps.push(''); - // write it as a new file where currentDeps is fs.writeFileSync(outputPath, updatedDeps.join("\n")); console.log('Done.'); diff --git a/make-options.json b/make-options.json index ed92cf5e052b..a7b1de8d44f5 100644 --- a/make-options.json +++ b/make-options.json @@ -72,6 +72,7 @@ "DownloadBuildArtifactsV0", "DownloadFileshareArtifactsV0", "DownloadGitHubNugetPackageV1", + "DownloadGitHubNpmPackageV1", "DownloadGitHubReleaseV0", "DownloadPackageV0", "DownloadPackageV1",