public async Task Run()
    {
        var process = new WinProcess("robocopy");

        if (outputToConsole)
        {
            process.WriteOutputToConsole();
        }
        process
        .UseArgumentNameDelimiter("")
        .AddArgument(new Quoted(source))
        .AddArgument(new Quoted(target))
        .AddArgument(pattern)
        .UseArgumentNameDelimiter("/")
        .UseArgumentValueDelimiter(":")
        .SetWorkingDirectory(workingDirectory);
        foreach (var arg in options)
        {
            process.AddArgument(arg);
        }
        if (attributesToAdd.Any())
        {
            process.AddArgument("a+", string.Join("", attributesToAdd));
        }
        var result = await process.Run();

        if (result.ExitCode >= 8)
        {
            throw new Exception($"robocopy failed with exit code {result.ExitCode}");
        }
    }
        private async Task packLibProjects(AppKey appKey, string versionNumber)
        {
            Console.WriteLine("Packing Lib Projects");
            var libDir = Path.Combine(Environment.CurrentDirectory, "Lib");

            if (Directory.Exists(libDir))
            {
                string packageVersion;
                string outputPath;
                var    envName = hostEnv.IsProduction()
                    ? "Production"
                    : "Development";
                if (hostEnv.IsProduction())
                {
                    packageVersion = versionNumber;
                }
                else
                {
                    packageVersion = await retrieveDevPackageVersion(appKey);
                }
                outputPath = Path.Combine
                             (
                    getXtiDir(),
                    "Packages",
                    envName
                             );
                foreach (var dir in Directory.GetDirectories(libDir))
                {
                    var packProcess = new WinProcess("dotnet")
                                      .WriteOutputToConsole()
                                      .UseArgumentNameDelimiter("")
                                      .AddArgument("pack")
                                      .AddArgument(dir)
                                      .UseArgumentNameDelimiter("-")
                                      .AddArgument("c", getConfiguration())
                                      .AddArgument("o", new Quoted(outputPath))
                                      .UseArgumentValueDelimiter("=")
                                      .AddArgument("p:PackageVersion", packageVersion);
                    if (!hostEnv.IsProduction())
                    {
                        packProcess
                        .UseArgumentNameDelimiter("--")
                        .AddArgument("include-source")
                        .AddArgument("include-symbols");
                    }
                    var result = await packProcess.Run();

                    result.EnsureExitCodeIsZero();
                }
            }
        }
        private async Task runDotNetPublish(AppKey appKey, AppVersionKey versionKey)
        {
            var publishDir    = getPublishDir(appKey, versionKey);
            var publishAppDir = Path.Combine(publishDir, "App");

            Console.WriteLine($"Publishing web app to '{publishAppDir}'");
            var publishProcess = new WinProcess("dotnet")
                                 .WriteOutputToConsole()
                                 .UseArgumentNameDelimiter("")
                                 .AddArgument("publish")
                                 .AddArgument(new Quoted(getProjectDir(appKey)))
                                 .UseArgumentNameDelimiter("-")
                                 .AddArgument("c", getConfiguration())
                                 .UseArgumentValueDelimiter("=")
                                 .AddArgument("p:PublishProfile", "Default")
                                 .AddArgument("p:PublishDir", publishAppDir);
            var result = await publishProcess.Run();

            result.EnsureExitCodeIsZero();
        }
        private async Task publishSetup(AppKey appKey, AppVersionKey versionKey)
        {
            Console.WriteLine("Publishing setup");
            var setupAppDir = Path.Combine
                              (
                Environment.CurrentDirectory,
                "Apps",
                $"{getAppName(appKey)}SetupApp"
                              );

            if (Directory.Exists(setupAppDir))
            {
                var publishDir        = getPublishDir(appKey, versionKey);
                var versionsPath      = Path.Combine(publishDir, "versions.json");
                var persistedVersions = new PersistedVersions(hubApi, appKey, versionsPath);
                await persistedVersions.Store();

                var publishSetupDir = Path.Combine(publishDir, "Setup");
                Console.WriteLine($"Publishing setup to '{publishSetupDir}'");
                var publishProcess = new WinProcess("dotnet")
                                     .WriteOutputToConsole()
                                     .UseArgumentNameDelimiter("")
                                     .AddArgument("publish")
                                     .AddArgument(new Quoted(setupAppDir))
                                     .UseArgumentNameDelimiter("-")
                                     .AddArgument("c", getConfiguration())
                                     .UseArgumentValueDelimiter("=")
                                     .AddArgument("p:PublishProfile", "Default")
                                     .AddArgument("p:PublishDir", publishSetupDir);
                var result = await publishProcess.Run();

                result.EnsureExitCodeIsZero();
            }
            else
            {
                Console.WriteLine($"Setup App Not Found at '{setupAppDir}'");
            }
        }