Example #1
0
        public static async Task <Stream> GetAppZipFile(string functionAppRoot, bool buildNativeDeps, BuildOption buildOption, bool noBuild, GitIgnoreParser ignoreParser = null, string additionalPackages = null, bool ignoreDotNetCheck = false)
        {
            var gitIgnorePath = Path.Combine(functionAppRoot, Constants.FuncIgnoreFile);

            if (ignoreParser == null && FileSystemHelpers.FileExists(gitIgnorePath))
            {
                ignoreParser = new GitIgnoreParser(await FileSystemHelpers.ReadAllTextFromFileAsync(gitIgnorePath));
            }

            if (noBuild)
            {
                ColoredConsole.WriteLine(Yellow("Skipping build event for functions project (--no-build)."));
            }
            else if (buildOption == BuildOption.Remote)
            {
                ColoredConsole.WriteLine(Yellow("Perform remote build for functions project (--build remote)."));
            }
            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python && !noBuild)
            {
                return(await PythonHelpers.GetPythonDeploymentPackage(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot, buildNativeDeps, buildOption, additionalPackages));
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.dotnet && !ignoreDotNetCheck && !noBuild && buildOption != BuildOption.Remote)
            {
                throw new CliException("Pack command doesn't work for dotnet functions");
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.dotnet && buildOption == BuildOption.Remote)
            {
                // Remote build for dotnet does not require bin and obj folders. They will be generated during the oryx build
                return(CreateZip(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser, false, new string[] { "bin", "obj" }), functionAppRoot));
            }
            else
            {
                return(CreateZip(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser, false), functionAppRoot));
            }
        }
Example #2
0
        public override async Task RunAsync()
        {
            GitIgnoreParser ignoreParser = null;

            try
            {
                var path = Path.Combine(Environment.CurrentDirectory, Constants.FuncIgnoreFile);
                if (FileSystemHelpers.FileExists(path))
                {
                    ignoreParser = new GitIgnoreParser(FileSystemHelpers.ReadAllTextFromFile(path));
                }
            }
            catch { }

            if (ListIncludedFiles)
            {
                InternalListIncludedFiles(ignoreParser);
            }
            else if (ListIgnoredFiles)
            {
                InternalListIgnoredFiles(ignoreParser);
            }
            else
            {
                if (PublishLocalSettingsOnly)
                {
                    await InternalPublishLocalSettingsOnly();
                }
                else
                {
                    await InternalPublishFunctionApp(ignoreParser);
                }
            }
        }
        public static async Task <Stream> GetAppZipFile(WorkerRuntime workerRuntime, string functionAppRoot, bool buildNativeDeps, bool noBuild, GitIgnoreParser ignoreParser = null, string additionalPackages = null, bool ignoreDotNetCheck = false)
        {
            var gitIgnorePath = Path.Combine(functionAppRoot, Constants.FuncIgnoreFile);

            if (ignoreParser == null && FileSystemHelpers.FileExists(gitIgnorePath))
            {
                ignoreParser = new GitIgnoreParser(await FileSystemHelpers.ReadAllTextFromFileAsync(gitIgnorePath));
            }

            if (noBuild)
            {
                ColoredConsole.WriteLine(Yellow("Skipping build event for functions project (--no-build)."));
            }

            if (workerRuntime == WorkerRuntime.python && !noBuild)
            {
                return(await PythonHelpers.GetPythonDeploymentPackage(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot, buildNativeDeps, additionalPackages));
            }
            else if (workerRuntime == WorkerRuntime.dotnet && !ignoreDotNetCheck && !noBuild)
            {
                throw new CliException("Pack command doesn't work for dotnet functions");
            }
            else
            {
                return(CreateZip(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
        }
        private static StreamContent CreateStreamContentZip(string path, GitIgnoreParser ignoreParser)
        {
            var memoryStream = CreateZip(path, ignoreParser);
            var content      = new StreamContent(memoryStream);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            return(content);
        }
Example #5
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);
        }
Example #6
0
        public void GitIgnoreParser_IsIgnored_ReturnsFalseWhenNoGitRepositoryIsFound(string relativePath)
        {
            // Arrange
            gitignore = new GitIgnoreParser();
            var directory = Path.GetTempPath();

            // Act
            gitignore.Directory = directory;
            var isIgnored = gitignore.IsIgnored(relativePath);

            Assert.False(isIgnored);
        }
Example #7
0
        private static void InternalListIgnoredFiles(GitIgnoreParser ignoreParser)
        {
            if (ignoreParser == null)
            {
                ColoredConsole.Error.WriteLine("No .funcignore file");
                return;
            }

            foreach (var file in PackAction.GetLocalFiles(Environment.CurrentDirectory, ignoreParser, returnIgnored: true))
            {
                ColoredConsole.WriteLine(file);
            }
        }
Example #8
0
        private static void InternalListIncludedFiles(GitIgnoreParser ignoreParser)
        {
            if (ignoreParser == null)
            {
                ColoredConsole.Error.WriteLine("No .funcignore file");
                return;
            }

            foreach (var file in FileSystemHelpers.GetLocalFiles(Environment.CurrentDirectory))
            {
                ColoredConsole.WriteLine(file);
            }
        }
        private static void InternalListIncludedFiles(GitIgnoreParser ignoreParser)
        {
            if (ignoreParser == null)
            {
                ColoredConsole.Error.WriteLine("No .funcignore file");
                return;
            }

            foreach (var file in GetFiles(Environment.CurrentDirectory).Select(f => f.Replace(Environment.CurrentDirectory, "").Trim(Path.DirectorySeparatorChar).Replace("\\", "/")))
            {
                if (ignoreParser.Accepts(file))
                {
                    ColoredConsole.WriteLine(file);
                }
            }
        }
        private static Stream CreateZip(string path, GitIgnoreParser ignoreParser)
        {
            var memoryStream = new MemoryStream();

            using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true))
            {
                foreach (var fileName in GetFiles(path))
                {
                    if (ignoreParser?.Accepts(fileName.Replace(path, "").Trim(Path.DirectorySeparatorChar).Replace("\\", "/")) ?? true)
                    {
                        zip.AddFile(fileName, fileName, path);
                    }
                }
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            return(memoryStream);
        }
