Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DownloadBuildArtifactsV0] Respect "Parallelization limit" input #14540

67 changes: 58 additions & 9 deletions Tasks/DownloadBuildArtifactsV0/download_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@ import { debug, loc } from 'azure-pipelines-task-lib/task';
import { ArtifactDownloadTicket, ItemType, TicketState } from 'artifact-engine/Models';
import { getFileSizeInBytes } from './file_helper';

/**
* Just a Promise wrapper for setTimeout function
* @param {number} interval - timeout interval in milliseconds
*/
export function timeoutPromise(interval: number): Promise<{}> {
debug(`Wait for ${interval} milliseconds`);
return new Promise(resolve => setTimeout(resolve, interval));
}

/**
* This function checks a result of artifact download
* @param {Array<ArtifactDownloadTicket>} downloadTickets
Expand Down Expand Up @@ -96,3 +87,61 @@ function isItemCorrupted(ticket: ArtifactDownloadTicket): boolean {

return isCorrupted;
}

/**
* This function resolves the value for the `parallelProcessingLimit` option of `ArtifactEngine`
*
* Earlier the only way to set parallelProcessingLimit in the task
* was by declaring the `release.artifact.download.parallellimit` variable.
*
* To maintain backward compatibility we will use the following strategy:
*
* Firstly, investigate the `release.artifact.download.parallellimit` variable.
* If everything is okay with this variable, the task will use the value from this variable.
*
* Secondly, investigate the `Parallelization limit` input of the task.
* If everything is okay with the value in the related task's input, the task will use the value from this input.
*
* If validation failed for both cases the function will return the `defaultLimit` for the `parallelProcessingLimit` option.
*
* @param {string} artifactDownloadLimit - value of `release.artifact.download.parallellimit` variable
* @param {string} taskLimit - value of `Parallelization limit` task input
* @param {number} defaultLimit - the default value that will be returned if `artifactDownloadLimit` and `taskLimit` contain invalid values.
* @returns {number} - parallel processing limit
*/
export function resolveParallelProcessingLimit(artifactDownloadLimit: string, taskLimit: string, defaultLimit: number): number {
debug(`Checking value of the "release.artifact.download.parallellimit" variable - ${artifactDownloadLimit}`);
const artifactDownloadParallelLimit: number = Number(artifactDownloadLimit);
if (isParallelProcessingLimitCorrect(artifactDownloadParallelLimit)) {
return artifactDownloadParallelLimit;
}

debug(`Checking value of the "Parallelization limit" input - ${taskLimit}`);
const taskInputParallelLimit: number = Number(taskLimit);
if (isParallelProcessingLimitCorrect(taskInputParallelLimit)) {
return taskInputParallelLimit;
}

debug(`The parallelization limit is set to default value - ${defaultLimit}`);
return defaultLimit;
}

/**
* This function checks the input value for the `parallelProcessingLimit` option of `ArtifactEngine`
*
* The parallel processing limit must be a number greater than 0.
*
* @param {number} limit - value of parallel processing limit
* @returns {boolean} true if parallel processing limit is correct, false otherwise.
*/
function isParallelProcessingLimitCorrect(limit: number): boolean {
const isCorrect: boolean = (!isNaN(limit) && limit > 0);

if (isCorrect) {
debug(`The value is correct, the parallelization limit is set to ${limit}`);
} else {
debug(`The value is incorrect ${limit}`);
}

return isCorrect;
}
22 changes: 15 additions & 7 deletions Tasks/DownloadBuildArtifactsV0/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ import { DownloadHandlerContainer } from './DownloadHandlers/DownloadHandlerCont
import { DownloadHandlerContainerZip } from './DownloadHandlers/DownloadHandlerContainerZip';
import { DownloadHandlerFilePath } from './DownloadHandlers/DownloadHandlerFilePath';

import { resolveParallelProcessingLimit } from './download_helper';

var taskJson = require('./task.json');

tl.setResourcePath(path.join(__dirname, 'task.json'));

const area: string = 'DownloadBuildArtifacts';
const DefaultParallelProcessingLimit: number = 8;

function getDefaultProps() {
var hostType = (tl.getVariable('SYSTEM.HOSTTYPE') || "").toLowerCase();
Expand Down Expand Up @@ -73,7 +76,7 @@ async function main(): Promise<void> {
var buildId: number = null;
var buildVersionToDownload: string = tl.getInput("buildVersionToDownload", false);
var allowPartiallySucceededBuilds: boolean = tl.getBoolInput("allowPartiallySucceededBuilds", false);
var branchName: string = tl.getInput("branchName", false);;
var branchName: string = tl.getInput("branchName", false);
var downloadPath: string = tl.getInput("downloadPath", true);
var downloadType: string = tl.getInput("downloadType", true);
var tagFiltersInput: string = tl.getInput("tags", false);
Expand Down Expand Up @@ -253,7 +256,7 @@ async function main(): Promise<void> {
if (artifacts) {
var downloadPromises: Array<Promise<any>> = [];
artifacts.forEach(async function (artifact, index, artifacts) {
let downloaderOptions = configureDownloaderOptions();
const downloaderOptions: engine.ArtifactEngineOptions = configureDownloaderOptions();

const config: IBaseHandlerConfig = {
artifactInfo: artifact,
Expand Down Expand Up @@ -372,11 +375,16 @@ function getRetryIntervalInSeconds(retryCount: number): number {
}

function configureDownloaderOptions(): engine.ArtifactEngineOptions {
var downloaderOptions = new engine.ArtifactEngineOptions();
downloaderOptions.itemPattern = tl.getInput('itemPattern', false) || "**";
downloaderOptions.parallelProcessingLimit = +tl.getVariable("release.artifact.download.parallellimit") || 8;
var debugMode = tl.getVariable('System.Debug');
downloaderOptions.verbose = debugMode ? debugMode.toLowerCase() != 'false' : false;
const downloaderOptions: engine.ArtifactEngineOptions = new engine.ArtifactEngineOptions();

const debugMode: string = tl.getVariable('System.Debug');
downloaderOptions.verbose = debugMode ? debugMode.toLowerCase() !== 'false' : false;

const artifactDownloadLimit: string = tl.getVariable('release.artifact.download.parallellimit');
const taskInputParallelLimit: string = tl.getInput('parallelizationLimit', false);
downloaderOptions.parallelProcessingLimit = resolveParallelProcessingLimit(artifactDownloadLimit, taskInputParallelLimit, DefaultParallelProcessingLimit);

downloaderOptions.itemPattern = tl.getInput('itemPattern', false) || '**';

return downloaderOptions;
}
Expand Down
2 changes: 1 addition & 1 deletion Tasks/DownloadBuildArtifactsV0/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"author": "Microsoft Corporation",
"version": {
"Major": 0,
"Minor": 183,
"Minor": 184,
"Patch": 0
},
"groups": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/DownloadBuildArtifactsV0/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"author": "Microsoft Corporation",
"version": {
"Major": 0,
"Minor": 183,
"Minor": 184,
"Patch": 0
},
"groups": [
Expand Down