From 15ac4821f1852ca678bb047f17fbb7d44ef03794 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Tue, 21 May 2019 04:48:42 -0700 Subject: [PATCH] Added support for building ASP.NET Core app using Debug configuration (#153) --- doc/configuration.md | 21 ++++----- .../DotNetCoreBashBuildSnippet.sh.tpl | 2 +- .../DotnetCoreBashBuildSnippetProperties.cs | 2 + .../DotNetCore/DotnetCoreConstants.cs | 2 + .../DotNetCore/DotnetCorePlatform.cs | 18 +++++++- .../DotnetCoreScriptGeneratorOptions.cs | 2 + .../DotnetCoreScriptGeneratorOptionsSetup.cs | 3 +- .../EnvironmentSettingsKeys.cs | 5 +++ .../DotNetCoreEndToEndTests.cs | 45 +++++++++++++++++++ .../NetCoreApp22WebApp.csproj | 3 +- .../DotNetCore/NetCoreApp22WebApp/Startup.cs | 9 +++- 11 files changed, 96 insertions(+), 16 deletions(-) diff --git a/doc/configuration.md b/doc/configuration.md index d4924a3bef..e629b67c43 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -5,16 +5,17 @@ can apply minor adjustments and still utilize the automatic build process. The f > NOTE: In Azure Web Apps, these variables are set as App Settings [App Settings][]. -Setting name | Description | Default | Example ----------------------------------|----------------------------------------------------------------|---------|---------------- -PRE\_BUILD\_SCRIPT\_PATH | repo-relative path to a shell script to be run before build | "" | scripts/prebuild.sh -POST\_BUILD\_SCRIPT\_PATH | repo-relative path to a shell script to be run after build | "" | scripts/postbuild.sh -DISABLE\_COLLECTSTATIC | Disable running `collecstatic` when building Django apps. | `false` | `true`, `false` -PROJECT | repo-relative path to directory with `.csproj` file for build | "" | src/WebApp1/WebApp1.csproj -ENABLE\_MULTIPLATFORM\_BUILD | apply more than one toolset if repo indicates it | `false` | `true`, `false` -DISABLE\_DOTNETCORE\_BUILD | do not apply .NET Core build even if repo indicates it | `false` | `true`, `false` -DISABLE\_PYTHON\_BUILD | do not apply Python build even if repo indicates it | `false` | `true`, `false` -DISABLE\_NODEJS\_BUILD | do not apply Node.js build even if repo indicates it | `false` | `true`, `false` +Setting name | Description | Default | Example +-----------------------------|----------------------------------------------------------------|---------|---------------- +PRE\_BUILD\_COMMAND | Command or a repo-relative path to a shell script to be run before build | "" | `echo foo`, `scripts/prebuild.sh` +POST\_BUILD\_COMMAND | Command or a repo-relative path to a shell script to be run after build | "" | `echo foo`, `scripts/postbuild.sh` +DISABLE\_COLLECTSTATIC | Disable running `collecstatic` when building Django apps. | `false` | `true`, `false` +PROJECT | repo-relative path to directory with `.csproj` file for build | "" | src/WebApp1/WebApp1.csproj +ENABLE\_MULTIPLATFORM\_BUILD | apply more than one toolset if repo indicates it | `false` | `true`, `false` +DISABLE\_DOTNETCORE\_BUILD | do not apply .NET Core build even if repo indicates it | `false` | `true`, `false` +DISABLE\_PYTHON\_BUILD | do not apply Python build even if repo indicates it | `false` | `true`, `false` +DISABLE\_NODEJS\_BUILD | do not apply Node.js build even if repo indicates it | `false` | `true`, `false` +MSBUILD\_CONFIGURATION | Configuration (Debug or Relase) that is used to build a .NET Core project | `Release` | `Debug`, `Release` # Azure App Service configuration diff --git a/src/BuildScriptGenerator/DotNetCore/DotNetCoreBashBuildSnippet.sh.tpl b/src/BuildScriptGenerator/DotNetCore/DotNetCoreBashBuildSnippet.sh.tpl index 60b68b45da..fec56a65da 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotNetCoreBashBuildSnippet.sh.tpl +++ b/src/BuildScriptGenerator/DotNetCore/DotNetCoreBashBuildSnippet.sh.tpl @@ -7,7 +7,7 @@ function publishToDirectory() echo echo "Publishing to directory '$directoryToPublishTo'..." echo - dotnet publish "{{ ProjectFile }}" -c Release -o "$directoryToPublishTo" + dotnet publish "{{ ProjectFile }}" -c {{ Configuration }} -o "$directoryToPublishTo" } TOTAL_EXECUTION_START_TIME=$SECONDS diff --git a/src/BuildScriptGenerator/DotNetCore/DotnetCoreBashBuildSnippetProperties.cs b/src/BuildScriptGenerator/DotNetCore/DotnetCoreBashBuildSnippetProperties.cs index c2571b5e8c..2c2e18a4c5 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotnetCoreBashBuildSnippetProperties.cs +++ b/src/BuildScriptGenerator/DotNetCore/DotnetCoreBashBuildSnippetProperties.cs @@ -29,5 +29,7 @@ public class DotNetCoreBashBuildSnippetProperties public string ManifestFileName { get; set; } public Dictionary BuildProperties { get; set; } + + public string Configuration { get; set; } } } \ No newline at end of file diff --git a/src/BuildScriptGenerator/DotNetCore/DotnetCoreConstants.cs b/src/BuildScriptGenerator/DotNetCore/DotnetCoreConstants.cs index 8842dc29de..d0947fb68f 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotnetCoreConstants.cs +++ b/src/BuildScriptGenerator/DotNetCore/DotnetCoreConstants.cs @@ -31,5 +31,7 @@ public static class DotnetCoreConstants public const string ProjectSdkAttributeValueXPathExpression = "string(/Project/@Sdk)"; public const string ProjectSdkElementNameAttributeValueXPathExpression = "string(/Project/Sdk/@Name)"; public const string TargetFrameworkElementXPathExpression = "/Project/PropertyGroup/TargetFramework"; + + public const string DefaultMSBuildConfiguration = "Release"; } } \ No newline at end of file diff --git a/src/BuildScriptGenerator/DotNetCore/DotnetCorePlatform.cs b/src/BuildScriptGenerator/DotNetCore/DotnetCorePlatform.cs index d41657fdba..b4805d174f 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotnetCorePlatform.cs +++ b/src/BuildScriptGenerator/DotNetCore/DotnetCorePlatform.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.IO; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Microsoft.Oryx.BuildScriptGenerator.DotNetCore { @@ -21,19 +22,22 @@ internal class DotnetCorePlatform : IProgrammingPlatform private readonly IEnvironmentSettingsProvider _environmentSettingsProvider; private readonly ILogger _logger; private readonly DotnetCoreLanguageDetector _detector; + private readonly DotnetCoreScriptGeneratorOptions _options; public DotnetCorePlatform( IDotnetCoreVersionProvider versionProvider, IAspNetCoreWebAppProjectFileProvider aspNetCoreWebAppProjectFileProvider, IEnvironmentSettingsProvider environmentSettingsProvider, ILogger logger, - DotnetCoreLanguageDetector detector) + DotnetCoreLanguageDetector detector, + IOptions options) { _versionProvider = versionProvider; _aspNetCoreWebAppProjectFileProvider = aspNetCoreWebAppProjectFileProvider; _environmentSettingsProvider = environmentSettingsProvider; _logger = logger; _detector = detector; + _options = options.Value; } public string Name => DotnetCoreConstants.LanguageName; @@ -75,6 +79,7 @@ public BuildScriptSnippet GenerateBashBuildScriptSnippet(BuildScriptGeneratorCon PostBuildCommand = postBuildCommand, ManifestFileName = Constants.ManifestFileName, ZipAllOutput = zipAllOutput, + Configuration = GetBuildConfiguration() }; var script = TemplateHelpers.Render( TemplateHelpers.TemplateResource.DotNetCoreSnippet, @@ -143,6 +148,17 @@ public IEnumerable GetDirectoriesToExcludeFromCopyToIntermediateDir( return dirs; } + private string GetBuildConfiguration() + { + var configuration = _options.MSBuildConfiguration; + if (string.IsNullOrEmpty(configuration)) + { + configuration = DotnetCoreConstants.DefaultMSBuildConfiguration; + } + + return configuration; + } + private static bool ShouldZipAllOutput(BuildScriptGeneratorContext context) { return BuildPropertiesHelper.IsTrue( diff --git a/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptions.cs b/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptions.cs index 59f177d446..b3ad8907fd 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptions.cs +++ b/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptions.cs @@ -16,5 +16,7 @@ public class DotnetCoreScriptGeneratorOptions public IList SupportedVersions { get; set; } public string Project { get; set; } + + public string MSBuildConfiguration { get; set; } } } \ No newline at end of file diff --git a/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptionsSetup.cs b/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptionsSetup.cs index b09d475c15..0595ab4b82 100644 --- a/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptionsSetup.cs +++ b/src/BuildScriptGenerator/DotNetCore/DotnetCoreScriptGeneratorOptionsSetup.cs @@ -3,7 +3,6 @@ // Licensed under the MIT license. // -------------------------------------------------------------------------------------------- -using System.IO; using Microsoft.Extensions.Options; namespace Microsoft.Oryx.BuildScriptGenerator.DotNetCore @@ -33,6 +32,8 @@ public void Configure(DotnetCoreScriptGeneratorOptions options) options.SupportedVersions = _environment.GetEnvironmentVariableAsList( EnvironmentSettingsKeys.DotnetCoreSupportedVersions); options.Project = _environment.GetEnvironmentVariable(EnvironmentSettingsKeys.Project); + options.MSBuildConfiguration = _environment.GetEnvironmentVariable( + EnvironmentSettingsKeys.MSBuildConfiguration); } } } \ No newline at end of file diff --git a/src/BuildScriptGenerator/EnvironmentSettingsKeys.cs b/src/BuildScriptGenerator/EnvironmentSettingsKeys.cs index 5790d7d7cd..19ec9de38c 100644 --- a/src/BuildScriptGenerator/EnvironmentSettingsKeys.cs +++ b/src/BuildScriptGenerator/EnvironmentSettingsKeys.cs @@ -29,5 +29,10 @@ public static class EnvironmentSettingsKeys public const string Project = "PROJECT"; public const string DisableCollectStatic = "DISABLE_COLLECTSTATIC"; + + /// + /// Represents the 'Configuration' switch of a build, for example: dotnet build --configuration Release + /// + public const string MSBuildConfiguration = "MSBUILD_CONFIGURATION"; } } diff --git a/tests/Oryx.Integration.Tests/DotNetCoreEndToEndTests.cs b/tests/Oryx.Integration.Tests/DotNetCoreEndToEndTests.cs index 6c247f29a6..f7468d3dd1 100644 --- a/tests/Oryx.Integration.Tests/DotNetCoreEndToEndTests.cs +++ b/tests/Oryx.Integration.Tests/DotNetCoreEndToEndTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.Oryx.BuildScriptGenerator; using Microsoft.Oryx.BuildScriptGenerator.DotNetCore; using Microsoft.Oryx.Tests.Common; using Xunit; @@ -440,6 +441,50 @@ await EndToEndTestHelper.BuildRunAndAssertAppAsync( }); } + [Fact] + public async Task CanBuildAndRun_NetCore22WebApp_UsingDebugConfiguration() + { + // Arrange + var dotnetcoreVersion = "2.2"; + var hostDir = Path.Combine(_hostSamplesDir, "DotNetCore", NetCoreApp22WebApp); + var volume = DockerVolume.Create(hostDir); + var appDir = volume.ContainerDir; + var appOutputDir = $"{appDir}/myoutputdir"; + var buildImageScript = new ShellScriptBuilder() + .SetEnvironmentVariable(EnvironmentSettingsKeys.MSBuildConfiguration, "Debug") + .AddCommand($"oryx build {appDir} -l dotnet --language-version {dotnetcoreVersion} -o {appOutputDir}") + .ToString(); + var runtimeImageScript = new ShellScriptBuilder() + .AddCommand( + $"oryx -appPath {appOutputDir} -bindPort {ContainerPort}") + .AddCommand(DefaultStartupFilePath) + .ToString(); + + await EndToEndTestHelper.BuildRunAndAssertAppAsync( + NetCoreApp22WebApp, + _output, + volume, + "/bin/sh", + new[] + { + "-c", + buildImageScript + }, + $"oryxdevms/dotnetcore-{dotnetcoreVersion}", + ContainerPort, + "/bin/sh", + new[] + { + "-c", + runtimeImageScript + }, + async (hostPort) => + { + var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/"); + Assert.Contains("Hello World! from Debug build.", data); + }); + } + [Fact] public async Task CanBuildAndRun_NetCore22WebApp_WithStartupFileName_HavingWhitespace() { diff --git a/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/NetCoreApp22WebApp.csproj b/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/NetCoreApp22WebApp.csproj index 749a688676..b90dbf30b0 100644 --- a/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/NetCoreApp22WebApp.csproj +++ b/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/NetCoreApp22WebApp.csproj @@ -1,5 +1,4 @@ - - + netcoreapp2.2 InProcess diff --git a/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/Startup.cs b/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/Startup.cs index 7e9acfcb49..70f27bcca9 100644 --- a/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/Startup.cs +++ b/tests/SampleApps/DotNetCore/NetCoreApp22WebApp/Startup.cs @@ -27,7 +27,14 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) app.Run(async (context) => { - await context.Response.WriteAsync("Hello World!"); + var responseContent = "Hello World!"; + +// For verifying scenarios where we want to make sure this app is being using Debug configuration. +#if DEBUG + responseContent += " from Debug build."; +#endif + + await context.Response.WriteAsync(responseContent); }); } }