Beispiel #1
0
        public override async Task RunAsync()
        {
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            ColoredConsole.WriteLine(WarningColor($"Publish {functionAppRoot} contents to an Azure Function App. Locally deleted files are not removed from destination."));
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            using (var client = await GetRemoteZipClient(new Uri($"https://{functionApp.ScmUri}")))
                using (var request = new HttpRequestMessage())
                {
                    request.Method     = HttpMethod.Put;
                    request.RequestUri = new Uri("api/zip/site/wwwroot", UriKind.Relative);
                    request.Headers.IfMatch.Add(EntityTagHeaderValue.Any);
                    ColoredConsole.WriteLine("Creating archive for current directory...");
                    request.Content = CreateZip(functionAppRoot);
                    ColoredConsole.WriteLine("Uploading archive...");
                    var response = await client.SendAsync(request);

                    response.EnsureSuccessStatusCode();
                    response = await client.PostAsync("api/functions/synctriggers", content : null);

                    response.EnsureSuccessStatusCode();
                    ColoredConsole.WriteLine("Upload completed successfully.");
                }
        }
Beispiel #2
0
        public override async Task RunAsync()
        {
            var functionAppRoot = string.IsNullOrEmpty(FolderName)
                ? Path.Combine(Environment.CurrentDirectory, FolderName)
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            string outputPath;

            if (string.IsNullOrEmpty(OutputPath))
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, $"{Path.GetFileName(functionAppRoot)}.zip");
            }
            else
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath);
                if (FileSystemHelpers.DirectoryExists(outputPath))
                {
                    outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip");
                }
            }

            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)))
            {
                throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}");
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            var zipStream = await GetAppZipFile(workerRuntimeEnum, functionAppRoot);

            await FileSystemHelpers.WriteToFile(outputPath, zipStream);
        }
        private static async Task <bool> IsRightServer(Uri server)
        {
            try
            {
                var hostId = await GetHostId(ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory));

                if (string.IsNullOrWhiteSpace(hostId))
                {
                    return(true);
                }

                using (var client = new HttpClient())
                {
                    var response = await client.GetAsync(new Uri(server, "admin/host/status"));

                    response.EnsureSuccessStatusCode();

                    var hostStatus = await response.Content.ReadAsAsync <HostStatus>();

                    return(hostStatus.Id.Equals(hostId, StringComparison.OrdinalIgnoreCase));
                }
            }
            catch
            {
                return(false);
            }
        }
        public override async Task RunAsync()
        {
            var functionAppRoot = string.IsNullOrEmpty(FolderName)
                ? Path.Combine(Environment.CurrentDirectory, FolderName)
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            string outputPath;

            if (string.IsNullOrEmpty(OutputPath))
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, $"{Path.GetFileName(functionAppRoot)}.zip");
            }
            else
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath);
                if (FileSystemHelpers.DirectoryExists(outputPath))
                {
                    outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip");
                }
            }

            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)))
            {
                throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}");
            }

            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            var zipStream = await ZipHelper.GetAppZipFile(workerRuntime, functionAppRoot, BuildNativeDeps);

            await FileSystemHelpers.WriteToFile(outputPath, zipStream);
        }
Beispiel #5
0
        public override async Task RunAsync()
        {
            Utilities.PrintLogo();

            var traceLevel = await ScriptHostHelpers.GetTraceLevel(ScriptRoot);

            var settings = SelfHostWebHostSettingsFactory.Create(traceLevel, ScriptRoot);

            (var baseAddress, var certificate) = Setup();

            IWebHost host = await BuildWebHost(settings, baseAddress, certificate);

            var runTask = host.RunAsync();

            var manager = host.Services.GetRequiredService <WebScriptHostManager>();
            await manager.DelayUntilHostReady();

            ColoredConsole.WriteLine($"Listening on {baseAddress}");
            ColoredConsole.WriteLine("Hit CTRL-C to exit...");

            DisableCoreLogging(manager);
            DisplayHttpFunctionsInfo(manager, baseAddress);
            DisplayDisabledFunctions(manager);
            await SetupDebuggerAsync(baseAddress);

            await runTask;
        }