Example #11
0
        private async Task InternalPublishFunctionApp(GitIgnoreParser ignoreParser)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            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."));
            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, ignoreParser);

                        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);
        }
Example #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);
        }
Example #13
0
        public static async Task <Stream> GetAppZipFile(WorkerRuntime workerRuntime, string functionAppRoot, GitIgnoreParser ignoreParser = null)
        {
            var gitIgnorePath = Path.Combine(functionAppRoot, Constants.FuncIgnoreFile);

            if (ignoreParser == null && FileSystemHelpers.FileExists(gitIgnorePath))
            {
                ignoreParser = new GitIgnoreParser(await FileSystemHelpers.ReadAllTextFromFileAsync(gitIgnorePath));
            }

            if (workerRuntime == WorkerRuntime.python)
            {
                return(await PythonHelpers.GetPythonDeploymentPackage(GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
            else
            {
                return(CreateZip(GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
        }
        public override async Task RunAsync()
        {
            GitIgnoreParser ignoreParser = null;

            try
            {
                var path = Path.Combine(Environment.CurrentDirectory, Constants.FuncIgnoreFile);
                if (FileSystemHelpers.FileExists(path))
                {
                    ignoreParser = new GitIgnoreParser(FileSystemHelpers.ReadAllTextFromFile(path));
                }
            }
            catch { }

            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

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

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

            if (ListIncludedFiles)
            {
                InternalListIncludedFiles(ignoreParser);
            }
            else if (ListIgnoredFiles)
            {
                InternalListIgnoredFiles(ignoreParser);
            }
            else
            {
                if (PublishLocalSettingsOnly)
                {
                    await InternalPublishLocalSettingsOnly();
                }
                else
                {
                    await InternalPublishFunctionApp(ignoreParser);
                }
            }
        }
        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);
            }
        }
Example #16
0
        private static StreamContent CreateZip(string path, GitIgnoreParser ignoreParser)
        {
            var memoryStream = new MemoryStream();

            using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true))
            {
                foreach (var fileName in GetFiles(path))
                {
                    if (ignoreParser?.Accepts(fileName.Replace(path, "").Trim(Path.DirectorySeparatorChar).Replace("\\", "/")) ?? true)
                    {
                        zip.AddFile(fileName, fileName, path);
                    }
                }
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var content = new StreamContent(memoryStream);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            return(content);
        }
Example #17
0
        public static IEnumerable <string> GetLocalFiles(string path, GitIgnoreParser ignoreParser = null, bool returnIgnored = false)
        {
            var ignoredDirectories = new[] { ".git", ".vscode" };
            var ignoredFiles       = new[] { ".funcignore", ".gitignore", "appsettings.json", "local.settings.json", "project.lock.json" };

            foreach (var file in FileSystemHelpers.GetFiles(path, ignoredDirectories, ignoredFiles))
            {
                if (preCondition(file))
                {
                    yield return(file);
                }
            }

            bool preCondition(string file)
            {
                var fileName = file.Replace(path, string.Empty).Trim(Path.DirectorySeparatorChar).Replace("\\", "/");

                return((returnIgnored ? ignoreParser?.Denies(fileName) : ignoreParser?.Accepts(fileName)) ?? true);
            }
        }
        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);
            }
        }
