Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ bundle.min.css
/**/coverage*.xml
/CoverageReport/

# Upgrade Assistant backups
backups/

# MacOS
.DS_Store
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@
<ItemGroup Label="Tools">
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.57.0" />
<PackageVersion Include="Spectre.Console" Version="0.49.1" />
</ItemGroup>
</Project>
90 changes: 90 additions & 0 deletions LinkDotNet.Blog.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,40 +43,128 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{A931171C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinkDotNet.Blog.CriticalCSS", "tools\LinkDotNet.Blog.CriticalCSS\LinkDotNet.Blog.CriticalCSS.csproj", "{8CB83177-C078-4953-BC27-8968D2A6E0FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinkDotNet.Blog.UpgradeAssistant", "tools\LinkDotNet.Blog.UpgradeAssistant\LinkDotNet.Blog.UpgradeAssistant.csproj", "{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinkDotNet.Blog.UpgradeAssistant.Tests", "tests\LinkDotNet.Blog.UpgradeAssistant.Tests\LinkDotNet.Blog.UpgradeAssistant.Tests.csproj", "{8CD027B6-B188-4091-A1A0-FD678DF98C52}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|x64.ActiveCfg = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|x64.Build.0 = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|x86.ActiveCfg = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Debug|x86.Build.0 = Debug|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|Any CPU.Build.0 = Release|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|x64.ActiveCfg = Release|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|x64.Build.0 = Release|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|x86.ActiveCfg = Release|Any CPU
{6D6519BF-9265-488D-AA3B-C879F427930F}.Release|x86.Build.0 = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|x64.ActiveCfg = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|x64.Build.0 = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|x86.ActiveCfg = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Debug|x86.Build.0 = Debug|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|Any CPU.Build.0 = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|x64.ActiveCfg = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|x64.Build.0 = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|x86.ActiveCfg = Release|Any CPU
{18F8E09D-FF0B-4FF9-93A9-971A388D0E2A}.Release|x86.Build.0 = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|x64.ActiveCfg = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|x64.Build.0 = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|x86.ActiveCfg = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Debug|x86.Build.0 = Debug|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|Any CPU.Build.0 = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|x64.ActiveCfg = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|x64.Build.0 = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|x86.ActiveCfg = Release|Any CPU
{E8ED38D2-FCD3-473D-BD78-43EE78E08EE6}.Release|x86.Build.0 = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|x64.ActiveCfg = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|x64.Build.0 = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|x86.ActiveCfg = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Debug|x86.Build.0 = Debug|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|Any CPU.Build.0 = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|x64.ActiveCfg = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|x64.Build.0 = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|x86.ActiveCfg = Release|Any CPU
{5B868911-7C93-4190-AEE4-3A6694F2FFCE}.Release|x86.Build.0 = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|x64.ActiveCfg = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|x64.Build.0 = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|x86.ActiveCfg = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|x86.Build.0 = Debug|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|Any CPU.Build.0 = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|x64.ActiveCfg = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|x64.Build.0 = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|x86.ActiveCfg = Release|Any CPU
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|x86.Build.0 = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|x64.ActiveCfg = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|x64.Build.0 = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|x86.ActiveCfg = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|x86.Build.0 = Debug|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|Any CPU.Build.0 = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|x64.ActiveCfg = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|x64.Build.0 = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|x86.ActiveCfg = Release|Any CPU
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|x86.Build.0 = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|x64.ActiveCfg = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|x64.Build.0 = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|x86.ActiveCfg = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Debug|x86.Build.0 = Debug|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|Any CPU.Build.0 = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|x64.ActiveCfg = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|x64.Build.0 = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|x86.ActiveCfg = Release|Any CPU
{8CB83177-C078-4953-BC27-8968D2A6E0FE}.Release|x86.Build.0 = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|x64.ActiveCfg = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|x64.Build.0 = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|x86.ActiveCfg = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Debug|x86.Build.0 = Debug|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|Any CPU.Build.0 = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|x64.ActiveCfg = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|x64.Build.0 = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|x86.ActiveCfg = Release|Any CPU
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4}.Release|x86.Build.0 = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|x64.ActiveCfg = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|x64.Build.0 = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|x86.ActiveCfg = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Debug|x86.Build.0 = Debug|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|Any CPU.Build.0 = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|x64.ActiveCfg = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|x64.Build.0 = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|x86.ActiveCfg = Release|Any CPU
{8CD027B6-B188-4091-A1A0-FD678DF98C52}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -89,6 +177,8 @@ Global
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A} = {CAD2F4A3-1282-49B5-B0AB-655CDBED0A35}
{310ABEE1-C131-43E6-A759-F2DB75A483DD} = {CAD2F4A3-1282-49B5-B0AB-655CDBED0A35}
{8CB83177-C078-4953-BC27-8968D2A6E0FE} = {A931171C-22A6-4DB5-802B-67286B536BD2}
{B0C71EE4-FD6F-4879-9F83-AEB4FD5824E4} = {A931171C-22A6-4DB5-802B-67286B536BD2}
{8CD027B6-B188-4091-A1A0-FD678DF98C52} = {CAD2F4A3-1282-49B5-B0AB-655CDBED0A35}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB9B0642-F1F0-4BD8-9EDD-15C95F082180}
Expand Down
26 changes: 26 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
# Migration Guide
This document describes the changes that need to be made to migrate from one version of the blog to another.

