async function run()

in Tasks/CopyFilesOverSSHV0/copyfilesoverssh.ts [102:248]


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

        // read SSH endpoint input
        const sshEndpoint = tl.getInput('sshEndpoint', true);
        const username: string = tl.getEndpointAuthorizationParameter(sshEndpoint, 'username', false);
        const password: string = tl.getEndpointAuthorizationParameter(sshEndpoint, 'password', true); //passphrase is optional
        const privateKey: string = process.env['ENDPOINT_DATA_' + sshEndpoint + '_PRIVATEKEY']; //private key is optional, password can be used for connecting
        const hostname: string = tl.getEndpointDataParameter(sshEndpoint, 'host', false);
        let port: string = tl.getEndpointDataParameter(sshEndpoint, 'port', true); //port is optional, will use 22 as default port if not specified
        if (!port) {
            console.log(tl.loc('UseDefaultPort'));
            port = '22';
        }

        const readyTimeout = getReadyTimeoutVariable();
        const useFastPut: boolean = !(process.env['USE_FAST_PUT'] === 'false');

        // set up the SSH connection configuration based on endpoint details
        let sshConfig;
        if (privateKey) {
            tl.debug('Using private key for ssh connection.');
            sshConfig = {
                host: hostname,
                port: port,
                username: username,
                privateKey: privateKey,
                passphrase: password,
                readyTimeout: readyTimeout,
                useFastPut: useFastPut
            }
        } else {
            // use password
            tl.debug('Using username and password for ssh connection.');
            sshConfig = {
                host: hostname,
                port: port,
                username: username,
                password: password,
                readyTimeout: readyTimeout,
                useFastPut: useFastPut
            }
        }

        // contents is a multiline input containing glob patterns
        const contents: string[] = tl.getDelimitedInput('contents', '\n', true);
        const sourceFolder: string = tl.getPathInput('sourceFolder', true, true);
        let targetFolder: string = tl.getInput('targetFolder');

        if (!targetFolder) {
            targetFolder = "./";
        } else {
            // '~/' is unsupported
            targetFolder = targetFolder.replace(/^~\//, "./");
        }

        // read the copy options
        const cleanTargetFolder: boolean = tl.getBoolInput('cleanTargetFolder', false);
        const overwrite: boolean = tl.getBoolInput('overwrite', false);
        const failOnEmptySource: boolean = tl.getBoolInput('failOnEmptySource', false);
        const flattenFolders: boolean = tl.getBoolInput('flattenFolders', false);

        if (!tl.stats(sourceFolder).isDirectory()) {
            throw tl.loc('SourceNotFolder');
        }

        // initialize the SSH helpers, set up the connection
        sshHelper = new SshHelper(sshConfig);
        await sshHelper.setupConnection();

        if (cleanTargetFolder && await sshHelper.checkRemotePathExists(targetFolder)) {
            console.log(tl.loc('CleanTargetFolder', targetFolder));
            const isWindowsOnTarget: boolean = tl.getBoolInput('isWindowsOnTarget', false);
            const cleanTargetFolderCmd: string = utils.getCleanTargetFolderCmd(targetFolder, isWindowsOnTarget);
            try {
                await sshHelper.runCommandOnRemoteMachine(cleanTargetFolderCmd, null);
            } catch (err) {
                throw tl.loc('CleanTargetFolderFailed', err);
            }
        }

        // identify the files to copy
        const filesToCopy: string[] = getFilesToCopy(sourceFolder, contents);

        // copy files to remote machine
        if (filesToCopy) {
            tl.debug('Number of files to copy = ' + filesToCopy.length);
            tl.debug('filesToCopy = ' + filesToCopy);

            let failureCount = 0;
            console.log(tl.loc('CopyingFiles', filesToCopy.length));
            for (const fileToCopy of filesToCopy) {
                try {
                    tl.debug('fileToCopy = ' + fileToCopy);

                    let relativePath;
                    if (flattenFolders) {
                        relativePath = path.basename(fileToCopy);
                    } else {
                        relativePath = fileToCopy.substring(sourceFolder.length)
                            .replace(/^\\/g, "")
                            .replace(/^\//g, "");
                    }
                    tl.debug('relativePath = ' + relativePath);
                    let targetPath = path.posix.join(targetFolder, relativePath);

                    if (!path.isAbsolute(targetPath) && !utils.pathIsUNC(targetPath)) {
                        targetPath = `./${targetPath}`;
                    }

                    console.log(tl.loc('StartedFileCopy', fileToCopy, targetPath));
                    if (!overwrite) {
                        const fileExists: boolean = await sshHelper.checkRemotePathExists(targetPath);
                        if (fileExists) {
                            throw tl.loc('FileExists', targetPath);
                        }
                    }

                    targetPath = utils.unixyPath(targetPath);
                    // looks like scp can only handle one file at a time reliably
                    await sshHelper.uploadFile(fileToCopy, targetPath);
                } catch (err) {
                    tl.error(tl.loc('FailedOnFile', fileToCopy, err));
                    failureCount++;
                }
            }
            console.log(tl.loc('CopyCompleted', filesToCopy.length));
            if (failureCount) {
                tl.setResult(tl.TaskResult.Failed, tl.loc('NumberFailed', failureCount));
            }
        } else if (failOnEmptySource) {
            throw tl.loc('NothingToCopy');
        } else {
            tl.warning(tl.loc('NothingToCopy'));
        }
    } catch (err) {
        tl.setResult(tl.TaskResult.Failed, err);
    } finally {
        // close the client connection to halt build execution
        if (sshHelper) {
            tl.debug('Closing the client connection');
            await sshHelper.closeConnection();
        }
    }
}