forked from umbraco/Umbraco-CMS
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix smidge bundles not always invalidated between backoffice versions. (
umbraco#11700) * Introduced new smidge CacheBuster with sensible defaults. * Bring back reset functionality in SmidgeRuntimeMinifier * Clearer obsolete messaging.
- Loading branch information
Paul Johnson
authored
Dec 2, 2021
1 parent
6c5851f
commit 08f106a
Showing
12 changed files
with
257 additions
and
15 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System.Reflection; | ||
|
||
namespace Umbraco.Cms.Core.Configuration | ||
{ | ||
internal class EntryAssemblyMetadata : IEntryAssemblyMetadata | ||
{ | ||
public EntryAssemblyMetadata() | ||
{ | ||
var entryAssembly = Assembly.GetEntryAssembly(); | ||
|
||
Name = entryAssembly | ||
?.GetName() | ||
?.Name ?? string.Empty; | ||
|
||
InformationalVersion = entryAssembly | ||
?.GetCustomAttribute<AssemblyInformationalVersionAttribute>() | ||
?.InformationalVersion ?? string.Empty; | ||
} | ||
|
||
public string Name { get; } | ||
|
||
public string InformationalVersion { get; } | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
namespace Umbraco.Cms.Core.Configuration | ||
{ | ||
/// <summary> | ||
/// Provides metadata about the entry assembly. | ||
/// </summary> | ||
public interface IEntryAssemblyMetadata | ||
{ | ||
/// <summary> | ||
/// Gets the Name of entry assembly. | ||
/// </summary> | ||
public string Name { get; } | ||
|
||
/// <summary> | ||
/// Gets the InformationalVersion string for entry assembly. | ||
/// </summary> | ||
public string InformationalVersion { get; } | ||
} | ||
} |
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
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
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
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
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
77 changes: 77 additions & 0 deletions
77
src/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBuster.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
using System; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using Smidge; | ||
using Smidge.Cache; | ||
using Umbraco.Cms.Core.Configuration; | ||
using Umbraco.Cms.Core.Configuration.Models; | ||
using Umbraco.Extensions; | ||
|
||
namespace Umbraco.Cms.Web.Common.RuntimeMinification | ||
{ | ||
/// <summary> | ||
/// Constructs a cache buster string with sensible defaults. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para> | ||
/// Had planned on handling all of this in SmidgeRuntimeMinifier, but that only handles some urls. | ||
/// </para> | ||
/// <para> | ||
/// A lot of the work is delegated e.g. to <see cref="SmidgeHelper.GenerateJsUrlsAsync(string, bool)"/> | ||
/// which doesn't care about the cache buster string in our classes only the value returned by the resolved ICacheBuster. | ||
/// </para> | ||
/// <para> | ||
/// Then I thought fine I'll just use a IConfigureOptions to tweak upstream <see cref="ConfigCacheBuster"/>, but that only cares about the <see cref="SmidgeConfig"/> | ||
/// class we instantiate and pass through in <see cref="Umbraco.Extensions.UmbracoBuilderExtensions.AddRuntimeMinifier"/> | ||
/// </para> | ||
/// <para> | ||
/// So here we are, create our own to ensure we cache bust in a reasonable fashion. | ||
/// </para> | ||
/// <br/><br/> | ||
/// <para> | ||
/// Note that this class makes some other bits of code pretty redundant e.g. <see cref="UrlHelperExtensions.GetUrlWithCacheBust"/> will | ||
/// concatenate version with CacheBuster value and hash again, but there's no real harm so can think about that later. | ||
/// </para> | ||
/// </remarks> | ||
internal class UmbracoSmidgeConfigCacheBuster : ICacheBuster | ||
{ | ||
private readonly IOptions<RuntimeMinificationSettings> _runtimeMinificationSettings; | ||
private readonly IUmbracoVersion _umbracoVersion; | ||
private readonly IEntryAssemblyMetadata _entryAssemblyMetadata; | ||
|
||
private string _cacheBusterValue; | ||
|
||
public UmbracoSmidgeConfigCacheBuster( | ||
IOptions<RuntimeMinificationSettings> runtimeMinificationSettings, | ||
IUmbracoVersion umbracoVersion, | ||
IEntryAssemblyMetadata entryAssemblyMetadata) | ||
{ | ||
_runtimeMinificationSettings = runtimeMinificationSettings ?? throw new ArgumentNullException(nameof(runtimeMinificationSettings)); | ||
_umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); | ||
_entryAssemblyMetadata = entryAssemblyMetadata ?? throw new ArgumentNullException(nameof(entryAssemblyMetadata)); | ||
} | ||
|
||
private string CacheBusterValue | ||
{ | ||
get | ||
{ | ||
if (_cacheBusterValue != null) | ||
{ | ||
return _cacheBusterValue; | ||
} | ||
|
||
// Assembly Name adds a bit of uniqueness across sites when version missing from config. | ||
// Adds a bit of security through obscurity that was asked for in standup. | ||
var prefix = _runtimeMinificationSettings.Value.Version ?? _entryAssemblyMetadata.Name ?? string.Empty; | ||
var umbracoVersion = _umbracoVersion.SemanticVersion.ToString(); | ||
var downstreamVersion = _entryAssemblyMetadata.InformationalVersion; | ||
|
||
_cacheBusterValue = $"{prefix}_{umbracoVersion}_{downstreamVersion}".GenerateHash(); | ||
|
||
return _cacheBusterValue; | ||
} | ||
} | ||
|
||
public string GetValue() => CacheBusterValue; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
root = false | ||
|
||
[*.cs] | ||
csharp_style_var_when_type_is_apparent = true:none | ||
csharp_style_var_elsewhere = true:none |
113 changes: 113 additions & 0 deletions
113
...s.UnitTests/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBusterTests.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using AutoFixture; | ||
using AutoFixture.AutoMoq; | ||
using AutoFixture.Kernel; | ||
using Microsoft.Extensions.Options; | ||
using Moq; | ||
using NUnit.Framework; | ||
using Smidge; | ||
using Smidge.Cache; | ||
using Umbraco.Cms.Core.Configuration; | ||
using Umbraco.Cms.Core.Configuration.Models; | ||
using Umbraco.Cms.Core.Semver; | ||
using Umbraco.Cms.Web.Common.RuntimeMinification; | ||
using Umbraco.Extensions; | ||
|
||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.RuntimeMinification | ||
{ | ||
/// <remarks> | ||
/// UmbracoCustomizations kindly configures an IUmbracoVersion so we need to go verbose without AutoMoqData | ||
/// </remarks> | ||
[TestFixture] | ||
public class UmbracoSmidgeConfigCacheBusterTests | ||
{ | ||
[Test] | ||
public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_HasSensibleDefaults() | ||
{ | ||
var fixture = new Fixture(); | ||
fixture.Customize(new AutoMoqCustomization()); | ||
|
||
var umbracoVersion = fixture.Freeze<Mock<IUmbracoVersion>>(); | ||
var entryAssemblyMetadata = fixture.Freeze<Mock<IEntryAssemblyMetadata>>(); | ||
var sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); | ||
entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); | ||
entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); | ||
|
||
var result = sut.GetValue(); | ||
|
||
var expected = $"Bills.Brilliant.Bakery_9.4.5-beta+41658f99_42.1.2-alpha+41658f99".GenerateHash(); | ||
Assert.AreEqual(expected, result); | ||
} | ||
|
||
[Test] | ||
public void GetValue_DefaultReleaseSetupWithConfiguredVersion_HasSensibleDefaults() | ||
{ | ||
var config = Options.Create(new RuntimeMinificationSettings { Version = "1" }); | ||
var fixture = new Fixture(); | ||
fixture.Customize(new AutoMoqCustomization()); | ||
fixture.Inject(config); | ||
|
||
var umbracoVersion = fixture.Freeze<Mock<IUmbracoVersion>>(); | ||
var entryAssemblyMetadata = fixture.Freeze<Mock<IEntryAssemblyMetadata>>(); | ||
var sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); | ||
entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); | ||
entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); | ||
|
||
var result = sut.GetValue(); | ||
|
||
var expected = $"1_9.4.5-beta+41658f99_42.1.2-alpha+41658f99".GenerateHash(); | ||
Assert.AreEqual(expected, result); | ||
} | ||
|
||
[Test] | ||
public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_ChangesWhenUmbracoVersionChanges() | ||
{ | ||
var fixture = new Fixture(); | ||
fixture.Customize(new AutoMoqCustomization()); | ||
|
||
var umbracoVersion = fixture.Freeze<Mock<IUmbracoVersion>>(); | ||
var entryAssemblyMetadata = fixture.Freeze<Mock<IEntryAssemblyMetadata>>(); | ||
var sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); | ||
entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); | ||
entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); | ||
|
||
var before = sut.GetValue(); | ||
|
||
umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 5, 0, "beta", "41658f99")); | ||
sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
var after = sut.GetValue(); | ||
|
||
Assert.AreNotEqual(before, after); | ||
} | ||
|
||
[Test] | ||
public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_ChangesWhenDownstreamVersionChanges() | ||
{ | ||
var fixture = new Fixture(); | ||
fixture.Customize(new AutoMoqCustomization()); | ||
|
||
var umbracoVersion = fixture.Freeze<Mock<IUmbracoVersion>>(); | ||
var entryAssemblyMetadata = fixture.Freeze<Mock<IEntryAssemblyMetadata>>(); | ||
var sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); | ||
entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); | ||
entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); | ||
|
||
var before = sut.GetValue(); | ||
|
||
entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.2.0-rc"); | ||
sut = fixture.Create<UmbracoSmidgeConfigCacheBuster>(); | ||
|
||
var after = sut.GetValue(); | ||
|
||
Assert.AreNotEqual(before, after); | ||
} | ||
} | ||
} |
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