diff --git a/build/repo.targets b/build/repo.targets
index 85ba1a8fe5..aa8ed89a8d 100644
--- a/build/repo.targets
+++ b/build/repo.targets
@@ -11,6 +11,7 @@
+
diff --git a/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/Microsoft.AspNetCore.AzureAppServices.TestBundle.csproj b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/Microsoft.AspNetCore.AzureAppServices.TestBundle.csproj
index 8dfc194aea..8d8949b8bf 100644
--- a/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/Microsoft.AspNetCore.AzureAppServices.TestBundle.csproj
+++ b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/Microsoft.AspNetCore.AzureAppServices.TestBundle.csproj
@@ -22,6 +22,7 @@
+
diff --git a/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/dotnet.cmd b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/dotnet.cmd
new file mode 100644
index 0000000000..b1f5d0c075
--- /dev/null
+++ b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/dotnet.cmd
@@ -0,0 +1 @@
+D:\home\SiteExtensions\AspNetCoreTestBundle\dotnet.exe %*
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/install.cmd b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/install.cmd
index ee3f1ff9cf..bac2756d10 100644
--- a/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/install.cmd
+++ b/src/Microsoft.AspNetCore.AzureAppServices.TestBundle/install.cmd
@@ -10,5 +10,7 @@ robocopy "%DOTNET%" "." /E /XC /XN /XO /NFL /NDL ^
/XD "%RUNTIMES%\2.0.0-preview1-002111-00" ^
/XD "%RUNTIMES%\2.0.0-preview2-25407-01"
+copy /y dotnet.cmd D:\home\site\deployments\tools
+
if %errorlevel% geq 8 exit /b 1
exit /b 0
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Templates/AppServicesWithSiteExtensions.json b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/AppServicesWithSiteExtensions.json
similarity index 100%
rename from test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Templates/AppServicesWithSiteExtensions.json
rename to test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/AppServicesWithSiteExtensions.json
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.0.5.txt b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.0.5.txt
new file mode 100644
index 0000000000..8da4b73745
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.0.5.txt
@@ -0,0 +1,155 @@
+Microsoft.AspNetCore.Antiforgery
+Microsoft.AspNetCore.Authentication
+Microsoft.AspNetCore.Authentication.Cookies
+Microsoft.AspNetCore.Authentication.Facebook
+Microsoft.AspNetCore.Authentication.Google
+Microsoft.AspNetCore.Authentication.JwtBearer
+Microsoft.AspNetCore.Authentication.MicrosoftAccount
+Microsoft.AspNetCore.Authentication.OAuth
+Microsoft.AspNetCore.Authentication.OpenIdConnect
+Microsoft.AspNetCore.Authentication.Twitter
+Microsoft.AspNetCore.Authorization
+microsoft.aspnetcore.azureappservicesintegration
+Microsoft.AspNetCore.Buffering
+Microsoft.AspNetCore.CookiePolicy
+Microsoft.AspNetCore.Cors
+Microsoft.AspNetCore.Cryptography.Internal
+Microsoft.AspNetCore.Cryptography.KeyDerivation
+Microsoft.AspNetCore.DataProtection
+Microsoft.AspNetCore.DataProtection.Abstractions
+microsoft.aspnetcore.dataprotection.azurestorage
+Microsoft.AspNetCore.DataProtection.Extensions
+microsoft.aspnetcore.dataprotection.redis
+Microsoft.AspNetCore.Diagnostics
+Microsoft.AspNetCore.Diagnostics.Abstractions
+Microsoft.AspNetCore.Diagnostics.Elm
+Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+Microsoft.AspNetCore.Hosting
+Microsoft.AspNetCore.Hosting.Abstractions
+Microsoft.AspNetCore.Hosting.Server.Abstractions
+Microsoft.AspNetCore.Html.Abstractions
+Microsoft.AspNetCore.Http
+Microsoft.AspNetCore.Http.Abstractions
+Microsoft.AspNetCore.Http.Extensions
+Microsoft.AspNetCore.Http.Features
+Microsoft.AspNetCore.HttpOverrides
+Microsoft.AspNetCore.Identity
+Microsoft.AspNetCore.Identity.EntityFrameworkCore
+Microsoft.AspNetCore.JsonPatch
+Microsoft.AspNetCore.Localization
+microsoft.aspnetcore.localization.routing
+Microsoft.AspNetCore.MiddlewareAnalysis
+Microsoft.AspNetCore.Mvc
+Microsoft.AspNetCore.Mvc.Abstractions
+Microsoft.AspNetCore.Mvc.ApiExplorer
+Microsoft.AspNetCore.Mvc.Core
+Microsoft.AspNetCore.Mvc.Cors
+Microsoft.AspNetCore.Mvc.DataAnnotations
+Microsoft.AspNetCore.Mvc.Formatters.Json
+Microsoft.AspNetCore.Mvc.Formatters.Xml
+Microsoft.AspNetCore.Mvc.Localization
+Microsoft.AspNetCore.Mvc.Razor
+Microsoft.AspNetCore.Mvc.Razor.Host
+Microsoft.AspNetCore.Mvc.TagHelpers
+Microsoft.AspNetCore.Mvc.ViewFeatures
+Microsoft.AspNetCore.Mvc.WebApiCompatShim
+Microsoft.AspNetCore.Owin
+Microsoft.AspNetCore.Proxy
+Microsoft.AspNetCore.Razor
+Microsoft.AspNetCore.Razor.Runtime
+microsoft.aspnetcore.responsecaching
+microsoft.aspnetcore.responsecaching.abstractions
+microsoft.aspnetcore.responsecompression
+microsoft.aspnetcore.rewrite
+Microsoft.AspNetCore.Routing
+Microsoft.AspNetCore.Routing.Abstractions
+Microsoft.AspNetCore.Server.IISIntegration
+Microsoft.AspNetCore.Server.Kestrel
+Microsoft.AspNetCore.Server.Kestrel.Https
+Microsoft.AspNetCore.Server.WebListener
+Microsoft.AspNetCore.Session
+Microsoft.AspNetCore.StaticFiles
+microsoft.aspnetcore.websockets
+Microsoft.AspNetCore.WebSockets.Protocol
+Microsoft.AspNetCore.WebSockets.Server
+Microsoft.AspNetCore.WebUtilities
+Microsoft.Data.Sqlite
+microsoft.dotnet.internalabstractions
+Microsoft.EntityFrameworkCore
+Microsoft.EntityFrameworkCore.InMemory
+Microsoft.EntityFrameworkCore.Relational
+Microsoft.EntityFrameworkCore.Relational.Design
+Microsoft.EntityFrameworkCore.Relational.Design.Specification.Tests
+Microsoft.EntityFrameworkCore.Relational.Specification.Tests
+Microsoft.EntityFrameworkCore.Specification.Tests
+Microsoft.EntityFrameworkCore.Sqlite
+Microsoft.EntityFrameworkCore.Sqlite.Design
+Microsoft.EntityFrameworkCore.SqlServer
+Microsoft.EntityFrameworkCore.SqlServer.Design
+Microsoft.Extensions.Caching.Abstractions
+Microsoft.Extensions.Caching.Memory
+Microsoft.Extensions.Caching.SqlServer
+Microsoft.Extensions.Configuration
+Microsoft.Extensions.Configuration.Abstractions
+microsoft.extensions.configuration.azurekeyvault
+Microsoft.Extensions.Configuration.Binder
+Microsoft.Extensions.Configuration.CommandLine
+Microsoft.Extensions.Configuration.EnvironmentVariables
+Microsoft.Extensions.Configuration.FileExtensions
+Microsoft.Extensions.Configuration.Ini
+Microsoft.Extensions.Configuration.Json
+Microsoft.Extensions.Configuration.UserSecrets
+Microsoft.Extensions.Configuration.Xml
+Microsoft.Extensions.DependencyInjection
+Microsoft.Extensions.DependencyInjection.Abstractions
+microsoft.extensions.dependencymodel
+Microsoft.Extensions.DiagnosticAdapter
+Microsoft.Extensions.FileProviders.Abstractions
+Microsoft.Extensions.FileProviders.Composite
+Microsoft.Extensions.FileProviders.Embedded
+Microsoft.Extensions.FileProviders.Physical
+Microsoft.Extensions.FileSystemGlobbing
+Microsoft.Extensions.Globalization.CultureInfoCache
+Microsoft.Extensions.Localization
+Microsoft.Extensions.Localization.Abstractions
+Microsoft.Extensions.Logging
+Microsoft.Extensions.Logging.Abstractions
+microsoft.extensions.logging.azureappservices
+Microsoft.Extensions.Logging.Console
+Microsoft.Extensions.Logging.Debug
+microsoft.extensions.logging.eventsource
+Microsoft.Extensions.Logging.Filter
+Microsoft.Extensions.Logging.TraceSource
+Microsoft.Extensions.ObjectPool
+Microsoft.Extensions.Options
+Microsoft.Extensions.Options.ConfigurationExtensions
+// Microsoft.Extensions.PlatformAbstractions - sha mismatch
+Microsoft.Extensions.Primitives
+Microsoft.Extensions.WebEncoders
+microsoft.identitymodel.logging
+microsoft.identitymodel.protocols
+microsoft.identitymodel.protocols.openidconnect
+microsoft.identitymodel.tokens
+microsoft.net.http
+Microsoft.Net.Http.Headers
+Microsoft.Net.Http.Server
+Microsoft.Net.WebSockets.Servern
+newtonsoft.json
+remotion.linq
+system.collections.nongeneric
+system.collections.specialized
+system.componentmodel.primitives
+system.componentmodel.typeconverter
+system.data.common
+system.data.sqlclient
+system.diagnostics.contracts
+system.diagnostics.tracesource
+system.identitymodel.tokens.jwt
+system.interactive.async
+system.io.pipes
+system.net.websockets
+system.private.datacontractserialization
+system.runtime.serialization.primitives
+system.runtime.serialization.xml
+//system.text.encodings.web - sha mismatch
+system.xml.xmlserializer
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.1.2.txt b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.1.2.txt
new file mode 100644
index 0000000000..caff5f16b5
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/DotNetCache.1.1.2.txt
@@ -0,0 +1,155 @@
+Microsoft.AspNetCore.Antiforgery
+Microsoft.AspNetCore.Authentication
+Microsoft.AspNetCore.Authentication.Cookies
+Microsoft.AspNetCore.Authentication.Facebook
+Microsoft.AspNetCore.Authentication.Google
+Microsoft.AspNetCore.Authentication.JwtBearer
+Microsoft.AspNetCore.Authentication.MicrosoftAccount
+Microsoft.AspNetCore.Authentication.OAuth
+Microsoft.AspNetCore.Authentication.OpenIdConnect
+Microsoft.AspNetCore.Authentication.Twitter
+Microsoft.AspNetCore.Authorization
+microsoft.aspnetcore.azureappservicesintegration
+Microsoft.AspNetCore.Buffering
+Microsoft.AspNetCore.CookiePolicy
+Microsoft.AspNetCore.Cors
+Microsoft.AspNetCore.Cryptography.Internal
+Microsoft.AspNetCore.Cryptography.KeyDerivation
+Microsoft.AspNetCore.DataProtection
+Microsoft.AspNetCore.DataProtection.Abstractions
+microsoft.aspnetcore.dataprotection.azurestorage
+Microsoft.AspNetCore.DataProtection.Extensions
+microsoft.aspnetcore.dataprotection.redis
+Microsoft.AspNetCore.Diagnostics
+Microsoft.AspNetCore.Diagnostics.Abstractions
+Microsoft.AspNetCore.Diagnostics.Elm
+Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+Microsoft.AspNetCore.Hosting
+Microsoft.AspNetCore.Hosting.Abstractions
+Microsoft.AspNetCore.Hosting.Server.Abstractions
+Microsoft.AspNetCore.Html.Abstractions
+Microsoft.AspNetCore.Http
+Microsoft.AspNetCore.Http.Abstractions
+Microsoft.AspNetCore.Http.Extensions
+Microsoft.AspNetCore.Http.Features
+Microsoft.AspNetCore.HttpOverrides
+Microsoft.AspNetCore.Identity
+Microsoft.AspNetCore.Identity.EntityFrameworkCore
+Microsoft.AspNetCore.JsonPatch
+Microsoft.AspNetCore.Localization
+microsoft.aspnetcore.localization.routing
+Microsoft.AspNetCore.MiddlewareAnalysis
+Microsoft.AspNetCore.Mvc
+Microsoft.AspNetCore.Mvc.Abstractions
+Microsoft.AspNetCore.Mvc.ApiExplorer
+Microsoft.AspNetCore.Mvc.Core
+Microsoft.AspNetCore.Mvc.Cors
+Microsoft.AspNetCore.Mvc.DataAnnotations
+Microsoft.AspNetCore.Mvc.Formatters.Json
+Microsoft.AspNetCore.Mvc.Formatters.Xml
+Microsoft.AspNetCore.Mvc.Localization
+Microsoft.AspNetCore.Mvc.Razor
+Microsoft.AspNetCore.Mvc.Razor.Host
+Microsoft.AspNetCore.Mvc.TagHelpers
+Microsoft.AspNetCore.Mvc.ViewFeatures
+Microsoft.AspNetCore.Mvc.WebApiCompatShim
+Microsoft.AspNetCore.Owin
+Microsoft.AspNetCore.Proxy
+Microsoft.AspNetCore.Razor
+Microsoft.AspNetCore.Razor.Runtime
+microsoft.aspnetcore.responsecaching
+microsoft.aspnetcore.responsecaching.abstractions
+microsoft.aspnetcore.responsecompression
+microsoft.aspnetcore.rewrite
+Microsoft.AspNetCore.Routing
+Microsoft.AspNetCore.Routing.Abstractions
+Microsoft.AspNetCore.Server.IISIntegration
+Microsoft.AspNetCore.Server.Kestrel
+Microsoft.AspNetCore.Server.Kestrel.Https
+Microsoft.AspNetCore.Server.WebListener
+Microsoft.AspNetCore.Session
+Microsoft.AspNetCore.StaticFiles
+microsoft.aspnetcore.websockets
+Microsoft.AspNetCore.WebSockets.Protocol
+Microsoft.AspNetCore.WebSockets.Server
+Microsoft.AspNetCore.WebUtilities
+Microsoft.Data.Sqlite
+microsoft.dotnet.internalabstractions
+Microsoft.EntityFrameworkCore
+Microsoft.EntityFrameworkCore.InMemory
+Microsoft.EntityFrameworkCore.Relational
+Microsoft.EntityFrameworkCore.Relational.Design
+Microsoft.EntityFrameworkCore.Relational.Design.Specification.Tests
+Microsoft.EntityFrameworkCore.Relational.Specification.Tests
+Microsoft.EntityFrameworkCore.Specification.Tests
+Microsoft.EntityFrameworkCore.Sqlite
+Microsoft.EntityFrameworkCore.Sqlite.Design
+Microsoft.EntityFrameworkCore.SqlServer
+Microsoft.EntityFrameworkCore.SqlServer.Design
+Microsoft.Extensions.Caching.Abstractions
+Microsoft.Extensions.Caching.Memory
+Microsoft.Extensions.Caching.SqlServer
+Microsoft.Extensions.Configuration
+Microsoft.Extensions.Configuration.Abstractions
+microsoft.extensions.configuration.azurekeyvault
+Microsoft.Extensions.Configuration.Binder
+Microsoft.Extensions.Configuration.CommandLine
+Microsoft.Extensions.Configuration.EnvironmentVariables
+Microsoft.Extensions.Configuration.FileExtensions
+Microsoft.Extensions.Configuration.Ini
+Microsoft.Extensions.Configuration.Json
+Microsoft.Extensions.Configuration.UserSecrets
+Microsoft.Extensions.Configuration.Xml
+Microsoft.Extensions.DependencyInjection
+Microsoft.Extensions.DependencyInjection.Abstractions
+//microsoft.extensions.dependencymodel - sha mismatch
+Microsoft.Extensions.DiagnosticAdapter
+Microsoft.Extensions.FileProviders.Abstractions
+Microsoft.Extensions.FileProviders.Composite
+Microsoft.Extensions.FileProviders.Embedded
+Microsoft.Extensions.FileProviders.Physical
+Microsoft.Extensions.FileSystemGlobbing
+Microsoft.Extensions.Globalization.CultureInfoCache
+Microsoft.Extensions.Localization
+Microsoft.Extensions.Localization.Abstractions
+Microsoft.Extensions.Logging
+Microsoft.Extensions.Logging.Abstractions
+microsoft.extensions.logging.azureappservices
+Microsoft.Extensions.Logging.Console
+Microsoft.Extensions.Logging.Debug
+microsoft.extensions.logging.eventsource
+Microsoft.Extensions.Logging.Filter
+Microsoft.Extensions.Logging.TraceSource
+Microsoft.Extensions.ObjectPool
+Microsoft.Extensions.Options
+Microsoft.Extensions.Options.ConfigurationExtensions
+Microsoft.Extensions.PlatformAbstractions
+Microsoft.Extensions.Primitives
+Microsoft.Extensions.WebEncoders
+microsoft.identitymodel.logging
+microsoft.identitymodel.protocols
+microsoft.identitymodel.protocols.openidconnect
+microsoft.identitymodel.tokens
+microsoft.net.http
+Microsoft.Net.Http.Headers
+Microsoft.Net.Http.Server
+Microsoft.Net.WebSockets.Servern
+newtonsoft.json
+remotion.linq
+// system.collections.nongeneric - sha mismatch
+// system.collections.specialized - sha mismatch
+// system.componentmodel.primitives - sha mismatch
+// system.componentmodel.typeconverter - sha mismatch
+system.data.common
+system.data.sqlclient
+system.diagnostics.contracts
+system.diagnostics.tracesource
+system.identitymodel.tokens.jwt
+system.interactive.async
+system.io.pipes
+system.net.websockets
+system.private.datacontractserialization
+// system.runtime.serialization.primitives - sha mismatch
+system.runtime.serialization.xml
+//system.text.encodings.web - sha mismatch
+system.xml.xmlserializer
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.mvc.csproj b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.mvc.csproj
new file mode 100644
index 0000000000..bbad0448ac
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.mvc.csproj
@@ -0,0 +1,19 @@
+
+
+ Exe
+ netcoreapp1.0
+ true
+
+
+
+ $(PackageTargetFallback);portable-net45+win8+wp8+wpa81;
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.web.csproj b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.web.csproj
new file mode 100644
index 0000000000..9920de4da0
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.0.5.web.csproj
@@ -0,0 +1,15 @@
+
+
+ Exe
+ netcoreapp1.0
+ true
+
+
+
+ $(PackageTargetFallback);portable-net45+win8+wp8+wpa81;
+
+
+
+
+
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.mvc.csproj b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.mvc.csproj
new file mode 100644
index 0000000000..0d78be3aed
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.mvc.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netcoreapp1.1
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.web.csproj b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.web.csproj
new file mode 100644
index 0000000000..d30aff10a1
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/Legacy.1.1.2.web.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netcoreapp1.1
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/NuGet.latest.config b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/NuGet.latest.config
new file mode 100644
index 0000000000..4a06556f1c
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/NuGet.latest.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Templates/RuntimeInformationMiddleware.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/RuntimeInformationMiddleware.cs
similarity index 95%
rename from test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Templates/RuntimeInformationMiddleware.cs
rename to test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/RuntimeInformationMiddleware.cs
index 2850f0a77f..1aa6ad74e7 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Templates/RuntimeInformationMiddleware.cs
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Assets/RuntimeInformationMiddleware.cs
@@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
Assembly assembly = null;
try
{
- assembly = Assembly.Load(Path.GetFileNameWithoutExtension(m.ModuleName));
+ assembly = Assembly.Load(new AssemblyName(Path.GetFileNameWithoutExtension(m.ModuleName)));
}
catch { }
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/AzureFixture.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/AzureFixture.cs
index 007ebd8daf..c8f5954212 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/AzureFixture.cs
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/AzureFixture.cs
@@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
Plan = Azure.AppServices.AppServicePlans.Define(servicePlanName)
.WithRegion(Region.USWest2)
.WithExistingResourceGroup(ResourceGroup)
- .WithPricingTier(PricingTier.BasicB1)
+ .WithPricingTier(PricingTier.StandardS1)
.WithOperatingSystem(OperatingSystem.Windows)
.Create();
}
@@ -98,7 +98,50 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
return name + Timestamp;
}
+ private Dictionary>> _deploymentCache = new Dictionary>>();
+ private int _predeploymentId;
+
public async Task Deploy(string template, IDictionary additionalArguments = null, [CallerMemberName] string baseName = null)
+ {
+ List> deployments;
+
+ void DeployBatch()
+ {
+ var maxId = _predeploymentId + 5;
+ for (; _predeploymentId < maxId; _predeploymentId++)
+ {
+ deployments.Add(DeployImpl(template, additionalArguments, "PreDeploy" + _predeploymentId));
+ }
+ }
+
+ var deploymentKeyParts = new List();
+ deploymentKeyParts.Add(template);
+ if (additionalArguments != null)
+ {
+ deploymentKeyParts.AddRange(additionalArguments.Select(a => a.Key + "=" + a.Value));
+ }
+ var deploymentKey = string.Join(Environment.NewLine, deploymentKeyParts);
+
+ Task deployment;
+ if (!_deploymentCache.TryGetValue(deploymentKey, out deployments))
+ {
+ deployments = new List>();
+ DeployBatch();
+ _deploymentCache[deploymentKey] = deployments;
+ }
+
+ deployment = await Task.WhenAny(deployments);
+ deployments.Remove(deployment);
+
+ if (deployments.Count == 2)
+ {
+ DeployBatch();
+ }
+
+ return await deployment;
+ }
+
+ private async Task DeployImpl(string template, IDictionary additionalArguments = null, [CallerMemberName] string baseName = null)
{
var siteName = GetTimestampedName(baseName);
var parameters = new Dictionary
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Microsoft.AspNetCore.AzureAppServices.FunctionalTests.csproj b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Microsoft.AspNetCore.AzureAppServices.FunctionalTests.csproj
index 1ae218e17d..b5ffd418c4 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Microsoft.AspNetCore.AzureAppServices.FunctionalTests.csproj
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/Microsoft.AspNetCore.AzureAppServices.FunctionalTests.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/PathUtilities.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/PathUtilities.cs
index e685152da4..f43ee9163a 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/PathUtilities.cs
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/PathUtilities.cs
@@ -21,19 +21,17 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
.ToArray();
}
- public static string[] GetSharedRuntimeAssemblies(string dotnetPath, out string runtimeVersion)
+ public static string[] GetLatestSharedRuntimeAssemblies(string dotnetPath, out string runtimeVersion)
{
var dotnetHome = Path.GetDirectoryName(dotnetPath);
var runtimeDirectory = new DirectoryInfo(Path.Combine(dotnetHome, "shared", "Microsoft.NETCore.App"))
.GetDirectories()
- .Single();
+ .OrderByDescending(d => d.Name)
+ .First();
runtimeVersion = runtimeDirectory.Name;
- return runtimeDirectory
- .GetFiles("*.dll")
- .Select(GetName)
- .ToArray();
+ return GetAllModules(runtimeDirectory);
}
public static string GetBundledAspNetCoreVersion(string dotnetPath)
@@ -52,5 +50,13 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
public string Name { get; set; }
public string[] Versions { get; set; }
}
+
+ public static string[] GetAllModules(DirectoryInfo publishPath)
+ {
+ return publishPath
+ .GetFiles("*.dll")
+ .Select(GetName)
+ .ToArray();
+ }
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/TemplateFunctionalTests.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/TemplateFunctionalTests.cs
index d3dfa3a0fe..66a29bb27c 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/TemplateFunctionalTests.cs
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/TemplateFunctionalTests.cs
@@ -19,9 +19,11 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
[Collection("Azure")]
public class TemplateFunctionalTests
{
- private const string RuntimeInformationMiddlewareType = "Microsoft.AspNetCore.AzureAppServices.FunctionalTests.RuntimeInformationMiddleware";
+ private static readonly string RuntimeInformationMiddlewareType = "Microsoft.AspNetCore.AzureAppServices.FunctionalTests.RuntimeInformationMiddleware";
- private const string RuntimeInformationMiddlewareFile = "Templates\\RuntimeInformationMiddleware.cs";
+ private static readonly string RuntimeInformationMiddlewareFile = Asset("RuntimeInformationMiddleware.cs");
+
+ private static readonly string AppServicesWithSiteExtensionsTemplate = Asset("AppServicesWithSiteExtensions.json");
readonly AzureFixture _fixture;
@@ -34,39 +36,34 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
}
[Theory]
- [InlineData("2.0", "web", "Hello World!")]
- [InlineData("2.0", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
- [InlineData("2.0", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
- [InlineData("latest", "web", "Hello World!")]
- [InlineData("latest", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
- [InlineData("latest", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
- public async Task TemplateRuns(string dotnetVersion, string template, string expected)
+ [InlineData(WebAppDeploymentKind.Git, "1.0.5", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Git, "1.0.5", "mvc", "Learn how to build ASP.NET apps that can run anywhere")]
+ [InlineData(WebAppDeploymentKind.Git, "1.1.2", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Git, "1.1.2", "mvc", "Learn how to build ASP.NET apps that can run anywhere")]
+ [InlineData(WebAppDeploymentKind.Ftp, "1.0.5", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Ftp, "1.0.5", "mvc", "Learn how to build ASP.NET apps that can run anywhere")]
+ [InlineData(WebAppDeploymentKind.Ftp, "1.1.2", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Ftp, "1.1.2", "mvc", "Learn how to build ASP.NET apps that can run anywhere")]
+ public async Task LegacyTemplateRuns(WebAppDeploymentKind deploymentKind, string expectedRuntime, string template, string expected)
{
- var testId = nameof(TemplateRuns) + template + dotnetVersion.Replace(".", string.Empty);
+ var testId = ToFriendlyName(nameof(LegacyTemplateRuns), deploymentKind, template, expectedRuntime);
using (var logger = GetLogger(testId))
{
- var site = await _fixture.Deploy("Templates\\AppServicesWithSiteExtensions.json",
- baseName: testId,
- additionalArguments: new Dictionary
- {
- { "extensionFeed", AzureFixture.GetRequiredEnvironmentVariable("SiteExtensionFeed") },
- { "extensionName", "AspNetCoreTestBundle" },
- { "extensionVersion", GetAssemblyInformationalVersion() },
- });
+ var siteTask = _fixture.Deploy(AppServicesWithSiteExtensionsTemplate, GetSiteExtensionArguments(), testId);
var testDirectory = GetTestDirectory(testId);
- var dotnet = DotNet(logger, testDirectory, dotnetVersion);
- await dotnet.ExecuteAndAssertAsync("new " + template);
+ var dotnet = DotNet(logger, testDirectory, "1.1");
+
+ await dotnet.ExecuteAndAssertAsync($"new {template}");
+
+ UpdateCSProj(testDirectory, Asset($"Legacy.{expectedRuntime}.{template}.csproj"));
InjectMiddlware(testDirectory, RuntimeInformationMiddlewareType, RuntimeInformationMiddlewareFile);
- FixAspNetCoreVersion(testDirectory, dotnet.Command);
-
- await site.BuildPublishProfileAsync(testDirectory.FullName);
-
- await dotnet.ExecuteAndAssertAsync("publish /p:PublishProfile=Profile");
+ var site = await siteTask;
+ await site.Deploy(deploymentKind, testDirectory, dotnet, logger);
using (var httpClient = site.CreateClient())
{
@@ -78,18 +75,115 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
getResult.EnsureSuccessStatusCode();
var runtimeInfo = JsonConvert.DeserializeObject(await getResult.Content.ReadAsStringAsync());
- ValidateRuntimeInfo(runtimeInfo, dotnet.Command);
+ ValidateLegacyRuntimeInfo(runtimeInfo, expectedRuntime, dotnet.Command);
}
}
}
- private void ValidateRuntimeInfo(RuntimeInfo runtimeInfo, string dotnetPath)
+ private void ValidateLegacyRuntimeInfo(RuntimeInfo runtimeInfo, string expectedRuntime, string dotnetPath)
{
- var storeModules = PathUtilities.GetStoreModules(dotnetPath);
- var runtimeModules = PathUtilities.GetSharedRuntimeAssemblies(dotnetPath, out var runtimeVersion);
+ var cacheAssemblies = new HashSet(File.ReadAllLines(Asset($"DotNetCache.{expectedRuntime}.txt")), StringComparer.InvariantCultureIgnoreCase);
+ var runtimeModules = PathUtilities.GetLatestSharedRuntimeAssemblies(dotnetPath, out _);
+ var modulesNotInCache = new List();
foreach (var runtimeInfoModule in runtimeInfo.Modules)
{
+ // Skip native
+ if (runtimeInfoModule.Version == null)
+ {
+ continue;
+ }
+
+ // Verify that modules that we expect to come from runtime actually come from there
+ if (runtimeModules.Any(rutimeModule => runtimeInfoModule.ModuleName.Equals(rutimeModule, StringComparison.InvariantCultureIgnoreCase)))
+ {
+ Assert.Contains($"shared\\Microsoft.NETCore.App\\{expectedRuntime}", runtimeInfoModule.FileName);
+ continue;
+ }
+
+ // Check if assembly that is in the cache is loaded from it
+ if (cacheAssemblies.Contains(Path.GetFileNameWithoutExtension(runtimeInfoModule.ModuleName)))
+ {
+ if (runtimeInfoModule.FileName.IndexOf("D:\\DotNetCache\\x86\\", StringComparison.CurrentCultureIgnoreCase) == -1)
+ {
+ modulesNotInCache.Add(runtimeInfoModule.FileName);
+ }
+ continue;
+ }
+
+ Assert.Contains("wwwroot\\", runtimeInfoModule.FileName);
+ }
+
+ Assert.Empty(modulesNotInCache);
+ }
+
+ [Theory]
+ [InlineData(WebAppDeploymentKind.Git, "2.0", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Git, "2.0", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.Git, "2.0", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.Git, "latest", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.Git, "latest", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.Git, "latest", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "2.0", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "2.0", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "2.0", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "latest", "web", "Hello World!")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "latest", "razor", "Learn how to build ASP.NET apps that can run anywhere.")]
+ [InlineData(WebAppDeploymentKind.WebDeploy, "latest", "mvc", "Learn how to build ASP.NET apps that can run anywhere.")]
+ public async Task TemplateRuns(WebAppDeploymentKind deploymentKind, string dotnetVersion, string template, string expected)
+ {
+ var testId = ToFriendlyName(nameof(TemplateRuns), deploymentKind, template, dotnetVersion);
+
+ using (var logger = GetLogger(testId))
+ {
+ var siteTask = _fixture.Deploy(AppServicesWithSiteExtensionsTemplate, GetSiteExtensionArguments(), testId);
+
+ var testDirectory = GetTestDirectory(testId);
+ var dotnet = DotNet(logger, testDirectory, dotnetVersion);
+
+ await dotnet.ExecuteAndAssertAsync("new " + template);
+
+ // We don't ship offline cache in site extension so we need to provider a feed to
+ // restore from when doing kudu git deploy for version not published to Nuget
+ if (deploymentKind == WebAppDeploymentKind.Git && dotnetVersion == "latest")
+ {
+ CopyToProjectDirectory(testDirectory, Asset("Nuget.latest.config"), "NuGet.config");
+ }
+
+ InjectMiddlware(testDirectory, RuntimeInformationMiddlewareType, RuntimeInformationMiddlewareFile);
+ FixAspNetCoreVersion(testDirectory, dotnet.Command);
+
+ var site = await siteTask;
+ await site.Deploy(deploymentKind, testDirectory, dotnet, logger);
+
+ using (var httpClient = site.CreateClient())
+ {
+ var getResult = await httpClient.GetAsync("/");
+ getResult.EnsureSuccessStatusCode();
+ Assert.Contains(expected, await getResult.Content.ReadAsStringAsync());
+
+ getResult = await httpClient.GetAsync("/runtimeInfo");
+ getResult.EnsureSuccessStatusCode();
+
+ var runtimeInfo = JsonConvert.DeserializeObject(await getResult.Content.ReadAsStringAsync());
+ ValidateStoreRuntimeInfo(runtimeInfo, dotnet.Command);
+ }
+ }
+ }
+
+ private void ValidateStoreRuntimeInfo(RuntimeInfo runtimeInfo, string dotnetPath)
+ {
+ var storeModules = PathUtilities.GetStoreModules(dotnetPath);
+ var runtimeModules = PathUtilities.GetLatestSharedRuntimeAssemblies(dotnetPath, out var runtimeVersion);
+
+ foreach (var runtimeInfoModule in runtimeInfo.Modules)
+ {
+ // Skip native
+ if (runtimeInfoModule.Version == null)
+ {
+ continue;
+ }
+
var moduleName = Path.GetFileNameWithoutExtension(runtimeInfoModule.ModuleName);
// Check if module should come from the store, verify that one of the expected versions is loaded
@@ -113,14 +207,44 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
// Verify that modules that we expect to come from runtime actually come from there
// Native modules would prefer to be loaded from windows folder, skip them
- if (runtimeModules.Any(rutimeModule => runtimeInfoModule.ModuleName.Equals(rutimeModule, StringComparison.InvariantCultureIgnoreCase)) &&
- runtimeInfoModule.FileName.IndexOf("windows\\system32", StringComparison.InvariantCultureIgnoreCase) == -1)
+ if (runtimeModules.Any(rutimeModule => runtimeInfoModule.ModuleName.Equals(rutimeModule, StringComparison.InvariantCultureIgnoreCase)))
{
Assert.Contains($"shared\\Microsoft.NETCore.App\\{runtimeVersion}", runtimeInfoModule.FileName);
}
}
}
+ private string ToFriendlyName(params object[] parts)
+ {
+ return new string(string.Join(string.Empty, parts).Where(char.IsLetterOrDigit).ToArray());
+ }
+
+ private static Dictionary GetSiteExtensionArguments()
+ {
+ return new Dictionary
+ {
+ { "extensionFeed", AzureFixture.GetRequiredEnvironmentVariable("SiteExtensionFeed") },
+ { "extensionName", "AspNetCoreTestBundle" },
+ { "extensionVersion", GetAssemblyInformationalVersion() },
+ };
+ }
+
+ private static void UpdateCSProj(DirectoryInfo projectRoot, string fileName)
+ {
+ var csproj = projectRoot.GetFiles("*.csproj").Single().FullName;
+
+ // Copy implementation file to project directory
+ var implementationFile = Path.Combine(Directory.GetCurrentDirectory(), fileName);
+ File.Copy(implementationFile, csproj, true);
+ }
+
+ private static void CopyToProjectDirectory(DirectoryInfo projectRoot, string fileName, string desinationFileName = null)
+ {
+ // Copy implementation file to project directory
+ var implementationFile = Path.Combine(Directory.GetCurrentDirectory(), fileName);
+ File.Copy(implementationFile, Path.Combine(projectRoot.FullName, desinationFileName ?? Path.GetFileName(fileName)), true);
+ }
+
private static void InjectMiddlware(DirectoryInfo projectRoot, string typeName, string fileName)
{
// Copy implementation file to project directory
@@ -162,7 +286,7 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
projectContents.Save(csproj);
}
- private string GetAssemblyInformationalVersion()
+ private static string GetAssemblyInformationalVersion()
{
var assemblyInformationalVersionAttribute = typeof(TemplateFunctionalTests).Assembly.GetCustomAttribute();
if (assemblyInformationalVersionAttribute == null)
@@ -208,14 +332,22 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
throw new InvalidOperationException("dotnet executable was not found");
}
-
private DirectoryInfo GetTestDirectory([CallerMemberName] string callerName = null)
{
if (Directory.Exists(callerName))
{
- Directory.Delete(callerName, recursive:true);
+ try
+ {
+ Directory.Delete(callerName, recursive: true);
+ }
+ catch { }
}
return Directory.CreateDirectory(callerName);
}
+
+ private static string Asset(string name)
+ {
+ return "Assets\\" + name;
+ }
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppDeploymentKind.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppDeploymentKind.cs
new file mode 100644
index 0000000000..36b5915f22
--- /dev/null
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppDeploymentKind.cs
@@ -0,0 +1,12 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
+{
+ public enum WebAppDeploymentKind
+ {
+ Git,
+ WebDeploy,
+ Ftp
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppExtensions.cs b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppExtensions.cs
index c53a3ca77d..b7888d7bfa 100644
--- a/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppExtensions.cs
+++ b/test/Microsoft.AspNetCore.AzureAppServices.FunctionalTests/WebAppExtensions.cs
@@ -6,12 +6,12 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.Azure.Management.AppService.Fluent;
using Microsoft.Azure.Management.AppService.Fluent.Models;
using Microsoft.Extensions.Logging;
+using Xunit;
namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
{
@@ -26,21 +26,16 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
public static async Task UploadFilesAsync(this IWebApp site, DirectoryInfo from, string to, IPublishingProfile publishingProfile, ILogger logger)
{
- foreach (var info in from.GetFileSystemInfos("*", SearchOption.AllDirectories))
+ foreach (var info in from.GetFileSystemInfos("*"))
{
+ var address = new Uri(
+ "ftp://" + publishingProfile.FtpUrl + to + info.FullName.Substring(from.FullName.Length + 1).Replace('\\', '/'));
+
if (info is FileInfo file)
{
- var address = new Uri(
- "ftp://" + publishingProfile.FtpUrl + to + file.FullName.Substring(from.FullName.Length).Replace('\\', '/'));
logger.LogInformation($"Uploading {file.FullName} to {address}");
- var request = (FtpWebRequest)WebRequest.Create(address);
- request.Method = WebRequestMethods.Ftp.UploadFile;
- request.KeepAlive = true;
- request.UseBinary = true;
- request.UsePassive = false;
- request.Credentials = new NetworkCredential(publishingProfile.FtpUsername, publishingProfile.FtpPassword);
- request.ConnectionGroupName = "group";
+ var request = CreateRequest(publishingProfile, address, WebRequestMethods.Ftp.UploadFile);
using (var fileStream = File.OpenRead(file.FullName))
{
using (var requestStream = await request.GetRequestStreamAsync())
@@ -50,9 +45,69 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
}
await request.GetResponseAsync();
}
+ if (info is DirectoryInfo directory)
+ {
+ var request = CreateRequest(publishingProfile, address, WebRequestMethods.Ftp.MakeDirectory);
+ await request.GetResponseAsync();
+ await UploadFilesAsync(site, directory, to + directory.Name + '/', publishingProfile, logger);
+ }
}
}
+ private static FtpWebRequest CreateRequest(IPublishingProfile publishingProfile, Uri address, string method)
+ {
+ var request = (FtpWebRequest) WebRequest.Create(address);
+ request.Method = method;
+ request.KeepAlive = true;
+ request.UseBinary = true;
+ request.UsePassive = false;
+ request.Credentials = new NetworkCredential(publishingProfile.FtpUsername, publishingProfile.FtpPassword);
+ request.ConnectionGroupName = "group";
+ return request;
+ }
+
+
+ public static async Task Deploy(this IWebApp site, WebAppDeploymentKind kind, DirectoryInfo from, TestCommand dotnet, ILogger logger)
+ {
+ switch (kind)
+ {
+ case WebAppDeploymentKind.Git:
+ await site.GitDeploy(from, logger);
+ break;
+ case WebAppDeploymentKind.WebDeploy:
+ await site.BuildPublishProfileAsync(from.FullName);
+ await dotnet.ExecuteAndAssertAsync("publish /p:PublishProfile=Profile");
+ break;
+ case WebAppDeploymentKind.Ftp:
+ var publishDirectory = from.CreateSubdirectory("publish");
+ await dotnet.ExecuteAndAssertAsync("restore");
+ await dotnet.ExecuteAndAssertAsync("publish -o " + publishDirectory.FullName);
+ await site.UploadFilesAsync(publishDirectory, "/", await site.GetPublishingProfileAsync(), logger);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(kind), kind, null);
+ }
+ }
+
+ public static async Task GitDeploy(this IWebApp site, DirectoryInfo workingDirectory, ILogger logger)
+ {
+ var git = new TestCommand("git")
+ {
+ Logger = logger,
+ WorkingDirectory = workingDirectory.FullName
+ };
+
+ var publishingProfile = await site.GetPublishingProfileAsync();
+
+ await git.ExecuteAndAssertAsync("init");
+ await git.ExecuteAndAssertAsync($"remote add origin https://{publishingProfile.GitUsername}:{publishingProfile.GitPassword}@{publishingProfile.GitUrl}");
+ await git.ExecuteAndAssertAsync("add .");
+ await git.ExecuteAndAssertAsync("commit -am Initial");
+ var result = await git.ExecuteAndAssertAsync("push origin master");
+
+ Assert.DoesNotContain("An error has occurred during web site deployment", result.StdErr);
+ }
+
public static async Task BuildPublishProfileAsync(this IWebApp site, string projectDirectory)
{
var result = await site.Manager.WebApps.Inner.ListPublishingProfileXmlWithSecretsAsync(