Last active
August 26, 2021 11:49
-
-
Save GeorgDangl/5521ef94bc6cae85793f8842f64fa3c5 to your computer and use it in GitHub Desktop.
WebDeploy task for Nuke, see https://github.com/nuke-build/nuke, code partially taken from https://github.com/SharpeRAD/Cake.WebDeploy Here's more about it: https://blog.dangl.me/archive/using-webdeploy-via-nuke-build-scripts/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Web.Deployment; | |
using System; | |
using System.IO; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
public class AppOfflineWrapper : IDisposable | |
{ | |
private readonly WebDeploySettings _settings; | |
private string _tempAppOfflinePath; | |
public AppOfflineWrapper(WebDeploySettings settings) | |
{ | |
_settings = settings; | |
CreateAppOffline(); | |
} | |
public void Dispose() | |
{ | |
RemoveAppOffline(); | |
} | |
private void CreateAppOffline() | |
{ | |
if (!_settings.WrapAppOffline) | |
{ | |
return; | |
} | |
GenerateTempAppOffline(); | |
CreateOrDeleteAppOffline(true); | |
} | |
private void GenerateTempAppOffline() | |
{ | |
_tempAppOfflinePath = Path.GetTempFileName(); | |
File.WriteAllText(_tempAppOfflinePath, _settings.AppOfflineHtmlTemplate); | |
} | |
private void RemoveAppOffline() | |
{ | |
if (!_settings.WrapAppOffline) | |
{ | |
return; | |
} | |
CreateOrDeleteAppOffline(false); | |
File.Delete(_tempAppOfflinePath); | |
} | |
private void CreateOrDeleteAppOffline(bool create = true) | |
{ | |
var sourceOptions = WebDeployOptionsFactory.GetSourceOptions(_settings); | |
var destinationOptions = WebDeployOptionsFactory.GetDestinationOptions(_settings); | |
destinationOptions.Trace += WebDeployLogger.DestinationOptions_Trace; | |
var syncOptions = WebDeployOptionsFactory.GetSyncOptions(_settings); | |
if (!create) | |
{ | |
syncOptions.DoNotDelete = false; | |
} | |
var sourceProvider = DeploymentWellKnownProvider.ContentPath; | |
var destinationProvider = DeploymentWellKnownProvider.ContentPath; | |
using (var deploymentObject = DeploymentManager.CreateObject(sourceProvider, _tempAppOfflinePath, sourceOptions)) | |
{ | |
if (!create) | |
{ | |
syncOptions.DeleteDestination = true; | |
} | |
deploymentObject.SyncTo(destinationProvider, _settings.SiteName + "/app_offline.htm", destinationOptions, syncOptions); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Nuke.Common; | |
using Nuke.Common.Git; | |
using Nuke.Common.Tools.GitVersion; | |
using Nuke.Core; | |
using static Nuke.Common.Tools.DotNet.DotNetTasks; | |
using static Nuke.Common.Tools.Npm.NpmTasks; | |
using static Nuke.Core.IO.FileSystemTasks; | |
using static Nuke.Core.IO.PathConstruction; | |
using static Nuke.Core.EnvironmentInfo; | |
using Nuke.Core.Tooling; | |
using Nuke.Common.Tools.Npm; | |
using static Nuke.Common.Tools.WebConfigTransformRunner.WebConfigTransformRunnerTasks; | |
using Nuke.Common.Tools.WebConfigTransformRunner; | |
using Nuke.Common.Tools.DotNet; | |
using static Nuke.Common.Tools.WebDeploy.WebDeployTasks; | |
using Nuke.Common.Tools.WebDeploy; | |
class Build : NukeBuild | |
{ | |
// Console application entry. Also defines the default target. | |
public static int Main() => Execute<Build>(x => x.Clean); | |
[Parameter] readonly string Environment; | |
[Parameter] readonly string WebDeployUsername; | |
[Parameter] readonly string WebDeployPassword; | |
[Parameter] readonly string WebDeployPublishUrl; | |
[Parameter] readonly string WebDeploySiteName; | |
Target Publish => _ => _ | |
.Requires(() => Environment) | |
.DependsOn(FrontendRestore) | |
.DependsOn(BackendRestore) | |
.DependsOn(FrontendCompile) | |
.Executes(() => | |
{ | |
DotNetPublish(p => | |
{ | |
return p.SetWorkingDirectory(SourceDirectory / "project_name") | |
.SetConfiguration(Environment) | |
.SetOutput(OutputDirectory); | |
}); | |
WebConfigTransformRunner(p => | |
{ | |
return p.SetWebConfigFilename(OutputDirectory / "web.config") | |
.SetTransformFilename(OutputDirectory / $"web.{Environment}.config") | |
.SetOutputFilename(OutputDirectory / "web.config"); | |
}); | |
}); | |
Target Deploy => _ => _ | |
.DependsOn(Publish) | |
.Requires(() => WebDeployUsername) | |
.Requires(() => WebDeployPassword) | |
.Requires(() => WebDeployPublishUrl) | |
.Requires(() => WebDeploySiteName) | |
.Executes(() => | |
{ | |
WebDeploy(s => | |
{ | |
return s.SetSourcePath(OutputDirectory) | |
.SetUsername(WebDeployUsername) | |
.SetPassword(WebDeployPassword) | |
.SetEnableAppOfflineRule(true) | |
.SetPublishUrl(WebDeployPublishUrl) | |
.SetSiteName(WebDeploySiteName) | |
.SetWrapAppOffline(true); | |
}); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net461</TargetFramework> | |
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | |
<RootNamespace></RootNamespace> | |
<IsPackable>False</IsPackable> | |
<NoWarn>CS0649;CS0169</NoWarn> | |
<!-- NUKE CONFIGURATION --> | |
<NukeVersion>0.1.454</NukeVersion> | |
<NukeCodeGeneration>False</NukeCodeGeneration> | |
<StartupObject>Build</StartupObject> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Nuke.Common" Version="$(NukeVersion)" /> | |
<PackageReference Include="Nuke.CodeGeneration" Version="$(NukeVersion)" Condition="'$(NukeCodeGeneration)' != 'False'" /> | |
<PackageReference Include="Microsoft.Web.Deployment" Version="3.6.0" /> | |
<PackageReference Include="GitVersion.CommandLine" Version="4.0.0-beta0011" /> | |
<PackageReference Include="WebConfigTransformRunner" Version="1.0.0.1"> | |
<PrivateAssets>All</PrivateAssets> | |
</PackageReference> | |
</ItemGroup> | |
<ItemGroup> | |
<NukeMetadata Include="**/*.json" Exclude="bin/**;obj/**" /> | |
<None Remove="*.csproj.dotsettings;_schema.json;*.ref.*.txt" /> | |
<None Remove="*.json;*.json.new" Condition="'$(NukeCodeGeneration)' == 'False'" /> | |
</ItemGroup> | |
<ItemGroup> | |
<EmbeddedResource Include="Resources\*" Exclude="bin\**;obj\**;**\*.xproj;packages\**;@(EmbeddedResource)" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
App Offline - Maintenance | |
</title> | |
<style tyle="text/css"> | |
body { | |
text-align: center; | |
padding: 150px; | |
font: 20px Helvetica, sans-serif; | |
color: #333; | |
} | |
h1 { | |
font-size: 50px; | |
} | |
div { | |
display: block; | |
text-align: left; | |
width: 650px; | |
margin: 0 auto; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>App Temporary Offline</h1> | |
<div> | |
<p>This website is temporary offline for maintenance. It should be back in a few moments.</p> | |
<p>Sorry for the inconvenience!</p> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Web.Deployment; | |
using Nuke.Core; | |
using System.Diagnostics; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
public static class WebDeployLogger | |
{ | |
public static void DestinationOptions_Trace(object sender, DeploymentTraceEventArgs e) | |
{ | |
switch (e.EventLevel) | |
{ | |
case TraceLevel.Error: | |
Logger.Error(e.Message); | |
break; | |
case TraceLevel.Warning: | |
Logger.Warn(e.Message); | |
break; | |
case TraceLevel.Info: | |
Logger.Info(e.Message); | |
break; | |
case TraceLevel.Verbose: | |
Logger.Trace(e.Message); | |
break; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Web.Deployment; | |
using System.Linq; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
public static class WebDeployOptionsFactory | |
{ | |
public static DeploymentBaseOptions GetDestinationOptions(WebDeploySettings settings) | |
{ | |
var options = new DeploymentBaseOptions(); | |
options.AuthenticationType = "basic"; | |
options.ComputerName = settings.PublishUrl; | |
options.UserName = settings.Username; | |
options.Password = settings.Password; | |
options.RetryAttempts = settings.RetryAttempts; | |
options.RetryInterval = settings.RetryInterval; | |
return options; | |
} | |
public static DeploymentBaseOptions GetSourceOptions(WebDeploySettings settings) | |
{ | |
var options = new DeploymentBaseOptions(); | |
return options; | |
} | |
public static DeploymentSyncOptions GetSyncOptions(WebDeploySettings settings) | |
{ | |
var options = new DeploymentSyncOptions(); | |
options.DoNotDelete = settings.EnableDoNotDeleteRule; | |
options.WhatIf = settings.ShowWhatIf; | |
if (settings.EnableAppOfflineRule) | |
{ | |
var appOfflineRule = GetRuleByName("AppOffline"); | |
options.Rules.Add(appOfflineRule); | |
} | |
// TODO MORE RULES | |
return options; | |
} | |
private static DeploymentRule GetRuleByName(string ruleName) | |
{ | |
var availableRules = DeploymentSyncOptions.GetAvailableRules(); | |
var rule = availableRules.Single(r => string.Equals(r.Name, ruleName, System.StringComparison.InvariantCultureIgnoreCase)); | |
return rule; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using JetBrains.Annotations; | |
using Nuke.Core.Tooling; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics.CodeAnalysis; | |
using System.IO; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
[PublicAPI] | |
[ExcludeFromCodeCoverage] | |
[Serializable] | |
public class WebDeploySettings : ToolSettings | |
{ | |
[Obsolete("Not required for WebDeploySettings")] | |
public override string ToolPath => null; | |
public virtual bool UseDoNotDeleteRule { get; internal set; } | |
public virtual string PublishUrl { get; internal set; } | |
public virtual string Username { get; internal set; } | |
public virtual string Password { get; internal set; } | |
public virtual bool EnableDoNotDeleteRule { get; internal set; } | |
public virtual bool EnableAppOfflineRule { get; internal set; } | |
public virtual bool ShowWhatIf { get; internal set; } | |
public virtual string SiteName { get; internal set; } | |
public virtual string SourcePath { get; internal set; } | |
public virtual string DestinationPath { get; internal set; } | |
public virtual IReadOnlyDictionary<string, string> Parameters { get; internal set; } | |
public virtual int RetryAttempts { get; internal set; } = 5; | |
public virtual int RetryInterval { get; internal set; } = 5000; | |
/// <summary> | |
/// This is because Azure is still case sensitive when deploying App_Offline.htm via | |
/// the WebDeploy rule. An all-lowercase app_offline.htm will be created prior to deployment | |
/// and removed afterwards if this option is enabled. | |
/// </summary> | |
public virtual bool WrapAppOffline { get; internal set; } | |
public virtual string AppOfflineHtmlTemplate { get; internal set; } = GetDefaultAppOffline(); | |
protected override void AssertValid() | |
{ | |
base.AssertValid(); | |
} | |
private static string GetDefaultAppOffline() | |
{ | |
using (var templateStream = typeof(WebDeploySettings).Assembly.GetManifestResourceStream("Resources.DefaultAppOffline.html")) | |
{ | |
if (templateStream == null) | |
{ | |
return "App Temporary Offline for Maintenance"; | |
} | |
using (var streamReader = new StreamReader(templateStream)) | |
{ | |
var template = streamReader.ReadToEnd(); | |
return template; | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using JetBrains.Annotations; | |
using Nuke.Core.Tooling; | |
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Diagnostics.CodeAnalysis; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
[PublicAPI] | |
[ExcludeFromCodeCoverage] | |
public static class WebDeploySettingsExtensions | |
{ | |
[Pure] | |
public static WebDeploySettings SetUseDoNotDeleteRule(this WebDeploySettings toolSettings, bool useDoNotDeleteRule) | |
=> toolSettings.CloneAndModify(s => s.UseDoNotDeleteRule = useDoNotDeleteRule); | |
[Pure] | |
public static WebDeploySettings SetPublishUrl(this WebDeploySettings toolSettings, string publishUrl) | |
=> toolSettings.CloneAndModify(s => s.PublishUrl = publishUrl); | |
[Pure] | |
public static WebDeploySettings SetUsername(this WebDeploySettings toolSettings, string username) | |
=> toolSettings.CloneAndModify(s => s.Username = username); | |
[Pure] | |
public static WebDeploySettings SetPassword(this WebDeploySettings toolSettings, string password) | |
=> toolSettings.CloneAndModify(s => s.Password = password); | |
[Pure] | |
public static WebDeploySettings SetEnableDoNotDeleteRule(this WebDeploySettings toolSettings, bool enableDoNotDeleteRule) | |
=> toolSettings.CloneAndModify(s => s.EnableDoNotDeleteRule = enableDoNotDeleteRule); | |
[Pure] | |
public static WebDeploySettings SetEnableAppOfflineRule(this WebDeploySettings toolSettings, bool enableAppOfflineRule) | |
=> toolSettings.CloneAndModify(s => s.EnableAppOfflineRule = enableAppOfflineRule); | |
[Pure] | |
public static WebDeploySettings SetShowWhatIf(this WebDeploySettings toolSettings, bool showWhatIf) | |
=> toolSettings.CloneAndModify(s => s.ShowWhatIf = showWhatIf); | |
[Pure] | |
public static WebDeploySettings SetSiteName(this WebDeploySettings toolSettings, string siteName) | |
=> toolSettings.CloneAndModify(s => s.SiteName = siteName); | |
[Pure] | |
public static WebDeploySettings SetSourcePath(this WebDeploySettings toolSettings, string sourcePath) | |
=> toolSettings.CloneAndModify(s => s.SourcePath = sourcePath); | |
[Pure] | |
public static WebDeploySettings SetDestinationPath(this WebDeploySettings toolSettings, string destinationPath) | |
=> toolSettings.CloneAndModify(s => s.DestinationPath = destinationPath); | |
[Pure] | |
public static WebDeploySettings SetParameters(this WebDeploySettings toolSettings, IDictionary<string, string> parameters) | |
=> toolSettings.CloneAndModify(s => s.Parameters = new ReadOnlyDictionary<string, string>(parameters)); | |
[Pure] | |
public static WebDeploySettings SetRetryAttempts(this WebDeploySettings toolSettings, int retryAttempts) | |
=> toolSettings.CloneAndModify(s => s.RetryAttempts = retryAttempts); | |
[Pure] | |
public static WebDeploySettings SetRetryInterval(this WebDeploySettings toolSettings, int retryInterval) | |
=> toolSettings.CloneAndModify(s => s.RetryInterval = retryInterval); | |
[Pure] | |
public static WebDeploySettings SetWrapAppOffline(this WebDeploySettings toolSettings, bool wrapAppOffline) | |
=> toolSettings.CloneAndModify(s => s.WrapAppOffline = wrapAppOffline); | |
[Pure] | |
public static WebDeploySettings SetAppOfflineHtmlTemplate(this WebDeploySettings toolSettings, string appOfflineHtmlTemplate) | |
=> toolSettings.CloneAndModify(s => s.AppOfflineHtmlTemplate = appOfflineHtmlTemplate); | |
private static WebDeploySettings CloneAndModify(this WebDeploySettings toolSettings, Action<WebDeploySettings> modifyAction) | |
{ | |
toolSettings = toolSettings.NewInstance(); | |
modifyAction(toolSettings); | |
return toolSettings; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Web.Deployment; | |
using Nuke.Core.Tooling; | |
namespace Nuke.Common.Tools.WebDeploy | |
{ | |
public class WebDeployTasks | |
{ | |
public static void WebDeploy(Configure<WebDeploySettings> configurator) | |
{ | |
var settings = configurator.InvokeSafe(new WebDeploySettings()); | |
using (var appOfflineWrapper = new AppOfflineWrapper(settings)) | |
{ | |
var sourceOptions = WebDeployOptionsFactory.GetSourceOptions(settings); | |
var destinationOptions = WebDeployOptionsFactory.GetDestinationOptions(settings); | |
destinationOptions.Trace += WebDeployLogger.DestinationOptions_Trace; | |
var syncOptions = WebDeployOptionsFactory.GetSyncOptions(settings); | |
var sourceProvider = DeploymentWellKnownProvider.IisApp; | |
var destinationProvider = DeploymentWellKnownProvider.IisApp; | |
using (var deploymentObject = DeploymentManager.CreateObject(sourceProvider, settings.SourcePath, sourceOptions)) | |
{ | |
if (settings.Parameters != null) | |
{ | |
foreach (var kv in settings.Parameters) | |
{ | |
if (deploymentObject.SyncParameters.Contains(kv.Key)) | |
{ | |
deploymentObject.SyncParameters[kv.Key].Value = kv.Value; | |
} | |
else | |
{ | |
deploymentObject.SyncParameters.Add(new DeploymentSyncParameter(kv.Key, kv.Key, "", "") | |
{ | |
Value = kv.Value | |
}); | |
} | |
} | |
} | |
deploymentObject.SyncTo(destinationProvider, settings.SiteName, destinationOptions, syncOptions); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment