Implements unattended package migrations for both explicit and implicit migrations (#10418)

* Clean up and changes to backoffice for the nuget only packages

* temp commit of package logic removal

* Lots of package code cleanup and removal

* Removes old package data from the test package xml

* Updates packaging code to take in XDocument instead of a file since we'll not be dealing with files, starts creating expressions for the package migrations scripting.

* fixing tests

* Fixes runtime state and boot failed middleware so that it actually runs. Separates out unattended install/upgrade into notification handlers.

* Gets unattended package migrations working and running

* Gets embedded package.xml resources able to install from package migration.

* Implements automatic package migrations for package that just declare an xml data manifest.

* fix build

* small cleanups

* fix build

* adds some tests

* Fix export test

* Fix newlines in test for linux

* Typo

* removes old todos and updates AutomaticPackgeMigrationPlan to use getter with backing field.

Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Shannon Deminick
2021-06-15 15:05:57 +10:00
committed by GitHub
parent dc6f1a6086
commit de2fb47b78
120 changed files with 1963 additions and 6284 deletions

View File

@@ -1,51 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core.Packaging;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Packaging
{
[TestFixture]
public class PackageExtractionTests
{
private const string PackageFileName = "Document_Type_Picker_1.1.umb";
private static FileInfo GetTestPackagePath(string packageName)
{
var testPackagesDirName = Path.Combine("Umbraco.Core", "Packaging", "Packages");
var testDir = TestContext.CurrentContext.TestDirectory.Split("bin")[0];
var path = Path.Combine(testDir, testPackagesDirName, packageName);
return new FileInfo(path);
}
[Test]
public void ReadFilesFromArchive_NumberOfFilesIs1_SearchingForPackageXmlFile()
{
// Arrange
var sut = new PackageExtraction();
// Act
IEnumerable<byte[]> result = sut.ReadFilesFromArchive(GetTestPackagePath(PackageFileName), new[] { "Package.xml" });
// Assert
Assert.AreEqual(1, result.Count());
}
[Test]
public void FindMissingFiles_1_UnknownFile()
{
// Arrange
var sut = new PackageExtraction();
// Act
IEnumerable<string> result = sut.FindMissingFiles(GetTestPackagePath(PackageFileName), new[] { "DoesNotExists.XYZ" });
// Assert
Assert.AreEqual(1, result.Count());
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Packaging;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Packaging
{
[TestFixture]
public class PendingPackageMigrationsTests
{
private static readonly Guid s_step1 = Guid.NewGuid();
private static readonly Guid s_step2 = Guid.NewGuid();
private const string PackageName = "Test1";
private class TestPackageMigrationPlan : PackageMigrationPlan
{
public TestPackageMigrationPlan() : base(PackageName)
{
}
protected override void DefinePlan()
{
To(s_step1);
To(s_step2);
}
}
private PendingPackageMigrations GetPendingPackageMigrations()
=> new PendingPackageMigrations(
Mock.Of<ILogger<PendingPackageMigrations>>(),
new PackageMigrationPlanCollection(new[]
{
new TestPackageMigrationPlan()
}));
[Test]
public void GivenNoRegisteredMigrations_ThenPlanIsReturned()
{
PendingPackageMigrations pendingPackageMigrations = GetPendingPackageMigrations();
var registeredMigrations = new Dictionary<string, string>();
IReadOnlyList<string> pending = pendingPackageMigrations.GetUmbracoPendingPackageMigrations(registeredMigrations);
Assert.AreEqual(1, pending.Count);
}
[Test]
public void GivenRegisteredMigration_WhenFinalStepMatched_ThenNoneAreReturned()
{
PendingPackageMigrations pendingPackageMigrations = GetPendingPackageMigrations();
var registeredMigrations = new Dictionary<string, string>
{
[Constants.Conventions.Migrations.KeyValuePrefix + PackageName] = s_step2.ToString()
};
IReadOnlyList<string> pending = pendingPackageMigrations.GetUmbracoPendingPackageMigrations(registeredMigrations);
Assert.AreEqual(0, pending.Count);
}
[Test]
public void GivenRegisteredMigration_WhenNonFinalStepMatched_ThenPlanIsReturned()
{
PendingPackageMigrations pendingPackageMigrations = GetPendingPackageMigrations();
var registeredMigrations = new Dictionary<string, string>
{
[Constants.Conventions.Migrations.KeyValuePrefix + PackageName] = s_step1.ToString()
};
IReadOnlyList<string> pending = pendingPackageMigrations.GetUmbracoPendingPackageMigrations(registeredMigrations);
Assert.AreEqual(1, pending.Count);
}
[Test]
public void GivenRegisteredMigration_WhenStepIsDifferentCase_ThenPlanIsReturned()
{
PendingPackageMigrations pendingPackageMigrations = GetPendingPackageMigrations();
var registeredMigrations = new Dictionary<string, string>
{
[Constants.Conventions.Migrations.KeyValuePrefix + PackageName] = s_step1.ToString().ToUpper()
};
IReadOnlyList<string> pending = pendingPackageMigrations.GetUmbracoPendingPackageMigrations(registeredMigrations);
Assert.AreEqual(1, pending.Count);
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Linq;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Migrations;
using Umbraco.Cms.Infrastructure.Migrations;
using Umbraco.Cms.Tests.Common.TestHelpers;
using Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations.Stubs;
@@ -16,14 +17,24 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
[TestFixture]
public class AlterMigrationTests
{
private readonly ILogger<MigrationContext> _logger = Mock.Of<ILogger<MigrationContext>>();
private readonly ILogger<MigrationContext> _logger = Mock.Of<ILogger<MigrationContext>>();
private class TestPlan : MigrationPlan
{
public TestPlan() : base("Test")
{
}
}
private MigrationContext GetMigrationContext(out TestDatabase db)
{
db = new TestDatabase();
return new MigrationContext(new TestPlan(), db, _logger);
}
[Test]
public void Drop_Foreign_Key()
{
// Arrange
var database = new TestDatabase();
var context = new MigrationContext(database, _logger);
var context = GetMigrationContext(out var database);
var stub = new DropForeignKeyMigrationStub(context);
// Act
@@ -44,8 +55,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
[Test]
public void CreateColumn()
{
var database = new TestDatabase();
var context = new MigrationContext(database, _logger);
var context = GetMigrationContext(out var database);
var migration = new CreateColumnMigration(context);
migration.Migrate();
@@ -74,8 +84,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
[Test]
public void AlterColumn()
{
var database = new TestDatabase();
var context = new MigrationContext(database, _logger);
var context = GetMigrationContext(out var database);
var migration = new AlterColumnMigration(context);
migration.Migrate();
@@ -110,8 +119,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
public void Can_Get_Up_Migration_From_MigrationStub()
{
// Arrange
var database = new TestDatabase();
var context = new MigrationContext(database, _logger);
var context = GetMigrationContext(out var database);
var stub = new AlterUserTableMigrationStub(context);
// Act

View File

@@ -59,11 +59,18 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
#endif
}
private class TestPlan : MigrationPlan
{
public TestPlan() : base("Test")
{
}
}
private MigrationContext GetMigrationContext() => new MigrationContext(new TestPlan(), Mock.Of<IUmbracoDatabase>(), Mock.Of<ILogger<MigrationContext>>());
[Test]
public void RunGoodMigration()
{
var migrationContext =
new MigrationContext(Mock.Of<IUmbracoDatabase>(), Mock.Of<ILogger<MigrationContext>>());
var migrationContext = GetMigrationContext();
IMigration migration = new GoodMigration(migrationContext);
migration.Migrate();
}
@@ -71,8 +78,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
[Test]
public void DetectBadMigration1()
{
var migrationContext =
new MigrationContext(Mock.Of<IUmbracoDatabase>(), Mock.Of<ILogger<MigrationContext>>());
var migrationContext = GetMigrationContext();
IMigration migration = new BadMigration1(migrationContext);
Assert.Throws<IncompleteMigrationExpressionException>(() => migration.Migrate());
}
@@ -80,8 +86,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
[Test]
public void DetectBadMigration2()
{
var migrationContext =
new MigrationContext(Mock.Of<IUmbracoDatabase>(), Mock.Of<ILogger<MigrationContext>>());
var migrationContext = GetMigrationContext();
IMigration migration = new BadMigration2(migrationContext);
Assert.Throws<IncompleteMigrationExpressionException>(() => migration.Migrate());
}

View File

@@ -113,7 +113,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations
TestMigration.MigrateCount = 0;
TestPostMigration.MigrateCount = 0;
new MigrationContext(database, s_loggerFactory.CreateLogger<MigrationContext>());
new MigrationContext(plan, database, s_loggerFactory.CreateLogger<MigrationContext>());
var upgrader = new Upgrader(plan);
IMigrationPlanExecutor executor = GetMigrationPlanExecutor(scopeProvider, builder);