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)); } }
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); }
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); }
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); }
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); } }
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); }
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); }
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); }
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); } }
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); }
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); } }
/// <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); }
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 }
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); }
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")); }
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"); } }
public void GitIgnoreParser_NullLine_Test(string inputLine) => Assert.Null(GitIgnoreParser.ParseLine(inputLine));
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); } }
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); } }
public void GitIgnoreParser_Exclusion_Test(string pattern, string relativePath, bool isFile, bool expectMatch) => Assert.Equal(expectMatch, GitIgnoreParser.ParseLine(pattern).IsMatch(relativePath, isFile));
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); } }