Beispiel #6
0
        public override async Task RunAsync()
        {
            // Get function app
            var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken, ManagementURL);

            // Get the GitIgnoreParser from the functionApp root
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);
            var ignoreParser    = PublishHelper.GetIgnoreParser(functionAppRoot);

            // Get the WorkerRuntime
            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            // Check for any additional conditions or app settings that need to change
            // before starting any of the publish activity.
            var additionalAppSettings = await ValidateFunctionAppPublish(functionApp, workerRuntime);

            if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "publish");
                    await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }

            if (workerRuntime != WorkerRuntime.dotnet || Csx)
            {
                // Restore all valid extensions
                var installExtensionAction = new InstallExtensionAction(_secretsManager, false);
                await installExtensionAction.RunAsync();
            }

            if (ListIncludedFiles)
            {
                InternalListIncludedFiles(ignoreParser);
            }
            else if (ListIgnoredFiles)
            {
                InternalListIgnoredFiles(ignoreParser);
            }
            else
            {
                if (PublishLocalSettingsOnly)
                {
                    await PublishLocalAppSettings(functionApp, additionalAppSettings);
                }
                else
                {
                    await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings);
                }
            }
        }
        public override async Task RunAsync()
        {
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            ColoredConsole.WriteLine(WarningColor($"Publish {functionAppRoot} contents to an Azure Function App. Locally deleted files are not removed from destination."));
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            if (PublishLocalSettingsOnly)
            {
                var isSuccessful = await PublishAppSettings(functionApp);

                if (!isSuccessful)
                {
                    return;
                }
            }
            else
            {
                await RetryHelper.Retry(async() =>
                {
                    using (var client = await GetRemoteZipClient(new Uri($"https://{functionApp.ScmUri}")))
                        using (var request = new HttpRequestMessage(HttpMethod.Put, new Uri("api/zip/site/wwwroot", UriKind.Relative)))
                        {
                            request.Headers.IfMatch.Add(EntityTagHeaderValue.Any);

                            ColoredConsole.WriteLine("Creating archive for current directory...");

                            request.Content = CreateZip(functionAppRoot);

                            ColoredConsole.WriteLine("Uploading archive...");
                            var response = await client.SendAsync(request);
                            if (!response.IsSuccessStatusCode)
                            {
                                throw new CliException($"Error uploading archive ({response.StatusCode}).");
                            }

                            response = await client.PostAsync("api/functions/synctriggers", content: null);
                            if (!response.IsSuccessStatusCode)
                            {
                                throw new CliException($"Error calling sync triggers ({response.StatusCode}).");
                            }

                            if (PublishLocalSettings)
                            {
                                var isSuccessful = await PublishAppSettings(functionApp);
                                if (!isSuccessful)
                                {
                                    return;
                                }
                            }

                            ColoredConsole.WriteLine("Upload completed successfully.");
                        }
                }, 2);
            }
        }
Beispiel #8
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            // For dedicated linux apps, we do not support run from package right now
            if (functionApp.IsLinux && !functionApp.IsDynamic && RunFromPackageDeploy)
            {
                ColoredConsole.WriteLine("Assuming --nozip (do not run from package) for publishing to Linux dedicated plan.");
                RunFromPackageDeploy = false;
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            if (workerRuntimeEnum == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            // If Consumption Linux
            if (functionApp.IsLinux && (functionApp.IsDynamic || functionApp.IsElasticPremium))
            {
                await PublishRunFromPackage(functionApp, await zipStreamFactory());
            }
            // If Windows default
            else if (RunFromPackageDeploy)
            {
                await PublishRunFromPackageLocal(functionApp, zipStreamFactory);
            }
            // If Dedicated Linux or "--no-zip"
            else
            {
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            // Syncing triggers is not required when using zipdeploy api
            if ((functionApp.IsLinux && (functionApp.IsDynamic || functionApp.IsElasticPremium)) ||
                RunFromPackageDeploy)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
                await SyncTriggers(functionApp);
            }
            await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, showKeys : true);
        }
Beispiel #9
0
        public override async Task RunAsync()
        {
            var functionAppRoot = string.IsNullOrEmpty(FolderName)
                ? Path.Combine(Environment.CurrentDirectory, FolderName)
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            string outputPath;

            if (string.IsNullOrEmpty(OutputPath))
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, $"{Path.GetFileName(functionAppRoot)}");
            }
            else
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath);
                if (FileSystemHelpers.DirectoryExists(outputPath))
                {
                    outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}");
                }
            }

            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)))
            {
                throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}");
            }

            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            outputPath += Squashfs ? ".squashfs" : ".zip";
            if (FileSystemHelpers.FileExists(outputPath))
            {
                ColoredConsole.WriteLine($"Deleting the old package {outputPath}");
                try
                {
                    FileSystemHelpers.FileDelete(outputPath);
                }
                catch (Exception)
                {
                    throw new CliException($"Could not delete {outputPath}");
                }
            }

            // Restore all valid extensions
            var installExtensionAction = new InstallExtensionAction(_secretsManager, false);
            await installExtensionAction.RunAsync();

            var stream = await ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, noBuild : false, buildOption : BuildOption.Default, additionalPackages : AdditionalPackages);

            if (Squashfs)
            {
                stream = await PythonHelpers.ZipToSquashfsStream(stream);
            }

            ColoredConsole.WriteLine($"Creating a new package {outputPath}");
            await FileSystemHelpers.WriteToFile(outputPath, stream);
        }
