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
168 changes: 84 additions & 84 deletions .github/workflows/dotnetpull.yml
Original file line number Diff line number Diff line change
@@ -1,84 +1,84 @@
name: .NET Pull Request
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: live-databases-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test (${{ matrix.database }})
runs-on: ubuntu-22.04
timeout-minutes: 35
strategy:
fail-fast: false
matrix:
database: [Unit, SQLite, SQLServer, PostgreSQL, Oracle, MySQL, MariaDB, Firebird, Db2, Informix, Sybase]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Start database
shell: bash
run: |
mkdir -p TestResults
bash .github/scripts/start-database.sh "${{ matrix.database }}" 2>&1 | tee TestResults/startup.log
timeout-minutes: 15
- name: Build
run: dotnet build Migrator.slnx -p:LiveDatabase=${{ matrix.database }}
- name: Configure native IBM drivers
if: matrix.database == 'Db2' || matrix.database == 'Informix'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y libaio1 libxml2 unixodbc libncurses5
output="$GITHUB_WORKSPACE/src/Migrator.Tests/bin/Debug/net9.0"
if [ "${{ matrix.database }}" = Db2 ]; then
echo "DB2_CLI_DRIVER_INSTALL_PATH=$output/clidriver" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$output/clidriver/lib" >> "$GITHUB_ENV"
else
echo "DELIMIDENT=y" >> "$GITHUB_ENV"
echo "INFORMIXDIR=$output/native" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$output/native/lib:$output/native/lib/cli:$output/native/lib/esql" >> "$GITHUB_ENV"
fi
- name: Test
shell: pwsh
run: ./.github/scripts/test.ps1 -Database ${{ matrix.database }}
- name: Collect database logs
if: always()
run: |
mkdir -p TestResults
if docker inspect migrator-db >/dev/null 2>&1; then
docker logs migrator-db > TestResults/database.log 2>&1
docker inspect migrator-db > TestResults/container.json
fi
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.database }}
path: TestResults/
if-no-files-found: error
- name: Remove test container
if: always()
run: |
if docker inspect migrator-db >/dev/null 2>&1; then
docker rm -fv migrator-db
fi
coverage:
name: Verify complete test coverage
needs: test
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
pattern: test-results-*
path: TestResults
- run: python3 .github/scripts/verify-test-coverage.py TestResults
name: .NET Pull Request
on:
push:
branches: [master]
pull_request:
branches: [master, "codex/**"]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: live-databases-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test (${{ matrix.database }})
runs-on: ubuntu-22.04
timeout-minutes: 35
strategy:
fail-fast: false
matrix:
database: [Unit, SQLite, SQLServer, PostgreSQL, Oracle, MySQL, MariaDB, Firebird, Db2, Informix, Sybase]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Start database
shell: bash
run: |
mkdir -p TestResults
bash .github/scripts/start-database.sh "${{ matrix.database }}" 2>&1 | tee TestResults/startup.log
timeout-minutes: 15
- name: Build
run: dotnet build Migrator.slnx -p:LiveDatabase=${{ matrix.database }}
- name: Configure native IBM drivers
if: matrix.database == 'Db2' || matrix.database == 'Informix'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y libaio1 libxml2 unixodbc libncurses5
output="$GITHUB_WORKSPACE/src/Migrator.Tests/bin/Debug/net9.0"
if [ "${{ matrix.database }}" = Db2 ]; then
echo "DB2_CLI_DRIVER_INSTALL_PATH=$output/clidriver" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$output/clidriver/lib" >> "$GITHUB_ENV"
else
echo "DELIMIDENT=y" >> "$GITHUB_ENV"
echo "INFORMIXDIR=$output/native" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$output/native/lib:$output/native/lib/cli:$output/native/lib/esql" >> "$GITHUB_ENV"
fi
- name: Test
shell: pwsh
run: ./.github/scripts/test.ps1 -Database ${{ matrix.database }}
- name: Collect database logs
if: always()
run: |
mkdir -p TestResults
if docker inspect migrator-db >/dev/null 2>&1; then
docker logs migrator-db > TestResults/database.log 2>&1
docker inspect migrator-db > TestResults/container.json
fi
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.database }}
path: TestResults/
if-no-files-found: error
- name: Remove test container
if: always()
run: |
if docker inspect migrator-db >/dev/null 2>&1; then
docker rm -fv migrator-db
fi
coverage:
name: Verify complete test coverage
needs: test
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
pattern: test-results-*
path: TestResults
- run: python3 .github/scripts/verify-test-coverage.py TestResults
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ billingMigrator.MigrateToLastVersion();

Important details:

