async function run()

in Tasks/AppCenterDistributeV3/appcenterdistribute.ts [541:678]


async function run() {
    try {
        tl.setResourcePath(path.join(__dirname, 'task.json'));

        // Get build inputs
        let apiEndpointData = getEndpointDetails('serverEndpoint');
        let apiToken: string = apiEndpointData.authToken;
        let apiServer: string = apiEndpointData.apiServer;
        let apiVersion: string = apiEndpointData.apiVersion;

        let userAgent = tl.getVariable('MSDEPLOY_HTTP_USER_AGENT');
        if (!userAgent) {
            userAgent = 'VSTS';
        }
        userAgent = userAgent + ' (Task:VSMobileCenterUpload)';

        var effectiveApiServer = process.env['SONOMA_API_SERVER'] || apiServer;
        var effectiveApiVersion = process.env['SONOMA_API_VERSION'] || apiVersion;

        tl.debug(`Effective API Url: ${effectiveApiServer}/${effectiveApiVersion}`);

        let appSlug: string = tl.getInput('appSlug', true);
        let appFilePattern: string = tl.getInput('app', true);

        /* The task has support for different symbol types but App Center server only support Apple currently, add back these types in the task.json when support is available in App Center.
        "AndroidNative": "Android (native C/C++)",
        "Windows": "Windows 8.1",
        "UWP": "Universal Windows Platform (UWP)"
        */
        const symbolType: TaskSymbolType = tl.getInput('symbolsType', false) as TaskSymbolType;
        const symbolsLookup: { symbolType: ApiSymbolType, fieldName: string, forceArchive?: boolean }[] = [];
        switch (symbolType) {
            case "Apple":
                symbolsLookup.push({ symbolType, fieldName: "dsymPath" });
                break;
            case "Android":
                symbolsLookup.push({ symbolType: "AndroidProguard", fieldName: "mappingTxtPath" });
                symbolsLookup.push({ symbolType: "Breakpad", fieldName: "nativeLibrariesPath", forceArchive: true });
                break;
            case "UWP":
                symbolsLookup.push({ symbolType, fieldName: "appxsymPath" });
                break;
            default:
                symbolsLookup.push({ symbolType, fieldName: "symbolsPath" });
        }

        let buildVersion: string = tl.getInput('buildVersion', false);
        let packParentFolder: boolean = tl.getBoolInput('packParentFolder', false);

        let releaseNotesSelection = tl.getInput('releaseNotesSelection', true);
        let releaseNotes: string = null;
        if (releaseNotesSelection === 'file') {
            let releaseNotesFile = tl.getPathInput('releaseNotesFile', true, true);
            releaseNotes = fs.readFileSync(releaseNotesFile).toString('utf8');
        } else {
            releaseNotes = tl.getInput('releaseNotesInput', true);
        }

        let isMandatory: boolean = tl.getBoolInput('isMandatory', false);

        const destinationType = tl.getInput('destinationType', false) as DestinationType || DestinationType.Groups;
        const destinationsInputName = destinationType === DestinationType.Groups ? 'destinationGroupIds' : 'destinationStoreId';
        const destinationIsMandatory = destinationType === DestinationType.Store;

        let destinations = tl.getInput(destinationsInputName, destinationIsMandatory) || "00000000-0000-0000-0000-000000000000";
        tl.debug(`Effective destinationIds: ${destinations}`);
        let destinationIds = destinations.split(/[, ;]+/).map(id => id.trim()).filter(id => id);

        // Validate inputs
        if (!apiToken) {
            throw new Error(tl.loc("NoApiTokenFound"));
        }
        if (!destinationIds.length) {
            throw new Error(tl.loc("InvalidDestinationInput"));
        }
        if (destinationType === DestinationType.Store && destinationIds.length > 1) {
            throw new Error(tl.loc("CanNotDistributeToMultipleStores"));
        }

        const isSilent: boolean = destinationType === DestinationType.Groups && (tl.getBoolInput('isSilent', false) || false);

        let app = utils.resolveSinglePath(appFilePattern);
        tl.checkPath(app, "Binary file");

        let continueIfSymbolsNotFoundVariable = tl.getVariable('VSMobileCenterUpload.ContinueIfSymbolsNotFound');
        let continueIfSymbolsNotFound = false;
        if (continueIfSymbolsNotFoundVariable && continueIfSymbolsNotFoundVariable.toLowerCase() === 'true') {
            continueIfSymbolsNotFound = true;
        }

        // Begin release upload
        let uploadInfo: UploadInfo = await beginReleaseUpload(effectiveApiServer, effectiveApiVersion, appSlug, apiToken, userAgent, buildVersion);
        const uploadId = uploadInfo.id;
        let releaseId: string;

        await uploadRelease(uploadInfo, app);
        await patchRelease(effectiveApiServer, effectiveApiVersion, appSlug, uploadId, apiToken, userAgent);
        releaseId = await loadReleaseIdUntilSuccess(effectiveApiServer, effectiveApiVersion, appSlug, uploadId, apiToken, userAgent);

        await updateRelease(effectiveApiServer, effectiveApiVersion, appSlug, releaseId, releaseNotes, apiToken, userAgent);

        await Q.all(destinationIds.map(destinationId => {
            return publishRelease(effectiveApiServer, effectiveApiVersion, appSlug, releaseId, destinationType, isMandatory, isSilent, destinationId, apiToken, userAgent);
        }));

        for (const { fieldName, symbolType, forceArchive } of symbolsLookup) {
            const symbolsPathPattern: string = tl.getInput(fieldName, false);

            // Expand symbols path pattern to a list of paths
            const symbolsPaths = expandSymbolsPaths(symbolType, symbolsPathPattern, continueIfSymbolsNotFound, packParentFolder);

            // Prepare symbols
            const symbolsFile = await prepareSymbols(symbolsPaths, forceArchive);

            if (symbolsFile) {
                // Begin preparing upload symbols
                let version: string;
                let build: string;
                if (symbolType === "AndroidProguard") {
                    const release = await getRelease(effectiveApiServer, effectiveApiVersion, appSlug, releaseId, apiToken, userAgent);
                    version = release.short_version;
                    build = release.version;
                }
                const symbolsUploadInfo = await beginSymbolUpload(effectiveApiServer, effectiveApiVersion, appSlug, symbolType, apiToken, userAgent, version, build);

                // upload symbols
                await uploadSymbols(symbolsUploadInfo.upload_url, symbolsFile);

                // Commit the symbols upload
                await commitSymbols(effectiveApiServer, effectiveApiVersion, appSlug, symbolsUploadInfo.symbol_upload_id, apiToken, userAgent);
            }
        }

        tl.setResult(tl.TaskResult.Succeeded, tl.loc("Succeeded"));
    } catch (err) {
        tl.setResult(tl.TaskResult.Failed, `${err}`);
    }
}