Beispiel #10
0
        public override async Task RunAsync()
        {
            Utilities.PrintLogo();

            var scriptPath = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);
            var traceLevel = await ScriptHostHelpers.GetTraceLevel(scriptPath);

            var settings = SelfHostWebHostSettingsFactory.Create(traceLevel, scriptPath);


            var baseAddress = Setup();

            await ReadSecrets(scriptPath, baseAddress);

            var config = new HttpSelfHostConfiguration(baseAddress)
            {
                IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always,
                TransferMode             = TransferMode.Streamed,
                HostNameComparisonMode   = HostNameComparisonMode.Exact,
                MaxReceivedMessageSize   = 1 * 1024 * 1024 * 100 // 1 byte * 1,024 * 1,024 * 100 = 100 MB (or 104,857,600 bytes)
            };

            if (!string.IsNullOrEmpty(CorsOrigins))
            {
                var cors = new EnableCorsAttribute(CorsOrigins, "*", "*");
                config.EnableCors(cors);
            }
            config.Formatters.Add(new JsonMediaTypeFormatter());

            Environment.SetEnvironmentVariable("EDGE_NODE_PARAMS", $"--debug={NodeDebugPort}", EnvironmentVariableTarget.Process);

            WebApiConfig.Initialize(config, settings: settings);

            using (var httpServer = new HttpSelfHostServer(config))
            {
                await httpServer.OpenAsync();

                ColoredConsole.WriteLine($"Listening on {baseAddress}");
                ColoredConsole.WriteLine("Hit CTRL-C to exit...");
                await PostHostStartActions(config);

                await Task.Delay(-1);

                await httpServer.CloseAsync();
            }
        }
        public override async Task RunAsync()
        {
            var functionAppRoot = string.IsNullOrEmpty(FolderName)
                ? Path.Combine(Environment.CurrentDirectory, FolderName)
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            string outputPath;

            if (string.IsNullOrEmpty(OutputPath))
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, $"{Path.GetFileName(functionAppRoot)}.zip");
            }
            else
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath);
                if (FileSystemHelpers.DirectoryExists(outputPath))
                {
                    outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip");
                }
            }

            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)))
            {
                throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}");
            }

            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            if (FileSystemHelpers.FileExists(outputPath))
            {
                ColoredConsole.WriteLine($"Deleting the old package {outputPath}");
                try
                {
                    FileSystemHelpers.FileDelete(outputPath);
                }
                catch (Exception)
                {
                    throw new CliException($"Could not delete {outputPath}");
                }
            }
            var zipStream = await ZipHelper.GetAppZipFile(workerRuntime, functionAppRoot, BuildNativeDeps, NoBundler, additionalPackages : AdditionalPackages);

            ColoredConsole.WriteLine($"Creating a new package {outputPath}");
            await FileSystemHelpers.WriteToFile(outputPath, zipStream);
        }
Beispiel #12
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            if (functionApp.IsLinux && !functionApp.IsDynamic && RunFromZipDeploy)
            {
                throw new CliException("--zip is not supported with dedicated linux apps.");
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            if (workerRuntimeEnum == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            // if consumption Linux, or --zip, run from zip
            if ((functionApp.IsLinux && functionApp.IsDynamic) || RunFromZipDeploy)
            {
                await PublishRunFromZip(functionApp, await zipStreamFactory());
            }
            else
            {
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            await Task.Delay(TimeSpan.FromSeconds(5));

            await SyncTriggers(functionApp);

            await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, showKeys : true);
        }
Beispiel #13
0
        public override async Task RunAsync()
        {
            // Get function app
            var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken);

            // Get the GitIgnoreParser from the functionApp root
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);
            var ignoreParser    = PublishHelper.GetIgnoreParser(functionAppRoot);

            // Get the WorkerRuntime
            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            // Check for any additional conditions or app settings that need to change
            // before starting any of the publish activity.
            var additionalAppSettings = ValidateFunctionAppPublish(functionApp, workerRuntime);

            if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild)
            {
                const string outputPath = "bin/publish";
                await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters);

                Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
            }

            if (ListIncludedFiles)
            {
                InternalListIncludedFiles(ignoreParser);
            }
            else if (ListIgnoredFiles)
            {
                InternalListIgnoredFiles(ignoreParser);
            }
            else
            {
                if (PublishLocalSettingsOnly)
                {
                    await PublishLocalAppSettings(functionApp, additionalAppSettings);
                }
                else
                {
                    await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings);
                }
            }
        }
        private async Task InternalPublishFunctionApp(GitIgnoreParser ignoreParser)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            if (functionApp.IsLinux && !functionApp.IsDynamicLinux && RunFromZipDeploy)
            {
                ColoredConsole
                .WriteLine(ErrorColor("--zip is not supported with dedicated linux apps."));
                return;
            }

            var workerRuntime = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;

            if (!string.IsNullOrWhiteSpace(workerRuntime))
            {
                var worker = WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);
                if (worker == WorkerRuntime.python)
                {
                    if (!SkipWheelRestore)
                    {
                        await PythonHelpers.InstallPipWheel();

                        await PythonHelpers.DownloadWheels();
                    }
                    else
                    {
                        ColoredConsole.WriteLine("Skipping wheels download");
                    }
                }
            }

            // if consumption linux, or --zip, run from zip
            if (functionApp.IsDynamicLinux || RunFromZipDeploy)
            {
                await PublishRunFromZip(functionApp, functionAppRoot, ignoreParser);
            }
            else
            {
                await PublishZipDeploy(functionApp, functionAppRoot, ignoreParser);
            }
        }
