diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
index 7be939e..b106b8e 100644
--- a/.github/workflows/format.yml
+++ b/.github/workflows/format.yml
@@ -15,7 +15,7 @@ on:
- develop
env:
- DOTNET_VERSION: '8.0.x'
+ DOTNET_VERSION: '9.0.x'
jobs:
format:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 2723bb2..bcc5980 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -8,7 +8,7 @@ on:
env:
BRANCH_NAME: ${{ github.event.release.target_commitish }}
SOLUTION_NAME: ${{ vars.SOLUTION_NAME }}
- DOTNET_VERSION: '8.0.x'
+ DOTNET_VERSION: '9.0.x'
NUGET_SOURCE: 'https://api.nuget.org/v3/index.json'
BUILD_CONFIGURATION: ''
VERSION_SUFFIX: ''
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 91f356f..23289f8 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -17,7 +17,7 @@ on:
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
SOLUTION_NAME: ${{ vars.SOLUTION_NAME }}
- DOTNET_VERSION: '8.0.x'
+ DOTNET_VERSION: '9.0.x'
jobs:
test:
diff --git a/Deploy GitHub Pages.yml b/Deploy GitHub Pages.yml
new file mode 100644
index 0000000..e69de29
diff --git a/Hyperbee.Migrations.sln b/Hyperbee.Migrations.sln
index 272e5e1..818ac02 100644
--- a/Hyperbee.Migrations.sln
+++ b/Hyperbee.Migrations.sln
@@ -54,12 +54,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\publish.yml = .github\workflows\publish.yml
.github\workflows\test-report.yml = .github\workflows\test-report.yml
.github\workflows\test.yml = .github\workflows\test.yml
+ unlist-nuget.yml = unlist-nuget.yml
+ update-version.yml = update-version.yml
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{FAE7F244-124F-4BCB-8EA6-049BEE4991B9}"
- ProjectSection(SolutionItems) = preProject
- todo.md = todo.md
- EndProjectSection
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "docs", "docs\docs.shproj", "{5A1580F9-6806-401E-9CAB-AC876DB070FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -130,9 +129,12 @@ Global
{C4B50B74-3FCA-453E-AF19-D9EA9233F8FC} = {17F0B438-3EBD-4566-9A22-7A5EC4AEAF3D}
{004E4E55-FA1C-49D0-865F-4FF238C7A1F3} = {5A09B7FE-D694-45B5-BCBC-256A8E06CFC5}
{A192B3D2-E452-4A85-BBA4-1A8499F1A056} = {004E4E55-FA1C-49D0-865F-4FF238C7A1F3}
- {FAE7F244-124F-4BCB-8EA6-049BEE4991B9} = {5A09B7FE-D694-45B5-BCBC-256A8E06CFC5}
+ {5A1580F9-6806-401E-9CAB-AC876DB070FD} = {5A09B7FE-D694-45B5-BCBC-256A8E06CFC5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {97071D77-035B-4126-AD4E-DE150E318714}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ docs\docs.projitems*{5a1580f9-6806-401e-9cab-ac876db070fd}*SharedItemsImports = 13
+ EndGlobalSection
EndGlobal
diff --git a/README.md b/README.md
index 077e8bf..829dfc6 100644
--- a/README.md
+++ b/README.md
@@ -55,12 +55,12 @@ public class PeopleHaveFullNames : Migration // #2 inherit from Migration
# Build Requirements
-* To build and run this project, **.NET 8 SDK** is required.
-* Ensure your development tools are compatible with .NET 8.
+* To build and run this project, **.NET 9 SDK** is required.
+* Ensure your development tools are compatible with .NET 9.
## Building the Solution
-* With .NET 8 SDK installed, you can build the solution using the standard `dotnet build` command.
+* With .NET 9 SDK installed, you can build the solution using the standard `dotnet build` command.
# Status
diff --git a/docs/.todo.md b/docs/.todo.md
new file mode 100644
index 0000000..ebb46dc
--- /dev/null
+++ b/docs/.todo.md
@@ -0,0 +1,14 @@
+# Things TODO
+
+* Dynamic provider loading
+* Option to specify provider through configuration and/or command line
+* Providers should have own startup/registration
+* Add Hyperbee.Migration.Providers.Mongodb
+ * Mongo bootstrapper
+ * Mongo distributed lock
+ * Mongo resource runner and basic statements.json parser
+* Relocate shared functionality for providers
+ * WaitHelper
+* Provider samples
+ * Rename Hyperbee.Migrations.Samples to Hyperbee.Migrations.Samples.Couchbase
+ * Create Hyperbee.Migrations.Samples.Mongodb
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000..b2be748
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,26 @@
+title: Hyperbee Migrations
+description: Documentation for Hyperbee Migrations.
+remote_theme: pmarsceill/just-the-docs
+baseurl: "/hyperbee.migrations/"
+url: "https://stillpoint-software.github.io"
+
+aux_links:
+ "GitHub Repository":
+ - "//github.com/Stillpoint-Software/hyperbee.migrations"
+
+footer_content: |
+
+
+# logo: "/assets/icon.png"
+search_enabled: true # Enable search
+
+# External navigation links
+nav_external_links:
+ - title: Stillpoint Software
+ url: https://www.stillpointsoftware.net/
+ opens_in_new_tab: true
diff --git a/docs/_includes/nav_footer_custom.html b/docs/_includes/nav_footer_custom.html
new file mode 100644
index 0000000..4ddba84
--- /dev/null
+++ b/docs/_includes/nav_footer_custom.html
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/docs/couchbase.md b/docs/couchbase.md
new file mode 100644
index 0000000..9ea8021
--- /dev/null
+++ b/docs/couchbase.md
@@ -0,0 +1,228 @@
+---
+layout: default
+title: Migrations Couchbase Provider
+nav_order: 2
+---
+
+# Hyperbee Migrations Couchbase Provider
+
+Welcome to `Hyperbee.Migrations.Providers.Couchbase`, an extension to the foundational `Hyperbee.Migrations` library. This extension is specifically designed to incorporate support for Couchbase.
+
+## Introduction
+
+The `Hyperbee.Migrations.Providers.Couchbase` library is an tool for developers seeking to perform database migrations in a Couchbase environment using the `Hyperbee.Migrations` library. This library furnishes a comprehensive suite of tools and functionalities that integrate effortlessly with `Hyperbee.Migrations`, thereby enabling developers to harness the robust capabilities of Couchbase in their applications.
+
+The `Hyperbee.Migrations.Providers.Couchbase` library is equipped to assist developers in creating, updating, and managing their Couchbase databases. With the aid of this library, developers can concentrate their efforts on the development of their application, while the library handles the intricacies of database management.
+
+We are committed to continuous improvement and feature enhancement. We appreciate your interest and look forward to your valuable feedback.
+
+Please see [Hyperbee Migrations' Read Me](index.md) for non-database specific usage.
+
+
+## Concepts
+
+Every migration has several elements you need to be aware of.
+
+* You can create a StartMethod method that resolves to **Task \**, in order to tell the runner when to start.
+* You can create a StopMethod method that resolves to **Task \**, in order to tell the runner when to stop.
+* You can set whether or not you want to journal the migration.
+
+## Configuration
+
+### Add Couchbase Services
+```c#
+// In Startup.cs
+public void ConfigureServices(IServiceCollection services)
+{
+ // Configure MongoDB
+ services.AddCouchbase();
+
+ // Add the MigrationRunner
+ services.AddCouchbaseMigrations(...);
+}
+
+public void Configure(IApplicationBuilder app, ...)
+{
+ // Run pending migrations.
+ var migrationService = app.ApplicationServices.GetRequiredService();
+ migrationService.Run();
+}
+```
+### Preventing simultaneous migrations
+
+By default, Hyperbee Migrations prevents parallel migration runner execution. If you have 2 instances of your
+app running, and both try to run migrations, Hyperbee Migrations will prevent the second instance from running
+migrations and will log a warning.
+
+Hyperbee Migrations accomplishes this by using a distributed lock at the database layer. The default
+implementation is based on the provider and uses a timeout and an auto-renewal interval to prevent orphaned locks.
+
+If you want to change this behavior you can override the default options:
+
+```c#
+services.AddCouchbaseMigrations( options =>
+{
+ // Locking is on by default. Set to false to allow simultaneous runners - but don't be that guy.
+ options.LockingEnabled = false;
+
+ // You can change locking behavior. Defaults shown.
+ options.LockMaxLifetime = TimeSpan.FromHours( 1 ); // max time-to-live
+ options.LockExpireInterval = TimeSpan.FromMinutes( 5 ); // expire heartbeat
+ options.LockRenewInterval = TimeSpan.FromMinutes( 2 ); // renewal heartbeat
+});
+```
+
+### Migrations
+Hyperbee Migrations relies on dependency injection to pass services to your migration.
+
+```c#
+[Migration(1)]
+public class MyMigration : Migration
+{
+ private IClusterProvider _clusterProvider;
+ private ILogger _logger;
+
+ // Injected services registered with the container
+ public MyMigration( IClusterProvider clusterProvider, ILogger logger )
+ {
+ _clusterProvider = clusterProvider;
+ _logger = logger;
+ }
+
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something with clusterProvider
+ }
+}
+```
+
+### Dependency Injection
+
+The MongoDB provider also provides a `MongoDBResourceRunner` that adds helpful functionality when using embedded resources.
+ - `StatementsFromAsync` run SQL++ (N1QL) statements for different bucket/scope/collections within Couchbase.
+ - `DocumentsFromAsync` Upserts documents into Couchbase. This is normally use for pre-seeding.
+ - `StartMethod` determines when the migration should start (optional)
+ - `StopMethod` determines when the migration should stop (optional)
+ - `false` determines if you want to journal (default = true)
+
+```c#
+[Migration(1, "StartMethod", "StopMethod", false)]
+public class MyMigration : Migration
+{
+ private readonly CouchbaseResourceRunner _resourceRunner;
+
+ public CreateInitialBuckets( CouchbaseResourceRunner resourceRunner )
+ {
+ _resourceRunner = resourceRunner;
+ }
+
+ public override async Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // run a `resource` migration to create initial buckets and state.
+ // resource migrations are atypical; prefer `n1ql` migrations.
+
+ await _resourceRunner.StatementsFromAsync( new[]
+ {
+ "statements.json",
+ "migrationbucket/statements.json"
+ },
+ cancellationToken
+ );
+
+ await _resourceRunner.DocumentsFromAsync( new[]
+ {
+ "migrationbucket/_default"
+ },
+ cancellationToken
+ );
+ }
+
+ public Task StartMethod()
+ {
+ //create process here
+ }
+
+ public Task StopMethod()
+ {
+ //create process here
+ }
+}
+```
+
+### Profiles
+
+There are times when you may want to scope migrations to specific environments. To allow this Hyperbee Migrations
+supports profiles. For instance, some migrations might only run during development. By decorating your migration
+with the profile of _"development"_ and setting **options** to include only that profile, you can control which
+migrations run in which environments.
+
+```c#
+[Migration(3, "development")]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+}
+
+...
+
+// In Startup.cs
+public void ConfigureServices( IServiceCollection services )
+{
+ services.AddCouchbaseMigrations( options =>
+ {
+ // Configure to only run development migrations
+ options.Profiles = new[] { "development" } };
+ });
+}
+```
+
+A migration may belong to multiple profiles.
+
+```c#
+[Migration(3, "development", "staging")]
+public class TargetedMigration : Migration
+{
+ // ...
+}
+```
+
+### Cron Settings
+```c#
+[Migration(3, "StartMethod", "StopMethod")]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+
+ public async Task StartMethod()
+ {
+ var helper = new MigrationCronHelper();
+ var results = await helper.CronDelayAsync( "* * * * *" );
+ return results;
+ }
+
+ public Task StopMethod()
+ {
+ var helper = new MigrationCronHelper();
+ var results = await helper.CronDelayAsync( "4 * * * *" );
+ return results;
+ }
+}
+```
+
+### Journaling
+Journaling is a bool indicator. Null indicates there are no start or stop methods.
+```c#
+[Migration(3, null, null, false)]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+}
\ No newline at end of file
diff --git a/docs/docs.projitems b/docs/docs.projitems
new file mode 100644
index 0000000..2885ed1
--- /dev/null
+++ b/docs/docs.projitems
@@ -0,0 +1,23 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 5a1580f9-6806-401e-9cab-ac876db070fd
+
+
+ docs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/docs.shproj b/docs/docs.shproj
new file mode 100644
index 0000000..9584ea4
--- /dev/null
+++ b/docs/docs.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 5a1580f9-6806-401e-9cab-ac876db070fd
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..419617d
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,81 @@
+---
+layout: default
+title: Hyperbee Migrations
+nav_order: 1
+---
+
+# Welcome to Hyperbee Migrations
+
+Hyperbee Migrations is a migration framework for .NET. Migrations are a structured way to alter your database
+schema and are an alternative to creating lots of database scripts that have to be run manually by every
+developer involved. Migrations solve the problem of evolving a database schema (and data) for multiple databases
+(for example, the developer's local database, the test database and the production database). Database changes
+are described in classes written in C# that can be checked into a version control system.
+
+
+The Cron Helper uses HangFire Cronos.
+
+## Features include:
+
+* Easy integration
+* Supports **Couchbase**, **MongoDB** and **Postgresql**
+* Preventing simultaneous migrations
+ * By default, Hyperbee Migrations prevents parallel migration runner execution.
+* Profiles
+ * There are times when you may want to scope migrations to specific environments.
+* A Record Store
+ * Keeps list of migrations that have completed
+* Local Solutions
+ * Run a migration locally
+* Run from Command Line
+ * Run a migration at the command line
+* Cron Helper
+ * Run a migration based on a start and stop criteria using a cron setting
+* Journaling
+ * You can determine whether or not to journal the migration
+
+## A Migration Example
+
+A migration looks like the following:
+
+```c#
+// #1 - specify the migration number
+[Migration(1)]
+public class PeopleHaveFullNames : Migration // #2 inherit from Migration
+{
+ // #3 do the migration
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ }
+
+ // #4 optional: undo the migration
+ public async override Task DownAsync( CancellationToken cancellationToken = default )
+ {
+ }
+}
+
+```
+## Getting Started
+
+To get started with Hyperbee.Migrations, refer to the documentation for detailed instructions and examples. Install the library via NuGet:
+
+Install via NuGet:
+
+```bash
+dotnet add package Hyperbee.Migrations
+```
+
+## Credits
+
+Hyperbee.Migrations framework API is heavily influenced by [Fluent Migrator](https://github.com/schambers/fluentmigrator), [Raven Migrations](https://github.com/migrating-ravens/RavenMigrations) and [DbUp](https://github.com/DbUp/DbUp). Special thanks to:
+
+- HangFire Cronos [HangFire Cronos](https://github.com/HangfireIO/Cronos)
+- Couchbase .Net Client & Couchbase Extentions DI [Couchbase .Net Client](https://github.com/couchbase/couchbase-net-client)
+- Raven Migrations [Raven Migrations](https://github.com/migrating-ravens/RavenMigrations)
+
+
+
+## Contributing
+
+We welcome contributions! Please see our [Contributing Guide](https://github.com/Stillpoint-Software/.github/blob/main/.github/CONTRIBUTING.md)
+for more details.
diff --git a/docs/migration-runner.md b/docs/migration-runner.md
new file mode 100644
index 0000000..4d23a36
--- /dev/null
+++ b/docs/migration-runner.md
@@ -0,0 +1,170 @@
+---
+layout: default
+title: Migrations Runner
+nav_order: 5
+---
+
+### The Runner
+
+At the heart of migrations is the **MigrationRunner**. The migration runner scans all provided assemblies for
+classes deriving from the **Migration** base class and then orders them according to their migration attribute
+value.
+
+After each migration is executed, a **MigrationRecord** is inserted into your database, unless no journaling is set. This ensures that the
+next time the runner is executed, previously completed migrations are not executed again. When a migration is
+rolled back the **MigrationRecord** is removed.
+
+You can modify the runner options by passing an action to the **.AddCouchbaseMigrations** call:
+
+```c#
+// In Startup.cs
+public void ConfigureServices( IServiceCollection services )
+{
+ services.AddCouchbaseMigrations( options =>
+ {
+ // Configure migration options
+ options.Direction = Direction.Down;
+ });
+}
+```
+
+### Profiles
+
+There are times when you may want to scope migrations to specific environments. To allow this Hyperbee Migrations
+supports profiles. For instance, some migrations might only run during development. By decorating your migration
+with the profile of _"development"_ and setting **options** to include only that profile, you can control which
+migrations run in which environments.
+
+```c#
+[Migration(3, null,null, true,"development")]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+}
+
+...
+
+// In Startup.cs
+public void ConfigureServices( IServiceCollection services )
+{
+ services.AddCouchbaseMigrations( options =>
+ {
+ // Configure to only run development migrations
+ options.Profiles = new[] { "development" } };
+ });
+}
+```
+
+A migration may belong to multiple profiles.
+
+```c#
+[Migration(3, null,null, true,"development", "staging")]
+public class TargetedMigration : Migration
+{
+ // ...
+}
+```
+
+This migration will run if either the **development** or the **stating** profile is specified in
+**MigrationOptions**.
+
+### The Record Store
+
+Hyperbee Migrations currently supports **Couchbase**, **MongoDB** & **Postgres** databases but it can easily be extended.
+The steps are:
+
+1. Derive from IMigrationRecordStore
+2. Derive from MigrationOptions to add any store specific configuration
+3. Implement ServiceCollectionExtensions to register your implementation
+
+See the one of the current implementations for reference.
+
+## Configure Local Solution
+
+To run the migration solution you will need to add some local configuration.
+
+`appsettings.developer.json`
+
+```json
+{
+ "Couchbase": {
+ "ConnectionString": "couchbase://localhost"
+ }
+}
+```
+
+`Manage User Secrets`
+
+```json
+{
+ "Couchbase:UserName": "Administrator",
+ "Couchbase:Password": "_YOUR_PASSWORD_"
+}
+```
+
+## Using Sample Runners
+
+Currently there is are [sample runners](../samples) for each of the database providers. These provider a simple console app that can be run using a command line or built into a docker image.
+
+### Running From The Command Line
+
+Once installed as a dotnet tool, the runner can be run from the command line. The runner expects, and will use settings
+from the `appSettings.json` in the execution folder. Arguments can also be provided from the command line.
+
+#### Command Line Options
+
+| Switch | Alias | Description |
+| ------ | ------------ | --------------------- |
+| -f | --file | From Paths Array |
+| -a | --assembly | From Assemblies Array |
+| -p | --profile | Profiles Array |
+| -b | --bucket | Bucket Name |
+| -s | --scope | Scope Name |
+| -c | --collection | Collection Name |
+| -usr | --user | Database User |
+| -pwd | --password | Database Password |
+| -cs | --connection | Database Connection String |
+
+#### Runtime Configuration
+
+```json
+{
+ "Couchbase": {
+ "ConnectionString": "__CONNECTION_STRING_HERE__",
+ "UserName": "__SECRET_HERE__",
+ "Password": "__SECRET_HERE__",
+ "MaxConnectionLimit": 20
+ },
+ "Migrations": {
+ "BucketName": "hyperbee",
+ "ScopeName": "migrations",
+ "CollectionName": "ledger",
+ "Lock": {
+ "Enabled": false,
+ "Name": "migration-runner-mutex",
+ "MaxLifetime": 3600,
+ "ExpireInterval": 300,
+ "RenewInterval": 120
+ },
+ "FromPaths": [
+ "c:\\my-migration-assembly.dll"
+ ],
+ "FromAssemblies": [
+ ]
+ },
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "Couchbase": "Warning",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information",
+ "System": "Warning"
+ }
+ }
+ }
+}
+```
diff --git a/docs/mongodb.md b/docs/mongodb.md
new file mode 100644
index 0000000..52faae0
--- /dev/null
+++ b/docs/mongodb.md
@@ -0,0 +1,157 @@
+---
+layout: default
+title: Migrations MongoDB Provider
+nav_order: 3
+---
+# Hyperbee Migrations MongoDB Provider
+
+Welcome to `Hyperbee.Migrations.Providers.MongoDB`, an extension to the foundational `Hyperbee.Migrations` library. This extension is specifically designed to incorporate support for MongoDB.
+
+## Introduction
+
+The `Hyperbee.Migrations.Providers.MongoDB` library is an tool for developers seeking to perform database migrations in a MongoDB environment using the `Hyperbee.Migrations` library. This library furnishes a comprehensive suite of tools and functionalities that integrate effortlessly with `Hyperbee.Migrations`, thereby enabling developers to harness the robust capabilities of MongoDB in their applications.
+
+The `Hyperbee.Migrations.Providers.MongoDB` library is equipped to assist developers in creating, updating, and managing their MongoDB databases. With the aid of this library, developers can concentrate their efforts on the development of their application, while the library handles the intricacies of database management.
+
+We are committed to continuous improvement and feature enhancement. We appreciate your interest and look forward to your valuable feedback.
+
+Please see [Hyperbee Migrations' Read Me](index.md) for non-database specific usage.
+
+
+## Concepts
+
+Every migration has several elements you need to be aware of.
+
+* You can create a StartMethod method that resolves to **Task \**, in order to tell the runner when to start.
+* You can create a StopMethod method that resolves to **Task \**, in order to tell the runner when to stop.
+* You can set whether or not you want to journal the migration.
+
+## Configuration
+
+### Add MongoDB Services
+```c#
+// In Startup.cs
+public void ConfigureServices(IServiceCollection services)
+{
+ // Configure MongoDB
+ services.AddTransient( _ => new MongoClient( connectionString ) );
+
+ // Add the MigrationRunner
+ services.AddMongoDBMigrations(...);
+}
+
+public void Configure(IApplicationBuilder app, ...)
+{
+ // Run pending migrations.
+ var migrationService = app.ApplicationServices.GetRequiredService();
+ migrationService.Run();
+}
+```
+### Preventing simultaneous migrations
+
+By default, Hyperbee Migrations prevents parallel migration runner execution. If you have 2 instances of your
+app running, and both try to run migrations, Hyperbee Migrations will prevent the second instance from running
+migrations and will log a warning.
+
+Hyperbee Migrations accomplishes this by using a distributed lock at the database layer. The default
+implementation is based on the provider and uses a timeout and an auto-renewal interval to prevent orphaned locks.
+
+If you want to change this behavior you can override the default options:
+
+```c#
+services.AddMongoDBMigrations( options =>
+{
+ // Locking is on by default. Set to false to allow simultaneous runners - but don't be that guy.
+ options.LockingEnabled = false;
+
+ // You can change locking behavior. Defaults shown.
+ options.LockMaxLifetime = TimeSpan.FromMinutes( 1 ); // max time-to-live
+ options.LockName = "ledger"
+});
+```
+
+### Migrations
+Hyperbee Migrations relies on dependency injection to pass services to your migration.
+
+```c#
+[Migration(1)]
+public class MyMigration : Migration
+{
+ private IClusterProvider _clusterProvider;
+ private ILogger _logger;
+
+ // Injected services registered with the container
+ public MyMigration( IClusterProvider clusterProvider, ILogger logger )
+ {
+ _clusterProvider = clusterProvider;
+ _logger = logger;
+ }
+
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something with clusterProvider
+ }
+}
+```
+
+### Dependency Injection
+
+Hyperbee Migrations relies on dependency injection to pass services to your migration. For MongoDB you can directly use the `IMongoClient` and interact with MongoDB directly.
+
+```c#
+[Migration(1)]
+public class MyMigration : Migration
+{
+ private IMongoClient _mongoClient;
+ private ILogger _logger;
+
+ // Injected services registered with the container
+ public MyMigration( IMongoClient mongoClient, ILogger logger )
+ {
+ _mongoClient = mongoClient;
+ _logger = logger;
+ }
+
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something with mongoClient
+ }
+}
+```
+
+The MongoDB provider also provides a `MongoDBResourceRunner` that adds helpful functionality when using embedded resources.
+ - `DocumentsFromAsync` inserts documents into database/collections within MongoDB. This is normally use for pre seeding the database.
+ - `StartMethod` determines when the migration should start (optional)
+ - `StopMethod` determines when the migration should stop (optional)
+ - `false` determines if you want to journal (default = true)
+
+```c#
+[Migration(1, "StartMethod", "StopMethod", false)]
+public class MyMigration : Migration
+{
+ private readonly MongoDBResourceRunner _resourceRunner;
+
+ public CreateInitialBuckets( MongoDBResourceRunner resourceRunner )
+ {
+ _resourceRunner = resourceRunner;
+ }
+
+ public override async Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // run a `resource` migration to create initial state.
+ await resourceRunner.DocumentsFromAsync( [
+ "administration/users/user.json"
+ ], cancellationToken );
+ }
+
+ public Task StartMethod()
+ {
+ //create process here
+ }
+
+ public Task StopMethod()
+ {
+ //create process here
+ }
+}
+```
\ No newline at end of file
diff --git a/docs/postgresql.md b/docs/postgresql.md
new file mode 100644
index 0000000..6cebe6b
--- /dev/null
+++ b/docs/postgresql.md
@@ -0,0 +1,212 @@
+---
+layout: default
+title: Migrations Postgres Provider
+nav_order: 4
+---
+
+# Hyperbee Migrations Postgres Provider
+
+Welcome to `Hyperbee.Migrations.Providers.Postgres`, an extension to the foundational `Hyperbee.Migrations` library. This extension is specifically designed to incorporate support for Postgres.
+
+## Introduction
+
+The `Hyperbee.Migrations.Providers.Postgres` library is an tool for developers seeking to perform database migrations in a Postgres environment using the `Hyperbee.Migrations` library. This library furnishes a comprehensive suite of tools and functionalities that integrate effortlessly with `Hyperbee.Migrations`, thereby enabling developers to harness the robust capabilities of Postgres in their applications.
+
+The `Hyperbee.Migrations.Providers.Postgres` library is equipped to assist developers in creating, updating, and managing their Postgres databases. With the aid of this library, developers can concentrate their efforts on the development of their application, while the library handles the intricacies of database management.
+
+We are committed to continuous improvement and feature enhancement. We appreciate your interest and look forward to your valuable feedback.
+
+Please see [Hyperbee Migrations' Read Me](index.md) for non-database specific usage.
+
+## Concepts
+
+Every migration has several elements you need to be aware of.
+
+* You can create a StartMethod method that resolves to **Task \**, in order to tell the runner when to start.
+* You can create a StopMethod method that resolves to **Task \**, in order to tell the runner when to stop.
+* You can set whether or not you want to journal the migration.
+
+## Configuration
+
+### Add Postgres Services
+```c#
+// In Startup.cs
+public void ConfigureServices(IServiceCollection services)
+{
+ // Configure Postgres
+ services.AddNpgsqlDataSource( connectionString );
+
+ // Add the MigrationRunner
+ services.AddPostgresMigrations(...);
+}
+
+public void Configure(IApplicationBuilder app, ...)
+{
+ // Run pending migrations.
+ var migrationService = app.ApplicationServices.GetRequiredService();
+ migrationService.Run();
+}
+```
+### Preventing simultaneous migrations
+
+By default, Hyperbee Migrations prevents parallel migration runner execution. If you have 2 instances of your
+app running, and both try to run migrations, Hyperbee Migrations will prevent the second instance from running
+migrations and will log a warning.
+
+Hyperbee Migrations accomplishes this by using a distributed lock at the database layer. The default
+implementation is based on the provider and uses a timeout and an auto-renewal interval to prevent orphaned locks.
+
+If you want to change this behavior you can override the default options:
+
+```c#
+services.AddPostgresDBMigrations( options =>
+{
+ // Locking is on by default. Set to false to allow simultaneous runners - but don't be that guy.
+ options.LockingEnabled = false;
+
+ // You can change locking behavior. Defaults shown.
+ options.LockMaxLifetime = TimeSpan.FromMinutes( 1 ); // max time-to-live
+ options.LockName = "ledger"
+});
+```
+
+### Migrations
+Hyperbee Migrations relies on dependency injection to pass services to your migration.
+
+```c#
+[Migration(1)]
+public class MyMigration : Migration
+{
+ private IClusterProvider _clusterProvider;
+ private ILogger _logger;
+
+ // Injected services registered with the container
+ public MyMigration( IClusterProvider clusterProvider, ILogger logger )
+ {
+ _clusterProvider = clusterProvider;
+ _logger = logger;
+ }
+
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something with clusterProvider
+ }
+}
+```
+
+### Dependency Injection
+The Postgres provider also provides a `PostgresResourceRunner` that adds helpful functionality when using embedded resources.
+ - `SqlFromAsync` runs sql statements and can do any sort of updates supported by Postgres
+ - `AllSqlFromAsync` runs all the embedded resources with the resource named matching the Migration. See [1000-Initial](../../samples/Hyperbee.Migrations.Postgres.Samples/Migrations/1000-Initial.cs) as an example
+ - `StartMethod` determines when the migration should start (optional)
+ - `StopMethod` determines when the migration should stop (optional)
+ - `false` determines if you want to journal (default = true)
+
+```c#
+[Migration(1, "StartMethod", "StopMethod", false)]
+public class MyMigration : Migration
+{
+ private readonly PostgresResourceRunner _resourceRunner;
+
+ public CreateInitialBuckets( PostgresResourceRunner resourceRunner )
+ {
+ _resourceRunner = resourceRunner;
+ }
+
+ public override async Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // run a `resource` migration to create initial state.
+ await resourceRunner.SqlFromAsync( [
+ "1-MyMigration.sql"
+ ], cancellationToken );
+ }
+
+ public Task StartMethod()
+ {
+ //create process here
+ }
+
+ public Task StopMethod()
+ {
+ //create process here
+ }
+}
+```
+
+### Profiles
+
+There are times when you may want to scope migrations to specific environments. To allow this Hyperbee Migrations
+supports profiles. For instance, some migrations might only run during development. By decorating your migration
+with the profile of _"development"_ and setting **options** to include only that profile, you can control which
+migrations run in which environments.
+
+```c#
+[Migration(3, "development")]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+}
+
+...
+
+// In Startup.cs
+public void ConfigureServices( IServiceCollection services )
+{
+ services.AddPostgresMigrations( options =>
+ {
+ // Configure to only run development migrations
+ options.Profiles = new[] { "development" } };
+ });
+}
+```
+
+A migration may belong to multiple profiles.
+
+```c#
+[Migration(3, "development", "staging")]
+public class TargetedMigration : Migration
+{
+ // ...
+}
+```
+
+### Cron Settings
+```c#
+[Migration(3, "StartMethod", "StopMethod")]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+
+ public async Task StartMethod()
+ {
+ var helper = new MigrationCronHelper();
+ var results = await helper.CronDelayAsync( "* * * * *" );
+ return results;
+ }
+
+ public Task StopMethod()
+ {
+ var helper = new MigrationCronHelper();
+ var results = await helper.CronDelayAsync( "4 * * * *" );
+ return results;
+ }
+}
+```
+
+### Journaling
+Journaling is a bool indicator. Null indicates there are no start or stop methods.
+```c#
+[Migration(3, null, null, false)]
+public class DevelopmentOnlyMigration : Migration
+{
+ public async override Task UpAsync( CancellationToken cancellationToken = default )
+ {
+ // do something nice for local developers
+ }
+}
\ No newline at end of file
diff --git a/samples/Hyperbee.MigrationRunner.Couchbase/Hyperbee.MigrationRunner.Couchbase.csproj b/samples/Hyperbee.MigrationRunner.Couchbase/Hyperbee.MigrationRunner.Couchbase.csproj
index 7404cb1..7b7605b 100644
--- a/samples/Hyperbee.MigrationRunner.Couchbase/Hyperbee.MigrationRunner.Couchbase.csproj
+++ b/samples/Hyperbee.MigrationRunner.Couchbase/Hyperbee.MigrationRunner.Couchbase.csproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net9.0
enable
false
diff --git a/samples/Hyperbee.MigrationRunner.MongoDB/Hyperbee.MigrationRunner.MongoDB.csproj b/samples/Hyperbee.MigrationRunner.MongoDB/Hyperbee.MigrationRunner.MongoDB.csproj
index 508f510..abdb570 100644
--- a/samples/Hyperbee.MigrationRunner.MongoDB/Hyperbee.MigrationRunner.MongoDB.csproj
+++ b/samples/Hyperbee.MigrationRunner.MongoDB/Hyperbee.MigrationRunner.MongoDB.csproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net9.0
enable
false
diff --git a/samples/Hyperbee.MigrationRunner.Postgres/Hyperbee.MigrationRunner.Postgres.csproj b/samples/Hyperbee.MigrationRunner.Postgres/Hyperbee.MigrationRunner.Postgres.csproj
index 848bf66..52d188e 100644
--- a/samples/Hyperbee.MigrationRunner.Postgres/Hyperbee.MigrationRunner.Postgres.csproj
+++ b/samples/Hyperbee.MigrationRunner.Postgres/Hyperbee.MigrationRunner.Postgres.csproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net9.0
enable
false
diff --git a/samples/Hyperbee.Migrations.Couchbase.Samples/Hyperbee.Migrations.Couchbase.Samples.csproj b/samples/Hyperbee.Migrations.Couchbase.Samples/Hyperbee.Migrations.Couchbase.Samples.csproj
index 7401407..8ad563f 100644
--- a/samples/Hyperbee.Migrations.Couchbase.Samples/Hyperbee.Migrations.Couchbase.Samples.csproj
+++ b/samples/Hyperbee.Migrations.Couchbase.Samples/Hyperbee.Migrations.Couchbase.Samples.csproj
@@ -1,6 +1,6 @@
- net8.0
+ net9.0
enable
false
diff --git a/samples/Hyperbee.Migrations.MongoDB.Samples/Hyperbee.Migrations.MongoDB.Samples.csproj b/samples/Hyperbee.Migrations.MongoDB.Samples/Hyperbee.Migrations.MongoDB.Samples.csproj
index 0c64413..6d6f949 100644
--- a/samples/Hyperbee.Migrations.MongoDB.Samples/Hyperbee.Migrations.MongoDB.Samples.csproj
+++ b/samples/Hyperbee.Migrations.MongoDB.Samples/Hyperbee.Migrations.MongoDB.Samples.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
false
diff --git a/samples/Hyperbee.Migrations.Postgres.Samples/Hyperbee.Migrations.Postgres.Samples.csproj b/samples/Hyperbee.Migrations.Postgres.Samples/Hyperbee.Migrations.Postgres.Samples.csproj
index ab3abbb..05fbe1b 100644
--- a/samples/Hyperbee.Migrations.Postgres.Samples/Hyperbee.Migrations.Postgres.Samples.csproj
+++ b/samples/Hyperbee.Migrations.Postgres.Samples/Hyperbee.Migrations.Postgres.Samples.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
false
diff --git a/src/Hyperbee.Migrations.Providers.Couchbase/Hyperbee.Migrations.Providers.Couchbase.csproj b/src/Hyperbee.Migrations.Providers.Couchbase/Hyperbee.Migrations.Providers.Couchbase.csproj
index ec658cc..1506b60 100644
--- a/src/Hyperbee.Migrations.Providers.Couchbase/Hyperbee.Migrations.Providers.Couchbase.csproj
+++ b/src/Hyperbee.Migrations.Providers.Couchbase/Hyperbee.Migrations.Providers.Couchbase.csproj
@@ -1,6 +1,6 @@
- net8.0
+ net9.0
Hyperbee.Migrations.Providers.Couchbase
enable
true
@@ -10,7 +10,7 @@
icon.png
https://github.com/Stillpoint-Software/Hyperbee.Migrations/
https://github.com/Stillpoint-Software/Hyperbee.Migrations/releases/latest
- net8.0
+ net9.0
LICENSE
Stillpoint Software, Inc.
Hyperbee Migrations
diff --git a/src/Hyperbee.Migrations.Providers.MongoDB/Hyperbee.Migrations.Providers.MongoDB.csproj b/src/Hyperbee.Migrations.Providers.MongoDB/Hyperbee.Migrations.Providers.MongoDB.csproj
index 8e5212b..750d929 100644
--- a/src/Hyperbee.Migrations.Providers.MongoDB/Hyperbee.Migrations.Providers.MongoDB.csproj
+++ b/src/Hyperbee.Migrations.Providers.MongoDB/Hyperbee.Migrations.Providers.MongoDB.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
Hyperbee.Migrations.Providers.MongoDB
enable
true
@@ -11,7 +11,7 @@
icon.png
https://github.com/Stillpoint-Software/Hyperbee.Migrations/
https://github.com/Stillpoint-Software/Hyperbee.Migrations/releases/latest
- net8.0
+ net9.0
LICENSE
Stillpoint Software, Inc.
Hyperbee Migrations
diff --git a/src/Hyperbee.Migrations.Providers.Postgres/Hyperbee.Migrations.Providers.Postgres.csproj b/src/Hyperbee.Migrations.Providers.Postgres/Hyperbee.Migrations.Providers.Postgres.csproj
index 26c2384..2850bbe 100644
--- a/src/Hyperbee.Migrations.Providers.Postgres/Hyperbee.Migrations.Providers.Postgres.csproj
+++ b/src/Hyperbee.Migrations.Providers.Postgres/Hyperbee.Migrations.Providers.Postgres.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
Hyperbee.Migrations.Providers.Postgres
enable
true
@@ -11,7 +11,7 @@
icon.png
https://github.com/Stillpoint-Software/Hyperbee.Migrations/
https://github.com/Stillpoint-Software/Hyperbee.Migrations/releases/latest
- net8.0
+ net9.0
LICENSE
Stillpoint Software, Inc.
Hyperbee Migrations
diff --git a/src/Hyperbee.Migrations/Hyperbee.Migrations.csproj b/src/Hyperbee.Migrations/Hyperbee.Migrations.csproj
index d24e833..7e9e963 100644
--- a/src/Hyperbee.Migrations/Hyperbee.Migrations.csproj
+++ b/src/Hyperbee.Migrations/Hyperbee.Migrations.csproj
@@ -1,6 +1,6 @@
- net8.0
+ net9.0
Hyperbee.Migrations
enable
true
@@ -10,7 +10,7 @@
icon.png
https://github.com/Stillpoint-Software/Hyperbee.Migrations/
https://github.com/Stillpoint-Software/Hyperbee.Migrations/releases/latest
- net8.0
+ net9.0
LICENSE
Stillpoint Software, Inc.
Hyperbee Migrations
diff --git a/tests/Hyperbee.Migrations.Integration.Tests/Hyperbee.Migrations.Integration.Tests.csproj b/tests/Hyperbee.Migrations.Integration.Tests/Hyperbee.Migrations.Integration.Tests.csproj
index b015d0d..de898d4 100644
--- a/tests/Hyperbee.Migrations.Integration.Tests/Hyperbee.Migrations.Integration.Tests.csproj
+++ b/tests/Hyperbee.Migrations.Integration.Tests/Hyperbee.Migrations.Integration.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
diff --git a/tests/Hyperbee.Migrations.Tests/Hyperbee.Migrations.Tests.csproj b/tests/Hyperbee.Migrations.Tests/Hyperbee.Migrations.Tests.csproj
index fa484b2..668ea99 100644
--- a/tests/Hyperbee.Migrations.Tests/Hyperbee.Migrations.Tests.csproj
+++ b/tests/Hyperbee.Migrations.Tests/Hyperbee.Migrations.Tests.csproj
@@ -1,6 +1,6 @@
- net8.0
+ net9.0
false
enable
diff --git a/tests/Hyperbee.Migrations.Tests/StatementTests.cs b/tests/Hyperbee.Migrations.Tests/StatementTests.cs
index 53d2c3b..27d9820 100644
--- a/tests/Hyperbee.Migrations.Tests/StatementTests.cs
+++ b/tests/Hyperbee.Migrations.Tests/StatementTests.cs
@@ -31,8 +31,8 @@ public static IEnumerable GetStatements( string resourceName )
var node = JsonNode.Parse( json );
return node!["statements"]!.AsArray()
- .Select( e => e["statement"]?.ToString() )
- .Where( x => x != null );
+ .Select( e => e!["statement"]?.ToString() )
+ .Where( x => x != null )!;
}
public static string GetResource( string fullyQualifiedName )
diff --git a/unlist-nuget.yml b/unlist-nuget.yml
new file mode 100644
index 0000000..4c11c1b
--- /dev/null
+++ b/unlist-nuget.yml
@@ -0,0 +1,26 @@
+name: Unlist NuGet
+
+on:
+ workflow_dispatch:
+ # release:
+ # types: [deleted]
+
+env:
+ BRANCH_NAME: ${{ github.event.release.target_commitish }}
+ PROJECT_NAME: ${{ vars.PROJECT_NAME }}
+
+jobs:
+ publish:
+ name: unlist on nuget
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ # Unlist
+ - name: Unlist Deleted Tag
+ uses: darenm/unlist-nuget@v1
+ with:
+ NUGET_PACKAGE: ${{ env.PROJECT_NAME }} # Full Package ID
+ VERSION_REGEX: ${{ github.event.release.tag_name }} # Regex pattern to match version
+ NUGET_KEY: ${{ secrets.NUGET_API_KEY }} # nuget.org API key
\ No newline at end of file
diff --git a/update-version.yml b/update-version.yml
new file mode 100644
index 0000000..bfa87ba
--- /dev/null
+++ b/update-version.yml
@@ -0,0 +1,78 @@
+name: Update Version
+
+on:
+ workflow_dispatch:
+ inputs:
+ version_type:
+ description: 'Update branch version by:'
+ type: choice
+ options:
+ - major
+ - minor
+ - patch
+ required: true
+ default: 'patch'
+
+env:
+ ALLOW_UPDATES: ${{ startsWith(github.ref, 'refs/heads/develop') || startsWith(github.ref, 'refs/heads/hotfix/') }}
+
+jobs:
+ update-version:
+ runs-on: ubuntu-latest
+ outputs:
+ version_tag: ${{ env.version_tag }}
+ previous_version_tag: ${{ env.previous_version_tag }}
+
+ steps:
+ - name: Check For Valid Updates
+ if: env.ALLOW_UPDATES == false
+ run: |
+ echo "Version updates should only be done on development or hotfix"
+ exit 1
+
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Run Update Version
+ id: set_version
+ shell: pwsh
+ run: |
+ Import-Module ./solution-helper.psm1 -Force
+ $previousVersion, $newVersion = Update-Version -type ${{ github.event.inputs.version_type }}
+ echo "version_tag=$newVersion" | Out-File -FilePath $env:GITHUB_ENV -Append
+ echo "previous_version_tag=$previousVersion" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - name: Check for Existing Release
+ run: |
+ compare_versions() {
+ echo -e "$1\n$2" | sort -V | tail -n 1
+ }
+
+ # Fetch the list of releases
+ releases=$(gh release list --json createdAt,tagName --limit 100)
+ echo -e "$releases"
+
+ # Sort the releases by date and extract the most recent one
+ latest_release=$(echo "$releases" | jq -r 'sort_by(.createdAt) | reverse | .[0] | .tagName')
+ echo -e "$latest_release"
+
+ greater_version=$(compare_versions $latest_release $version_tag)
+
+ if [ "$greater_version" = "$version_tag" ]; then
+ echo "✅ $version_tag is greater than $latest_release"
+ elif [ "$greater_version" = "$latest_release" ]; then
+ echo "⛔ $version_tag is less than $latest_release"
+ exit 1
+ else
+ echo "⚠️ Versions are equal"
+ exit 1
+ fi
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Update Version Number
+ run: |
+ git config --global user.name '${{ github.triggering_actor }}'
+ git config --global user.email '${{ github.triggering_actor }}@users.noreply.github.com'
+ git commit -am "Previous version was '${{ env.previous_version_tag }}'. Version now '${{ env.version_tag }}'."
+ git push
\ No newline at end of file