async function main()

in Tasks/DownloadBuildArtifactsV0/main.ts [69:366]


async function main(): Promise<void> {
    var promise = new Promise<void>(async (resolve, reject) => {
        var buildType: string = tl.getInput("buildType", true);
        var isCurrentBuild: boolean = buildType.toLowerCase() === 'current';
        var isSpecificBuildWithTriggering: boolean = tl.getBoolInput("specificBuildWithTriggering", false);
        var projectId: string = null;
        var definitionId: string = null;
        var definitionIdSpecified: string = null;
        var definitionIdTriggered: string = null;
        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 downloadPath: string = path.normalize(tl.getInput("downloadPath", true));
        var cleanDestinationFolder: boolean = tl.getBoolInput("cleanDestinationFolder", false);
        var downloadType: string = tl.getInput("downloadType", true);
        var tagFiltersInput: string = tl.getInput("tags", false);
        var tagFilters = [];
        if (!!tagFiltersInput) {
            tagFilters = tagFiltersInput.split(",");
        }
        const checkDownloadedFiles: boolean = tl.getBoolInput('checkDownloadedFiles', false);

        const shouldExtractTars: boolean = tl.getBoolInput('extractTars');
        const isWin = process.platform === 'win32';
        if (shouldExtractTars && isWin) {
            reject(tl.loc('TarExtractionNotSupportedInWindows'));
            return;
        }

        var endpointUrl: string = tl.getVariable("System.TeamFoundationCollectionUri");
        var accessToken: string = tl.getEndpointAuthorizationParameter('SYSTEMVSSCONNECTION', 'AccessToken', false);
        var credentialHandler: IRequestHandler = getHandlerFromToken(accessToken);
        var webApi: WebApi = new WebApi(endpointUrl, credentialHandler);
        const retryLimitRequest: number  = parseInt(tl.getVariable('VSTS_HTTP_RETRY')) ? parseInt(tl.getVariable("VSTS_HTTP_RETRY")) : 4;
        const retryLimitDownload: number = parseInt(tl.getInput('retryDownloadCount', false)) ? parseInt(tl.getInput('retryDownloadCount', false)) : 4;

        var templatePath: string = path.join(__dirname, 'vsts.handlebars.txt');
        var buildApi: IBuildApi = await executeWithRetries("getBuildApi", () => webApi.getBuildApi(), retryLimitRequest).catch((reason) => {
            reject(reason);
            return;
        });
        var artifacts = [];

        // Clean destination folder if requested
        if (cleanDestinationFolder) {
            cleanUpFolder(downloadPath);
        }

        if (isCurrentBuild) {
            projectId = tl.getVariable("System.TeamProjectId");
            definitionId = '';
            buildId = parseInt(tl.getVariable("Build.BuildId"));
        }
        else {
            var releaseAlias: string = tl.getVariable("release.triggeringartifact.alias");
            var triggeringBuildFound: boolean = false;
            definitionIdSpecified = tl.getInput("definition", true);
            if (isSpecificBuildWithTriggering) {
                let hostType = tl.getVariable('system.hostType');
                if ((hostType && hostType.toUpperCase() != 'BUILD')) {
                    // try to use alias to grab triggering artifact for release, starting with definition to verify parity with specified definition
                    definitionIdTriggered = tl.getVariable("release.artifacts." + releaseAlias + ".definitionId");
                    if (definitionIdTriggered == definitionIdSpecified) {
                        // populate values using the triggering build
                        projectId = tl.getVariable("release.artifacts." + releaseAlias + ".projectId");
                        definitionId = definitionIdTriggered;
                        buildId = parseInt(tl.getVariable("release.artifacts." + releaseAlias + ".buildId"));

                        // verify that the triggerring bruild's info was found
                        if (projectId && definitionId && buildId) {
                            triggeringBuildFound = true;
                        }
                    }
                }
                else {
                    //Verify that the triggering build's definition is the same as the specified definition
                    definitionIdTriggered = tl.getVariable("build.triggeredBy.definitionId");
                    if (definitionIdTriggered == definitionIdSpecified) {
                        // populate values using the triggering build
                        projectId = tl.getVariable("build.triggeredBy.projectId");
                        definitionId = definitionIdTriggered;
                        buildId = parseInt(tl.getVariable("build.triggeredBy.buildId"));

                        // verify that the triggerring bruild's info was found
                        if (projectId && definitionId && buildId) {
                            triggeringBuildFound = true;
                        }
                    }
                }
            }

            if (!triggeringBuildFound) {
                // Triggering build info not found, or requested, default to specified build info
                projectId = tl.getInput("project", true);
                definitionId = definitionIdSpecified;
                buildId = parseInt(tl.getInput("buildId", buildVersionToDownload == "specific"));
            }

            // if the definition name includes a variable then definitionIdSpecified is a name vs a number
            if (!!definitionIdSpecified && Number.isNaN(parseInt(definitionIdSpecified))) {
                var definitions: BuildDefinitionReference[] = await executeWithRetries("getBuildDefinitions", () => buildApi.getDefinitions(projectId, definitionIdSpecified), retryLimitRequest).catch((reason) => {
                    reject(reason);
                    return;
                });

                if (!definitions || definitions.length < 1) {
                    reject(tl.loc("InvalidBuildDefinitionName", definitionIdSpecified));
                    return;
                }

                definitionId = String(definitions[0].id);
                console.log(tl.loc("DefinitionNameMatchFound", definitionIdSpecified, definitionId));
            }

            if (!definitionId) {
                reject(tl.loc("UnresolvedDefinitionId"));
                return;
            }
        }

        // verify that buildId belongs to the definition selected
        if (definitionId) {
            var build: Build;
            if (buildVersionToDownload != "specific" && !triggeringBuildFound) {
                var resultFilter = BuildResult.Succeeded;
                if (allowPartiallySucceededBuilds) {
                    resultFilter |= BuildResult.PartiallySucceeded;
                }
                var branchNameFilter = (buildVersionToDownload == "latest") ? null : branchName;

                // get latest successful build filtered by branch
                var buildsForThisDefinition = await executeWithRetries("getBuildId", () => buildApi.getBuilds(projectId, [parseInt(definitionId)], null, null, null, null, null, null, BuildStatus.Completed, resultFilter, tagFilters, null, null, null, null, null, BuildQueryOrder.FinishTimeDescending, branchNameFilter), retryLimitRequest).catch((reason) => {
                    reject(reason);
                    return;
                });

                if (!buildsForThisDefinition || buildsForThisDefinition.length == 0) {
                    if (buildVersionToDownload == "latestFromBranch") reject(tl.loc("LatestBuildFromBranchNotFound", branchNameFilter));
                    else reject(tl.loc("LatestBuildNotFound"));
                    return;
                }

                build = buildsForThisDefinition[0];
                console.log(tl.loc("LatestBuildFound", build.id));
                buildId = build.id
            }

            if (!build) {
                build = await executeWithRetries("getBuild", () => buildApi.getBuild(buildId, projectId), retryLimitRequest).catch((reason) => {
                    reject(reason);
                    return;
                });
            }

            if (build) {
                if (!build.definition || build.definition.id !== parseInt(definitionId)) {
                    reject(tl.loc("BuildIdBuildDefinitionMismatch", buildId, definitionId));
                    return;
                }
            }
            else {
                reject(tl.loc("BuildNotFound", buildId));
                return;
            }
        }

        console.log(tl.loc("DownloadingArtifactsForBuild", buildId));

        // populate output variable 'BuildNumber' with buildId
        tl.setVariable('BuildNumber', buildId.toString());

        // populate itempattern and artifacts based on downloadType
        if (downloadType === 'single') {
            var artifactName = tl.getInput("artifactName", true);
            var artifact = await executeWithRetries("getArtifact", () => buildApi.getArtifact(buildId, artifactName, projectId), retryLimitRequest).catch((reason) => {
                reject(reason);
                return;
            });

            if (!artifact) {
                reject(tl.loc("BuildArtifactNotFound", artifactName, buildId));
                return;
            }

            artifacts.push(artifact);
        }
        else {
            var buildArtifacts = await executeWithRetries("getArtifacts", () => buildApi.getArtifacts(buildId, projectId), retryLimitRequest).catch((reason) => {
                reject(reason);
            });

            if (!buildArtifacts) {
                tl.warning(tl.loc("NoArtifactsFound", buildId));
                resolve();
                return;
            }

            console.log(tl.loc("LinkedArtifactCount", buildArtifacts.length));
            artifacts = artifacts.concat(buildArtifacts);
        }

        if (artifacts) {
            var downloadPromises: Array<Promise<models.ArtifactDownloadTicket[]>> = [];
            artifacts.forEach(async function (artifact, index, artifacts) {
                const downloaderOptions: engine.ArtifactEngineOptions = configureDownloaderOptions();

                const config: IBaseHandlerConfig = {
                    artifactInfo: artifact,
                    downloadPath: downloadPath,
                    downloaderOptions: downloaderOptions,
                    checkDownloadedFiles: checkDownloadedFiles
                };

                if (artifact.resource.type.toLowerCase() === "container") {
                    var handler = new webHandlers.PersonalAccessTokenCredentialHandler(accessToken);
                    // this variable uses to force enable zip download option, it is used only in test purpose and shouldn't be used for other reasons
                    const forceEnableZipDownloadOption = tl.getVariable("DownloadBuildArtifacts.ForceEnableDownloadZipForCanary");
                    const forceEnableZipDownloadOptionBool = forceEnableZipDownloadOption ? forceEnableZipDownloadOption.toLowerCase() == 'true' : false;
                    var isPullRequestFork = tl.getVariable("SYSTEM.PULLREQUEST.ISFORK");
                    var isPullRequestForkBool = isPullRequestFork ? isPullRequestFork.toLowerCase() == 'true' : false;
                    var isZipDownloadDisabled = tl.getVariable("SYSTEM.DisableZipDownload");
                    var isZipDownloadDisabledBool = isZipDownloadDisabled ? isZipDownloadDisabled.toLowerCase() != 'false' : false;

                    // Disable zip download if selective itemPattern provided
                    if (downloaderOptions.itemPattern !== "**") {
                        isZipDownloadDisabledBool = true;
                    }

                    if (isWin && ((!isZipDownloadDisabledBool && isPullRequestForkBool) || forceEnableZipDownloadOptionBool)) {
                        const operationName: string = `Download zip - ${artifact.name}`;

                        const handlerConfig: IContainerHandlerZipConfig = { ...config, projectId, buildId, handler, endpointUrl };
                        const downloadHandler: DownloadHandlerContainerZip = new DownloadHandlerContainerZip(handlerConfig);

                        const downloadPromise: Promise<models.ArtifactDownloadTicket[]> = executeWithRetries(
                            operationName,
                            () => downloadHandler.downloadResources(),
                            retryLimitDownload
                        ).catch((reason) => {
                            reject(reason);
                            return;
                        });

                        downloadPromises.push(downloadPromise);
                        await downloadPromise;
                    } else {
                        const operationName: string = `Download container - ${artifact.name}`;

                        const handlerConfig: IContainerHandlerConfig = { ...config, endpointUrl, templatePath, handler };
                        const downloadHandler: DownloadHandlerContainer = new DownloadHandlerContainer(handlerConfig);
                        const downloadPromise: Promise<models.ArtifactDownloadTicket[]> = executeWithRetries(
                            operationName,
                            () => downloadHandler.downloadResources(),
                            retryLimitDownload
                        ).catch((reason) => {
                            reject(reason);
                            return;
                        });

                        downloadPromises.push(downloadPromise);
                        await downloadPromise;
                    }
                } else if (artifact.resource.type.toLowerCase() === "filepath") {
                    const operationName: string = `Download by FilePath - ${artifact.name}`;

                    const downloadHandler: DownloadHandlerFilePath = new DownloadHandlerFilePath(config);
                    const downloadPromise: Promise<models.ArtifactDownloadTicket[]> = executeWithRetries(
                        operationName,
                        () => downloadHandler.downloadResources(),
                        retryLimitDownload
                    ).catch((reason) => {
                        reject(reason);
                        return;
                    });

                    downloadPromises.push(downloadPromise);
                    await downloadPromise;
                } else {
                    console.log(tl.loc("UnsupportedArtifactType", artifact.resource.type));
                }
            });

            Promise.all(downloadPromises).then((tickets: models.ArtifactDownloadTicket[][]) => {
                console.log(tl.loc('ArtifactsSuccessfullyDownloaded', downloadPath));

                if (shouldExtractTars) {
                    extractTarsIfPresent(tickets, downloadPath);
                }

                resolve();
            }).catch((error) => {
                reject(error);
            });
        }
    });
    return promise;
}