- A scope partitions **history**, not migration discovery. Passing a mixed assembly does not automatically filter it by scope.
- Leave `MigrationAttribute.Scope` unset to inherit the provider scope. If you override it, it must align with the history the runner reads.
- Duplicate versions are checked across the runner's whole loaded migration set. Separate scopes do not permit duplicate versions within one runner.
- In the upgrade source, explicit scopes filter discovery; unscoped migrations inherit the runner scope. A scope partitions history, not database objects.
- Leave `MigrationAttribute.Scope` unset to inherit the provider scope; set it to select a migration for one specific scope.
- Duplicate versions are checked within the effective scope. Duplicate versions in distinct explicit scopes are independent.
- Scopes do not isolate tables or data. Module migrations still need compatible table names and coordinated schema ownership.

See [ProviderFactory](src/Migrator/ProviderFactory.cs), [MigrationLoader](src/Migrator/MigrationLoader.cs) and [history implementation](src/Migrator/Providers/TransformationProvider.cs).
Expand Down
149 changes: 69 additions & 80 deletions src/Migrator.Tests/MigrationLoaderTest.cs
Original file line number Diff line number Diff line change
@@ -1,80 +1,69 @@
using System.Reflection;
using DotNetProjects.Migrator;
using DotNetProjects.Migrator.Framework;
using DotNetProjects.Migrator.Framework.Loggers;
using NSubstitute;
using NUnit.Framework;

namespace Migrator.Tests;

[TestFixture]
public class MigrationLoaderTest
{
#region Setup/Teardown

[SetUp]
public void SetUp()
{
SetUpCurrentVersion(0, false);
}

#endregion

private MigrationLoader _migrationLoader;

private void SetUpCurrentVersion(int version, bool assertRollbackIsCalled)
{
var providerMock = Substitute.For<ITransformationProvider>();

providerMock.Logger = new Logger(false);
providerMock.When(x => x.Dispose()).Do(_ =>
{
if (assertRollbackIsCalled)
{
providerMock.Received().Rollback();
}
else
{
providerMock.DidNotReceive().Rollback();
}
});

_migrationLoader = new MigrationLoader(providerMock, Assembly.GetExecutingAssembly(), true);
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.FirstMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.SecondMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.ThirdMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.ForthMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.BadMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.SixthMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.NonIgnoredMigration));
}

[Test]
public void CheckForDuplicatedVersion()
{
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.FirstMigration));
Assert.Throws<DuplicatedVersionException>(() =>
{
_migrationLoader.CheckForDuplicatedVersion();
});
}

[Test]
public void LastVersion()
{
Assert.That(7, Is.EqualTo(_migrationLoader.LastVersion));
}

[Test]
public void NullIfNoMigrationForVersion()
{
Assert.That(_migrationLoader.GetMigration(99999999), Is.Null);
}

[Test]
public void ZeroIfNoMigrations()
{
_migrationLoader.MigrationsTypes.Clear();
Assert.That(0, Is.EqualTo(_migrationLoader.LastVersion));
}
}
using System.Reflection;
using DotNetProjects.Migrator;
using DotNetProjects.Migrator.Framework;
using DotNetProjects.Migrator.Framework.Loggers;
using NSubstitute;
using NUnit.Framework;

namespace Migrator.Tests;

[TestFixture]
public class MigrationLoaderTest
{
#region Setup/Teardown

[SetUp]
public void SetUp()
{
SetUpLoader();
}

#endregion

private MigrationLoader _migrationLoader;

private void SetUpLoader()
{
var providerMock = Substitute.For<ITransformationProvider>();

providerMock.Logger = new Logger(false);
_migrationLoader = new MigrationLoader(providerMock, Assembly.GetExecutingAssembly(), true);
_migrationLoader.MigrationsTypes.Clear();
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.FirstMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.SecondMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.ThirdMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.ForthMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.BadMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.SixthMigration));
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.NonIgnoredMigration));
}

[Test]
public void CheckForDuplicatedVersion()
{
_migrationLoader.MigrationsTypes.Add(typeof(MigratorTest.FirstMigration));
Assert.Throws<DuplicatedVersionException>(() =>
{
_migrationLoader.CheckForDuplicatedVersion();
});
}

[Test]
public void LastVersion()
{
Assert.That(7, Is.EqualTo(_migrationLoader.LastVersion));
}

[Test]
public void NullIfNoMigrationForVersion()
{
Assert.That(_migrationLoader.GetMigration(99999999), Is.Null);
}

[Test]
public void ZeroIfNoMigrations()
{
_migrationLoader.MigrationsTypes.Clear();
Assert.That(0, Is.EqualTo(_migrationLoader.LastVersion));
}
}
Loading
Loading