Beispiel #15
0
        public override async Task RunAsync()
        {
            Utilities.PrintLogo();

            var scriptPath = IgnoreHostJsonNotFound
                ? Environment.CurrentDirectory
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);
            var settings = SelfHostWebHostSettingsFactory.Create(ConsoleTraceLevel, scriptPath);

            ReadSecrets();
            CheckHostJsonId();

            var baseAddress = Setup();

            var config = new HttpSelfHostConfiguration(baseAddress)
            {
                IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always,
                TransferMode             = TransferMode.Streamed
            };

            var cors = new EnableCorsAttribute(CorsOrigins, "*", "*");

            config.EnableCors(cors);
            config.Formatters.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());

            Environment.SetEnvironmentVariable("EDGE_NODE_PARAMS", $"--debug={NodeDebugPort}", EnvironmentVariableTarget.Process);

            WebApiConfig.Initialize(config, settings: settings);

            using (var httpServer = new HttpSelfHostServer(config))
            {
                await httpServer.OpenAsync();

                ColoredConsole.WriteLine($"Listening on {baseAddress}");
                ColoredConsole.WriteLine("Hit CTRL-C to exit...");
                await PostHostStartActions(config);

                await Task.Delay(-1);

                await httpServer.CloseAsync();
            }
        }
        private async Task InternalPublishFunctionApp(GitIgnoreParser ignoreParser)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            if (functionApp.IsLinux && !functionApp.IsDynamic && RunFromZipDeploy)
            {
                ColoredConsole
                .WriteLine(ErrorColor("--zip is not supported with dedicated linux apps."));
                return;
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            if (workerRuntimeEnum == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            var zipStream = await ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, ignoreParser);

            // if consumption Linux, or --zip, run from zip
            if ((functionApp.IsLinux && functionApp.IsDynamic) || RunFromZipDeploy)
            {
                await PublishRunFromZip(functionApp, zipStream);
            }
            else
            {
                await PublishZipDeploy(functionApp, zipStream);
            }

            await SyncTriggers(functionApp);

            if (PublishLocalSettings)
            {
                await PublishAppSettings(functionApp);
            }
        }
        private async Task InternalPublishFunctionApp(GitIgnoreParser ignoreParser)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            if (functionApp.IsLinux && !functionApp.IsDynamicLinux && RunFromZipDeploy)
            {
                ColoredConsole
                .WriteLine(ErrorColor("--zip is not supported with dedicated linux apps."));
            }
            // if consumption linux, or --zip, run from zip
            else if (functionApp.IsDynamicLinux || RunFromZipDeploy)
            {
                await PublishRunFromZip(functionApp, functionAppRoot, ignoreParser);
            }
            else
            {
                await PublishZipDeploy(functionApp, functionAppRoot, ignoreParser);
            }
            // else same old same old
        }
        public override Task RunAsync()
        {
            ScriptHostHelpers.SetIsHelpRunning();

            Utilities.PrintLogo();
            if (!string.IsNullOrEmpty(_context) || !string.IsNullOrEmpty(_subContext))
            {
                var context    = Context.None;
                var subContext = Context.None;

                if (!string.IsNullOrEmpty(_context) && !Enum.TryParse(_context, true, out context))
                {
                    ColoredConsole.Error.WriteLine(ErrorColor($"Error: unknown argument {_context}"));
                    DisplayGeneralHelp();
                    return(Task.CompletedTask);
                }

                if (!string.IsNullOrEmpty(_subContext) && !Enum.TryParse(_subContext, true, out subContext))
                {
                    ColoredConsole.Error.WriteLine(ErrorColor($"Error: unknown argument {_subContext} in {context.ToLowerCaseString()} Context"));
                    DisplayContextHelp(context, Context.None);
                    return(Task.CompletedTask);
                }

                DisplayContextHelp(context, subContext);
            }
            else if (_action != null && _parseResult != null)
            {
                DisplayActionHelp();
            }
            else
            {
                DisplayGeneralHelp();
            }
            return(Task.CompletedTask);
        }
Beispiel #19
0
        public override async Task RunAsync()
        {
            // Get function app
            var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken, ManagementURL, Slot, Subscription);

            if (!functionApp.IsLinux && (PublishBuildOption == BuildOption.Container || PublishBuildOption == BuildOption.Remote))
            {
                throw new CliException($"--build {PublishBuildOption} is not supported for Windows Function Apps.");
            }

            // Get the GitIgnoreParser from the functionApp root
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);
            var ignoreParser    = PublishHelper.GetIgnoreParser(functionAppRoot);

            // Get the WorkerRuntime
            var workerRuntime = GlobalCoreToolsSettings.CurrentWorkerRuntime;

            // Check for any additional conditions or app settings that need to change
            // before starting any of the publish activity.
            var additionalAppSettings = await ValidateFunctionAppPublish(functionApp, workerRuntime);

            // Update build option
            PublishBuildOption = PublishHelper.ResolveBuildOption(PublishBuildOption, workerRuntime, functionApp, BuildNativeDeps, NoBuild);

            if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild && PublishBuildOption != BuildOption.Remote)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "publish");
                    await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }

            if (workerRuntime != WorkerRuntime.dotnet || Csx)
            {
                // Restore all valid extensions
                var installExtensionAction = new InstallExtensionAction(_secretsManager, false);
                await installExtensionAction.RunAsync();
            }

            if (ListIncludedFiles)
            {
                InternalListIncludedFiles(ignoreParser);
            }
            else if (ListIgnoredFiles)
            {
                InternalListIgnoredFiles(ignoreParser);
            }
            else
            {
                if (PublishLocalSettingsOnly)
                {
                    await PublishLocalAppSettings(functionApp, additionalAppSettings);
                }
                else
                {
                    await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings);
                }
            }
        }
Beispiel #20
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            // For dedicated linux apps, we do not support run from package right now
            var isFunctionAppDedicated = !functionApp.IsDynamic && !functionApp.IsElasticPremium;

            if (functionApp.IsLinux && isFunctionAppDedicated && RunFromPackageDeploy)
            {
                ColoredConsole.WriteLine("Assuming --nozip (do not run from package) for publishing to Linux dedicated plan.");
                RunFromPackageDeploy = false;
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            if (workerRuntimeEnum == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            bool shouldSyncTriggers  = true;
            var  fileNameNoExtension = string.Format("{0}-{1}", DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"), Guid.NewGuid());

            if (functionApp.IsLinux && functionApp.IsDynamic)
            {
                // Consumption Linux, try squashfs as a package format.
                if (workerRuntimeEnum == WorkerRuntime.python && !NoBuild && BuildNativeDeps)
                {
                    await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipStreamFactory()), $"{fileNameNoExtension}.squashfs");
                }
                else
                {
                    await PublishRunFromPackage(functionApp, await zipStreamFactory(), $"{fileNameNoExtension}.zip");
                }
            }
            else if (functionApp.IsLinux && functionApp.IsElasticPremium)
            {
                // Elastic Premium Linux
                await PublishRunFromPackage(functionApp, await zipStreamFactory(), $"{fileNameNoExtension}.zip");
            }
            else if (RunFromPackageDeploy)
            {
                // Windows default
                await PublishRunFromPackageLocal(functionApp, zipStreamFactory);
            }
            else
            {
                // ZipDeploy takes care of the SyncTriggers operation so we don't
                // need to perform one
                shouldSyncTriggers = false;

                // Dedicated Linux or "--no-zip"
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            if (shouldSyncTriggers)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
                await SyncTriggers(functionApp);
            }

            // Linux Elastic Premium functions take longer to deploy. Right now, we cannot guarantee that functions info will be most up to date.
            // So, we only show the info, if Function App is not Linux Elastic Premium
            if (!(functionApp.IsLinux && functionApp.IsElasticPremium))
            {
                await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true);
            }
        }
Beispiel #21
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            // For dedicated linux apps, we do not support run from package right now
            var isFunctionAppDedicatedLinux = functionApp.IsLinux && !functionApp.IsDynamic && !functionApp.IsElasticPremium;

            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            // Recommend Linux scm users to use --build remote instead of --build-native-deps
            if (BuildNativeDeps && functionApp.IsLinux && !string.IsNullOrEmpty(functionApp.ScmUri))
            {
                ColoredConsole.WriteLine(Yellow("Recommend using '--build remote' to resolve project dependencies remotely on Azure"));
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, PublishBuildOption,
                                                                                   NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            bool shouldSyncTriggers = true;

            if (functionApp.IsLinux && functionApp.IsDynamic)
            {
                // Consumption Linux
                shouldSyncTriggers = await HandleLinuxConsumptionPublish(functionApp, zipStreamFactory);
            }
            else if (functionApp.IsLinux && functionApp.IsElasticPremium)
            {
                // Elastic Premium Linux
                shouldSyncTriggers = await HandleElasticPremiumLinuxPublish(functionApp, zipStreamFactory);
            }
            else if (isFunctionAppDedicatedLinux)
            {
                // Dedicated Linux
                shouldSyncTriggers = false;
                await HandleLinuxDedicatedPublish(functionApp, zipStreamFactory);
            }
            else if (RunFromPackageDeploy)
            {
                // Windows default
                await PublishRunFromPackageLocal(functionApp, zipStreamFactory);
            }
            else
            {
                // ZipDeploy takes care of the SyncTriggers operation so we don't
                // need to perform one
                shouldSyncTriggers = false;

                // "--no-zip"
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            if (shouldSyncTriggers)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
                await SyncTriggers(functionApp);
            }

            // Linux Elastic Premium functions take longer to deploy. So do Linux Dedicated Function Apps with remote build
            // Right now, we cannot guarantee that functions info will be most up to date.
            // So, we only show the info, if Function App is not Linux Elastic Premium
            // or a Linux Dedicated Function App with remote build
            if (!(functionApp.IsLinux && functionApp.IsElasticPremium) &&
                !(isFunctionAppDedicatedLinux && PublishBuildOption == BuildOption.Remote))
            {
                await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true);
            }
        }
        public override async Task RunAsync()
        {
            using (var client = await _scriptServer.ConnectAsync(Timeout, NoInteractive))
            {
                var hostStatusResponse = await client.GetAsync("admin/host/status");

                var functionStatusResponse = await client.GetAsync($"admin/functions/{FunctionName}/status");

                if (!hostStatusResponse.IsSuccessStatusCode)
                {
                    ColoredConsole
                    .Error
                    .WriteLine(ErrorColor($"Error calling the functions host: {hostStatusResponse.StatusCode}"));
                    return;
                }
                else if (!functionStatusResponse.IsSuccessStatusCode)
                {
                    ColoredConsole
                    .Error
                    .WriteLine(ErrorColor($"Error calling function {FunctionName}: {functionStatusResponse.StatusCode}"));
                    return;
                }


                var functionMetadata = ScriptHostHelpers.GetFunctionMetadata(FunctionName);
                var hostStatus       = await hostStatusResponse.Content.ReadAsAsync <HostStatus>();

                Func <IEnumerable <string>, string, bool> printError = (errors, title) =>
                {
                    if (errors?.Any() == true)
                    {
                        ColoredConsole
                        .Error
                        .WriteLine(ErrorColor(title));

                        foreach (var error in errors)
                        {
                            ColoredConsole
                            .Error
                            .WriteLine(ErrorColor($"\t{error}"));
                        }
                        return(true);
                    }
                    return(false);
                };

                if (printError(hostStatus.Errors, "The function host has the following errors:") ||
                    printError(hostStatus.Errors, $"Function {FunctionName} has the following errors:"))
                {
                    return;
                }

                if (Debug)
                {
                    var scriptType = functionMetadata.ScriptType;
                    if (scriptType != ScriptType.CSharp && scriptType != ScriptType.Javascript)
                    {
                        ColoredConsole
                        .Error
                        .WriteLine(ErrorColor($"Only C# and Javascript functions are currently supported for debugging."));
                        return;
                    }

                    if (scriptType == ScriptType.CSharp)
                    {
                        ColoredConsole
                        .WriteLine("Debugger launching...")
                        .WriteLine("Setup your break points, and hit continue!");
                        await DebuggerHelper.AttachManagedAsync(client);
                    }
                    else if (scriptType == ScriptType.Javascript)
                    {
                        var nodeDebugger = await DebuggerHelper.TrySetupNodeDebuggerAsync();

                        if (nodeDebugger == NodeDebuggerStatus.Error)
                        {
                            ColoredConsole
                            .Error
                            .WriteLine(ErrorColor("Unable to configure node debugger. Check your launch.json."));
                            return;
                        }
                        else if (!NoInteractive)
                        {
                            ColoredConsole.WriteLine("launch.json configured.");
                        }
                        else
                        {
                            ColoredConsole
                            .Write("launch.json configured. Setup your break points, launch debugger (F5), and press any key to continue...");
                            Console.ReadKey();
                        }
                    }
                }

                var invocation = string.IsNullOrEmpty(FileName)
                    ? Content
                    : await FileSystemHelpers.ReadAllTextFromFileAsync(FileName);

                invocation = invocation ?? string.Empty;

                var adminInvocation = JsonConvert.SerializeObject(new FunctionInvocation {
                    Input = invocation
                });

                if (functionMetadata.IsHttpFunction())
                {
                    ColoredConsole.WriteLine(WarningColor("NOTE: the 'func run' command only supports POST for HTTP triggers. For other verbs, consider a REST client like cURL or Postman."));
                }

                var response = functionMetadata.IsHttpFunction()
                    ? await client.PostAsync($"api/{FunctionName}", new StringContent(invocation, Encoding.UTF8, invocation.IsJson() ? "application/json" : "plain/text"))
                    : await client.PostAsync($"admin/functions/{FunctionName}", new StringContent(adminInvocation, Encoding.UTF8, "application/json"));

                ColoredConsole.WriteLine($"{TitleColor($"Response Status Code:")} {response.StatusCode}");
                var contentTask = response.Content?.ReadAsStringAsync();
                if (contentTask != null)
                {
                    var content = await contentTask;
                    if (!response.IsSuccessStatusCode)
                    {
                        try
                        {
                            var exception = JsonConvert.DeserializeObject <JObject>(content);
                            if (exception?["InnerException"]?["ExceptionMessage"]?.ToString() == "Script compilation failed.")
                            {
                                ColoredConsole.Error.WriteLine(ErrorColor("Script compilation failed."));
                                return;
                            }
                        }
                        catch { }
                    }
                    ColoredConsole.WriteLine(await contentTask);
                }
            }
        }
