Skip to content

Instantly share code, notes, and snippets.

@tomvanenckevort
Last active November 1, 2018 10:28
Show Gist options
  • Save tomvanenckevort/0d1de85a3ec9cc2e5b4b66ca4789df88 to your computer and use it in GitHub Desktop.
Save tomvanenckevort/0d1de85a3ec9cc2e5b4b66ca4789df88 to your computer and use it in GitHub Desktop.
Automatic Umbraco upgrade module.

Will automatically execute a pending Umbraco upgrade on startup without prompting the user.

using System.Web;
using Umbraco.Core;
using Codery.AutoUpgrade.Services;
namespace Codery.AutoUpgrade.App_Start
{
public class ApplicationEvents : ApplicationEventHandler
{
// make sure event handler gets registered when Umbraco hasn't been configured (i.e. pending an upgrade)
protected override bool ExecuteWhenApplicationNotConfigured => true;
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationBase_ApplicationInit;
}
private static void UmbracoApplicationBase_ApplicationInit(object sender, System.EventArgs e)
{
if (sender is HttpApplication application)
{
application.PostResolveRequestCache += Application_PostResolveRequestCache;
}
}
private static void Application_PostResolveRequestCache(object sender, System.EventArgs e)
{
AutoUpgradeService.Upgrade();
}
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Http;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.Install.Controllers;
using Umbraco.Web.Install.Models;
using Umbraco.Web.Security;
namespace Codery.AutoUpgrade.Services
{
internal class AutoUpgradeService
{
internal static void Upgrade()
{
if (!IsEnabled || ApplicationContext.Current.IsConfigured)
{
// automatic upgrades not enabled, or already configured
return;
}
if (!ApplicationContext.Current.DatabaseContext.IsDatabaseConfigured)
{
// database hasn't been configured, so we can't do automatic upgrade
return;
}
if (upgradeAttemptFailed)
{
// a previous upgrade attempt has failed, skip automatic upgrade for now to allow a manual upgrade instead
return;
}
using (var controller = new InstallApiController())
{
// get setup steps
var installSetup = controller.GetSetup();
var instructions = new InstallInstructions()
{
InstallId = installSetup.InstallId,
Instructions = installSetup.Steps.ToDictionary(k => k.Name, v => JToken.Parse(JsonConvert.SerializeObject(v.ViewModel)))
};
// run each upgrade step until there are no more steps to run
bool hasNextStep = true;
while (hasNextStep)
{
try
{
var result = controller.PostPerformInstall(instructions);
if (string.IsNullOrEmpty(result.NextStep))
{
hasNextStep = false;
}
}
catch (HttpResponseException ex)
{
LogHelper.Error<AutoUpgradeService>("Failed to complete automatic upgrade", ex);
upgradeAttemptFailed = true;
hasNextStep = false;
}
}
}
var security = new WebSecurity(new HttpContextWrapper(HttpContext.Current), ApplicationContext.Current);
if (security.IsAuthenticated() && security.GetUserId() == 0)
{
// log out the admin user, since this might be from an automatic login during the upgrade
security.ClearCurrentLogin();
}
var request = HttpContext.Current?.Request;
if (request?.Url == null)
{
return;
}
// check if user was redirected to installation page
if (request.QueryString["redir"] == "true" && request.QueryString["url"] != null)
{
// redirect user to initial page
HttpContext.Current?.Response.Redirect(request.QueryString["url"], true);
return;
}
// redirect to current page to force a reload
HttpContext.Current?.Response.Redirect(request.Url.ToString(), true);
}
private static bool upgradeAttemptFailed;
private static bool? isEnabled;
/// <summary>
/// Returns whether automatic upgrades have been enabled.
/// </summary>
private static bool IsEnabled
{
get
{
if (isEnabled == null)
{
// read AutoUpgrade setting from web.config
isEnabled = ConfigurationManager.AppSettings["AutoUpgrade.Enabled"].InvariantEquals("true");
}
return isEnabled.Value;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment