New Backoffice: Refactor migrations to allow for unscoped migrations (#13654)
* Remove PostMigrations These should be replaced with Notification usage * Remove outer scope from Upgrader * Remove unececary null check * Add marker base class for migrations * Enable scopeless migrations * Remove unnecessary state check The final state of the migration is no longer necessarily the final state of the plan. * Extend ExecutedMigrationPlan * Ensure that MigrationPlanExecutor.Execute always returns a result. * Always save final state, regardless of errors * Remove obsolete Execute * Add Umbraco specific migration notification * Publish notification after umbraco migration * Throw the exception that failed a migration after publishing notification * Handle notification publishing in DatabaseBuilder * Fix tests * Remember to complete scope * Clean up MigrationPlanExecutor * Run each package migration in a separate scope * Add PartialMigrationsTests * Add unhappy path test * Fix bug shown by test * Move PartialMigrationsTests into the correct folder * Comment out refresh cache in data type migration Need to add this back again as a notification handler or something. * Start working on a notification test * Allow migrations to request a cache rebuild * Set RebuildCache from MigrateDataTypeConfigurations * Clean MigrationPlanExecutor * Add comment explaining the need to partial migration success * Fix tests * Allow overriding DefinePlan of UmbracoPlan This is needed to test the DatabaseBuilder * Fix notification test * Don't throw exception to be immediately re-caught * Assert that scopes notification are always published * Ensure that scopes are created when requested * Make test classes internal. It doesn't really matter, but this way it doesn't show up in intellisense * Add notification handler for clearing cookies * Add CompatibilitySuppressions * Rename Execute to ExecutePlan We have to do this to be able to obsolete :( * Update CompatibilitySuppressions * Update src/Umbraco.Infrastructure/Migrations/MigrationPlanExecutor.cs Co-authored-by: Bjarke Berg <mail@bergmania.dk> Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -9,9 +9,12 @@ using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NPoco;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.Migrations;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
@@ -37,6 +40,11 @@ public class MigrationPlanTests
|
||||
.Setup(x => x.Database)
|
||||
.Returns(database);
|
||||
|
||||
var databaseFactory = Mock.Of<IUmbracoDatabaseFactory>();
|
||||
Mock.Get(databaseFactory)
|
||||
.Setup(x => x.CreateDatabase())
|
||||
.Returns(database);
|
||||
|
||||
var sqlContext = new SqlContext(
|
||||
new SqlServerSyntaxProvider(Options.Create(new GlobalSettings())),
|
||||
DatabaseType.SQLCe,
|
||||
@@ -59,7 +67,11 @@ public class MigrationPlanTests
|
||||
}
|
||||
});
|
||||
|
||||
var executor = new MigrationPlanExecutor(scopeProvider, scopeProvider, loggerFactory, migrationBuilder);
|
||||
var distributedCache = new DistributedCache(
|
||||
Mock.Of<IServerMessenger>(),
|
||||
new CacheRefresherCollection(() => Enumerable.Empty<ICacheRefresher>()));
|
||||
|
||||
var executor = new MigrationPlanExecutor(scopeProvider, scopeProvider, loggerFactory, migrationBuilder, databaseFactory, Mock.Of<IPublishedSnapshotService>(), distributedCache);
|
||||
|
||||
var plan = new MigrationPlan("default")
|
||||
.From(string.Empty)
|
||||
@@ -77,7 +89,8 @@ public class MigrationPlanTests
|
||||
var sourceState = kvs.GetValue("Umbraco.Tests.MigrationPlan") ?? string.Empty;
|
||||
|
||||
// execute plan
|
||||
state = executor.Execute(plan, sourceState);
|
||||
var result = executor.ExecutePlan(plan, sourceState);
|
||||
state = result.FinalState;
|
||||
|
||||
// save new state
|
||||
kvs.SetValue("Umbraco.Tests.MigrationPlan", sourceState, state);
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NPoco;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Migrations;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Migrations;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Cms.Persistence.SqlServer.Services;
|
||||
using Umbraco.Cms.Tests.Common.TestHelpers;
|
||||
using IScope = Umbraco.Cms.Infrastructure.Scoping.IScope;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations;
|
||||
|
||||
[TestFixture]
|
||||
public class PostMigrationTests
|
||||
{
|
||||
private static readonly ILoggerFactory s_loggerFactory = NullLoggerFactory.Instance;
|
||||
|
||||
private IMigrationPlanExecutor GetMigrationPlanExecutor(
|
||||
ICoreScopeProvider scopeProvider,
|
||||
IScopeAccessor scopeAccessor,
|
||||
IMigrationBuilder builder)
|
||||
=> new MigrationPlanExecutor(scopeProvider, scopeAccessor, s_loggerFactory, builder);
|
||||
|
||||
[Test]
|
||||
public void ExecutesPlanPostMigration()
|
||||
{
|
||||
var builder = Mock.Of<IMigrationBuilder>();
|
||||
Mock.Get(builder)
|
||||
.Setup(x => x.Build(It.IsAny<Type>(), It.IsAny<IMigrationContext>()))
|
||||
.Returns<Type, IMigrationContext>((t, c) =>
|
||||
{
|
||||
switch (t.Name)
|
||||
{
|
||||
case nameof(NoopMigration):
|
||||
return new NoopMigration(c);
|
||||
case nameof(TestPostMigration):
|
||||
return new TestPostMigration(c);
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
});
|
||||
|
||||
var database = new TestDatabase();
|
||||
var scope = Mock.Of<IScope>(x => x.Notifications == Mock.Of<IScopedNotificationPublisher>());
|
||||
Mock.Get(scope)
|
||||
.Setup(x => x.Database)
|
||||
.Returns(database);
|
||||
|
||||
var sqlContext = new SqlContext(
|
||||
new SqlServerSyntaxProvider(Options.Create(new GlobalSettings())),
|
||||
DatabaseType.SQLCe,
|
||||
Mock.Of<IPocoDataFactory>());
|
||||
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
|
||||
|
||||
var plan = new MigrationPlan("Test")
|
||||
.From(string.Empty).To("done");
|
||||
|
||||
plan.AddPostMigration<TestPostMigration>();
|
||||
TestPostMigration.MigrateCount = 0;
|
||||
|
||||
var upgrader = new Upgrader(plan);
|
||||
var executor = GetMigrationPlanExecutor(scopeProvider, scopeProvider, builder);
|
||||
upgrader.Execute(
|
||||
executor,
|
||||
scopeProvider,
|
||||
Mock.Of<IKeyValueService>());
|
||||
|
||||
Assert.AreEqual(1, TestPostMigration.MigrateCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MigrationCanAddPostMigration()
|
||||
{
|
||||
var builder = Mock.Of<IMigrationBuilder>();
|
||||
Mock.Get(builder)
|
||||
.Setup(x => x.Build(It.IsAny<Type>(), It.IsAny<IMigrationContext>()))
|
||||
.Returns<Type, IMigrationContext>((t, c) =>
|
||||
{
|
||||
switch (t.Name)
|
||||
{
|
||||
case nameof(NoopMigration):
|
||||
return new NoopMigration(c);
|
||||
case nameof(TestMigration):
|
||||
return new TestMigration(c);
|
||||
case nameof(TestPostMigration):
|
||||
return new TestPostMigration(c);
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
});
|
||||
|
||||
var database = new TestDatabase();
|
||||
var scope = Mock.Of<IScope>(x => x.Notifications == Mock.Of<IScopedNotificationPublisher>());
|
||||
Mock.Get(scope)
|
||||
.Setup(x => x.Database)
|
||||
.Returns(database);
|
||||
|
||||
var sqlContext = new SqlContext(
|
||||
new SqlServerSyntaxProvider(Options.Create(new GlobalSettings())),
|
||||
DatabaseType.SQLCe,
|
||||
Mock.Of<IPocoDataFactory>());
|
||||
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
|
||||
|
||||
var plan = new MigrationPlan("Test")
|
||||
.From(string.Empty).To<TestMigration>("done");
|
||||
|
||||
TestMigration.MigrateCount = 0;
|
||||
TestPostMigration.MigrateCount = 0;
|
||||
|
||||
new MigrationContext(plan, database, s_loggerFactory.CreateLogger<MigrationContext>());
|
||||
|
||||
var upgrader = new Upgrader(plan);
|
||||
var executor = GetMigrationPlanExecutor(scopeProvider, scopeProvider, builder);
|
||||
upgrader.Execute(
|
||||
executor,
|
||||
scopeProvider,
|
||||
Mock.Of<IKeyValueService>());
|
||||
|
||||
Assert.AreEqual(1, TestMigration.MigrateCount);
|
||||
Assert.AreEqual(1, TestPostMigration.MigrateCount);
|
||||
}
|
||||
|
||||
public class TestMigration : MigrationBase
|
||||
{
|
||||
public TestMigration(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public static int MigrateCount { get; set; }
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
MigrateCount++;
|
||||
|
||||
Context.AddPostMigration<TestPostMigration>();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestPostMigration : MigrationBase
|
||||
{
|
||||
public TestPostMigration(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public static int MigrateCount { get; set; }
|
||||
|
||||
protected override void Migrate() => MigrateCount++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user