Beispiel #23
0
        private async Task <Uri> DiscoverServer(int iteration = 0)
        {
            var server = new Uri($"http://localhost:{Port + iteration}");

            if (!await server.IsServerRunningAsync())
            {
                // create the server
                if (_settings.DisplayLaunchingRunServerWarning)
                {
                    ColoredConsole
                    .WriteLine()
                    .WriteLine("We need to launch a server that will host and run your functions.")
                    .WriteLine("The server will auto load any changes you make to the function.");
                    string answer = null;
                    do
                    {
                        ColoredConsole
                        .Write(QuestionColor("Do you want to always display this warning before launching a new server [yes/no]? [yes] "));

                        answer = Console.ReadLine()?.Trim()?.ToLowerInvariant();
                        answer = string.IsNullOrEmpty(answer) ? "yes" : answer;
                    } while (answer != "yes" && answer != "no");
                    _settings.DisplayLaunchingRunServerWarning = answer == "yes" ? true : false;
                }

                //TODO: factor out to PlatformHelper.LaunchInNewConsole and implement for Mac using AppleScript
                var exeName = System.Reflection.Assembly.GetEntryAssembly().Location;
                var exe     = PlatformHelper.IsWindows
                    ? new Executable(exeName, $"host start -p {Port + iteration}", streamOutput: false, shareConsole: true)
                    : new Executable("mono", $"{exeName} host start -p {Port + iteration}", streamOutput: false, shareConsole: false);

                exe.RunAsync().Ignore();
                await Task.Delay(500);

                if (PlatformHelper.IsWindows)
                {
                    ConsoleNativeMethods.GetFocusBack();
                }

                return(server);
            }
            else
            {
                var hostId = await GetHostId(ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory));

                using (var client = new HttpClient())
                {
                    var response = await client.GetAsync(new Uri(server, "admin/host/status"));

                    response.EnsureSuccessStatusCode();

                    var hostStatus = await response.Content.ReadAsAsync <HostStatus>();

                    if (!hostStatus.Id.Equals(hostId, StringComparison.OrdinalIgnoreCase))
                    {
                        return(await DiscoverServer(iteration + 1));
                    }
                    else
                    {
                        return(server);
                    }
                }
            }
        }