## Automated Upgrade Assistant

Starting with version 12.0, we provide an **Upgrade Assistant** tool that automates most configuration migrations. This tool:
- Automatically detects your current configuration version
- Applies necessary transformations to `appsettings.json` files
- Creates backups before making changes
- Provides colorful console output with clear warnings and instructions

**Usage:**
```bash
# From your blog directory
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant

# Preview changes without applying
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant -- --dry-run

# See all options
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant -- --help
```

For detailed documentation, see [docs/Migrations/UpgradeAssistant.md](docs/Migrations/UpgradeAssistant.md).

**Note:** While the Upgrade Assistant handles most configuration changes automatically, some migrations still require manual steps (especially database schema changes). These are noted below.

---

## 11.0 to 12.0
`ShowBuildInformation` setting was added on the root level of the `appsettings.json` file. This setting controls whether build information (like build date) is shown in the `Footer` component.

Expand Down
2 changes: 2 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ This also includes source code snippets. Highlighting is done via [highlight.js]
- **About Me Page** - Customizable profile page that showcases skills and experience
- **RSS Feed** - Allow readers to subscribe to content updates
- **Visit Counter** - Get visitor counters for each blog post in the internal dashboard
- **Automated Configuration Migration** - Upgrade Assistant tool automatically migrates appsettings.json files between versions
- **Automated Database Migrations** - Seamless database schema updates using Entity Framework Migrations

## In Action

Expand Down
31 changes: 30 additions & 1 deletion docs/Migrations/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,33 @@ This is contrasted by Minor changes. These are things where the user does not ne

Breaking changes are recorded in the [MIGRATION.md](../../MIGRATION.md). Since version 9 of the blog, “Entity Framework Migrations” has been introduced for all SQL providers. You can read more in the [documentation](../Storage/Readme.md). In a nutshell, this means that database migration can be carried out easily via the “ef migration” CLI tool. More on this in the documentation linked above.

Changes for the appsettings.json must currently still be made manually. The exact changes that need to be made here can be found in MIGRATION.md.
Changes for the appsettings.json must currently still be made manually. The exact changes that need to be made here can be found in MIGRATION.md.

## Automated Configuration Migration (Version 12+)

Starting with **version 12**, the blog includes an **Automated Upgrade Assistant** that handles appsettings.json migrations automatically. This tool eliminates the need for manual configuration changes in most cases.

### What the Upgrade Assistant Does

- **Automatic Detection** - Detects your current configuration version
- **Sequential Migration** - Applies necessary migrations step-by-step
- **Safe Backups** - Creates timestamped backups before making any changes
- **Smart Filtering** - Skips version-controlled `appsettings.json`, only migrates environment-specific files
- **Colorful Output** - Provides clear, color-coded feedback about changes and warnings

### How to Use

Run the Upgrade Assistant from your blog directory:

```bash
# Preview changes without applying them
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant -- --dry-run

# Migrate all environment-specific appsettings files
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant

# Migrate a specific file
dotnet run --project tools/LinkDotNet.Blog.UpgradeAssistant -- --path appsettings.Production.json
```

For detailed documentation on the Upgrade Assistant, see [UpgradeAssistant.md](./UpgradeAssistant.md).
Loading