Example #19
0
        /// <summary>
        /// Handler for Linux Consumption publish event
        /// </summary>
        /// <param name="functionAppRoot">Function App project path in local machine</param>
        /// <param name="functionApp">Function App in Azure</param>
        /// <param name="fileNameNoExtension">Name of the file to be uploaded</param>
        /// <returns>ShouldSyncTrigger value</returns>
        private async Task <bool> HandleLinuxConsumptionPublish(string functionAppRoot, Site functionApp, string fileNameNoExtension)
        {
            // Choose if the content need to use remote build
            BuildOption     buildOption  = PublishHelper.UpdateLinuxConsumptionBuildOption(PublishBuildOption);
            GitIgnoreParser ignoreParser = PublishHelper.GetIgnoreParser(functionAppRoot);

            // We update the buildOption, so we need to update the zipFileStream factory as well
            Func <Task <Stream> > zipFileStreamTask = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, buildOption, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            // Consumption Linux, try squashfs as a package format.
            if (GlobalCoreToolsSettings.CurrentWorkerRuntimeOrNone == WorkerRuntime.python && !NoBuild && (BuildNativeDeps || buildOption == BuildOption.Remote))
            {
                if (BuildNativeDeps)
                {
                    await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipFileStreamTask()), $"{fileNameNoExtension}.squashfs");

                    return(true);
                }

                // Remote build don't need sync trigger, container will be deallocated once the build is finished
                if (buildOption == BuildOption.Remote)
                {
                    await RemoveFunctionAppAppSetting(functionApp,
                                                      "WEBSITE_RUN_FROM_PACKAGE",
                                                      "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                                                      "WEBSITE_CONTENTSHARE");
                    Task <DeployStatus> pollConsumptionBuild(HttpClient client) => KuduLiteDeploymentHelpers.WaitForConsumptionServerSideBuild(client, functionApp, AccessToken, ManagementURL);

                    var deployStatus = await PerformServerSideBuild(functionApp, zipFileStreamTask, pollConsumptionBuild);

                    return(deployStatus == DeployStatus.Success);
                }
            }
            else
            {
                await PublishRunFromPackage(functionApp, await zipFileStreamTask(), $"{fileNameNoExtension}.zip");

                return(true);
            }
            return(true);
        }