Beispiel #24
0
        public override ICommandLineParserResult ParseArgs(string[] args)
        {
            var hostSettings = _secretsManager.GetHostStartSettings();

            Parser
            .Setup <int>('p', "port")
            .WithDescription($"Local port to listen on. Default: {DefaultPort}")
            .SetDefault(hostSettings.LocalHttpPort == default(int) ? DefaultPort : hostSettings.LocalHttpPort)
            .Callback(p => Port = p);

            Parser
            .Setup <string>("cors")
            .WithDescription($"A comma separated list of CORS origins with no spaces. Example: https://functions.azure.com,https://functions-staging.azure.com")
            .SetDefault(hostSettings.Cors ?? string.Empty)
            .Callback(c => CorsOrigins = c);

            Parser
            .Setup <int>('t', "timeout")
            .WithDescription($"Timeout for on the functions host to start in seconds. Default: {DefaultTimeout} seconds.")
            .SetDefault(DefaultTimeout)
            .Callback(t => Timeout = t);

            Parser
            .Setup <bool>("useHttps")
            .WithDescription("Bind to https://localhost:{port} rather than http://localhost:{port}. By default it creates and trusts a certificate.")
            .SetDefault(false)
            .Callback(s => UseHttps = s);

            Parser
            .Setup <string>("cert")
            .WithDescription("for use with --useHttps. The path to a pfx file that contains a private key")
            .Callback(c => CertPath = c);

            Parser
            .Setup <string>("password")
            .WithDescription("to use with --cert. Either the password, or a file that contains the password for the pfx file")
            .Callback(p => CertPassword = p);

            Parser
            .Setup <DebuggerType>("debug")
            .WithDescription("Default is None. Options are VSCode and VS")
            .SetDefault(DebuggerType.None)
            .Callback(d => Debugger = d);

            Parser
            .Setup <string>('w', "workers")
            .WithDescription("Arguments to configure language workers, separated by ','. Example: --workers node:debug=<node-debug-port>,java:path=<path-to-worker-jar>")
            .Callback(w =>
            {
                foreach (var arg in w.Split(','))
                {
                    var pair    = arg.Split('=');
                    var section = pair[0];
                    var value   = pair.Count() == 2 ? pair[1] : string.Empty;
                    IConfigurationArguments[section] = value;
                }
            });

            Parser
            .Setup <string>("script-root")
            .WithDescription($"The path to the root of the function app where the command will be executed.")
            .SetDefault(".")
            .Callback(dir => {
                var fullDirPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, dir));
                ScriptRoot      = ScriptHostHelpers.GetFunctionAppRootDirectory(fullDirPath);
            });

            return(Parser.Parse(args));
        }
Beispiel #25
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            // For dedicated linux apps, we do not support run from package right now
            var isFunctionAppDedicatedLinux = functionApp.IsLinux && !functionApp.IsDynamic && !functionApp.IsElasticPremium;

            // For Python linux apps, we do not support --build remote with --build-native-deps flag
            if (PublishBuildOption == BuildOption.Remote && BuildNativeDeps)
            {
                throw new CliException("Cannot use '--build remote' along with '--build-native-deps'");
            }
            else if (PublishBuildOption == BuildOption.Local ||
                     PublishBuildOption == BuildOption.Container ||
                     PublishBuildOption == BuildOption.None)
            {
                throw new CliException("The --build flag only supports '--build remote'");
            }

            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, PublishBuildOption, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            bool shouldSyncTriggers  = true;
            var  fileNameNoExtension = string.Format("{0}-{1}", DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"), Guid.NewGuid());

            if (functionApp.IsLinux && functionApp.IsDynamic)
            {
                // Consumption Linux
                shouldSyncTriggers = await HandleLinuxConsumptionPublish(functionAppRoot, functionApp, fileNameNoExtension);
            }
            else if (functionApp.IsLinux && functionApp.IsElasticPremium)
            {
                // Elastic Premium Linux
                shouldSyncTriggers = await HandleElasticPremiumLinuxPublish(functionApp, zipStreamFactory, $"{fileNameNoExtension}.zip");
            }
            else if (isFunctionAppDedicatedLinux)
            {
                // Dedicated Linux
                shouldSyncTriggers = false;
                await HandleLinuxDedicatedPublish(zipStreamFactory, functionApp);
            }
            else if (RunFromPackageDeploy)
            {
                // Windows default
                await PublishRunFromPackageLocal(functionApp, zipStreamFactory);
            }
            else
            {
                // ZipDeploy takes care of the SyncTriggers operation so we don't
                // need to perform one
                shouldSyncTriggers = false;

                // "--no-zip"
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            if (shouldSyncTriggers)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
                await SyncTriggers(functionApp);
            }

            // Linux Elastic Premium functions take longer to deploy. So do Linux Dedicated Function Apps with remote build
            // Right now, we cannot guarantee that functions info will be most up to date.
            // So, we only show the info, if Function App is not Linux Elastic Premium
            // or a Linux Dedicated Function App with remote build
            if (!(functionApp.IsLinux && functionApp.IsElasticPremium) &&
                !(isFunctionAppDedicatedLinux && PublishBuildOption == BuildOption.Remote))
            {
                await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true);
            }
        }