Example #20
0
        public static async Task <Stream> GetAppZipFile(WorkerRuntime workerRuntime, string functionAppRoot, bool buildNativeDeps, GitIgnoreParser ignoreParser = null)
        {
            var gitIgnorePath = Path.Combine(functionAppRoot, Constants.FuncIgnoreFile);

            if (ignoreParser == null && FileSystemHelpers.FileExists(gitIgnorePath))
            {
                ignoreParser = new GitIgnoreParser(await FileSystemHelpers.ReadAllTextFromFileAsync(gitIgnorePath));
            }

            if (workerRuntime == WorkerRuntime.python)
            {
                return(await PythonHelpers.GetPythonDeploymentPackage(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot, buildNativeDeps));
            }
            else if (workerRuntime == WorkerRuntime.dotnet)
            {
                throw new CliException("Pack command doesn't work for dotnet functions");
            }
            else
            {
                return(CreateZip(FileSystemHelpers.GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
        }
        public async Task PublishZipDeploy(Site functionApp, string functionAppRoot, GitIgnoreParser ignoreParser)
        {
            await RetryHelper.Retry(async() =>
            {
                using (var client = await GetRemoteZipClient(new Uri($"https://{functionApp.ScmUri}")))
                    using (var request = new HttpRequestMessage(HttpMethod.Post, new Uri("api/zipdeploy", UriKind.Relative)))
                    {
                        request.Headers.IfMatch.Add(EntityTagHeaderValue.Any);

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

                        request.Content = CreateStreamContentZip(functionAppRoot, ignoreParser);

                        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);
        }
        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
        }
Example #23
0
        public void GitIgnoreParser_IsIgnored_ReturnsCorrectValueEvenIfGitRootIsInSomeParentDirectory(string path)
        {
            // Arrange
            var gitRoot = InitializeTempGitRepository();
            var full    = Path.Join(gitRoot, path);
            var info    = Directory.CreateDirectory(full);

            using (var writer = File.CreateText(Path.Join(gitRoot, ".gitignore")))
            {
                writer.Write("*.cs\n");
            }

            gitignore = new GitIgnoreParser()
            {
                Directory = full,
            };

            // Act
            var result = gitignore.IsIgnored("some/ignored/file.cs");

            // Assert
            Assert.True(result);
        }
Example #24
0
        public void GitIgnoreParser_IsIgnored_ReturnsTheCorrectValueForIgnoredFiles()
        {
            // Arrange
            var gitRoot = InitializeTempGitRepository();

            using (var writer = File.CreateText(Path.Join(gitRoot, ".gitignore")))
            {
                writer.Write(@"
                    # Advanced patterns
                    [Bb]in/
                    [Bb]uild[Ll]og.*
                    [Ll]og/
                    *.pyc
                    **/Properties/launchSettings.json
                    *.tmp.*.js
                ");
            }

            gitignore = new GitIgnoreParser()
            {
                Directory = gitRoot,
            };

            // Assert
            Assert.True(gitignore.IsIgnored("Bin/somefile.dll"));
            Assert.True(gitignore.IsIgnored("bin/somefile.dll"));
            Assert.True(gitignore.IsIgnored("something/bin/something/test.dll"));
            Assert.True(gitignore.IsIgnored("Buildlog.something.txt"));
            Assert.True(gitignore.IsIgnored("src/docker/watcher.pyc"));
            Assert.True(gitignore.IsIgnored("in/some/nested/folder/Properties/launchSettings.json"));
            Assert.True(gitignore.IsIgnored("test.tmp.backup.js"));

            Assert.False(gitignore.IsIgnored("src/docker/watcher.py"));
            Assert.False(gitignore.IsIgnored("Blog/something/something.c"));
            Assert.False(gitignore.IsIgnored("test/Analog/something.c"));
        }
Example #25
0
        static IEnumerable <IFilePathFilter> ReadGitIgnoreExclusions(string rootDirectoryPath, IRemoteDevLogger logger)
        {
            // Always ignore .git folder
            yield return(new GlobFilePathFilter(".git"));

            yield return(new GlobFilePathFilter(".git/**"));

            // Ignore files from root gitignore
            var gitIgnorePath = Path.Combine(rootDirectoryPath, ".gitignore");

            if (File.Exists(gitIgnorePath))
            {
                logger.Log(LogLevel.INFO, $"Using the gitignore found in {gitIgnorePath}");
                var filterCount = 0;

                using (var fs = File.OpenRead(gitIgnorePath))
                    using (var reader = new StreamReader(fs))
                    {
                        while (!reader.EndOfStream)
                        {
                            var filter = GitIgnoreParser.ParseLine(reader.ReadLine());
                            if (filter != null)
                            {
                                filterCount++;
                                yield return(filter);
                            }
                        }
                    }

                logger.Log(LogLevel.INFO, $"Found {filterCount} blob filters in the gitignore file");
            }
            else
            {
                logger.Log(LogLevel.WARN, "No .gitignore found in root directory. No file/folder changes will be ignored");
            }
        }
Example #26
0
 public void GitIgnoreParser_NullLine_Test(string inputLine)
 => Assert.Null(GitIgnoreParser.ParseLine(inputLine));
Example #27
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);
            }
        }
Example #28
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);
            }
        }
Example #29
0
 public void GitIgnoreParser_Exclusion_Test(string pattern, string relativePath, bool isFile, bool expectMatch)
 => Assert.Equal(expectMatch, GitIgnoreParser.ParseLine(pattern).IsMatch(relativePath, isFile));
Example #30
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);
            }
        }