Skip to content

feat(domain-modeling): add domain events support and optimistic concu… #405

feat(domain-modeling): add domain events support and optimistic concu…

feat(domain-modeling): add domain events support and optimistic concu… #405

Workflow file for this run

name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
workflow_dispatch:
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_NOLOGO: true
DOTNET_SDK_VERSION: "10.0.x"
jobs:
# Build job - runs first, creates build artifacts for test jobs
build:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.*.props') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore
run: dotnet restore Encina.slnx
- name: Build
run: dotnet build Encina.slnx --configuration Release --no-restore
- name: Upload build artifacts
uses: actions/upload-artifact@v6
with:
name: build-output
path: |
**/bin/Release/**
**/obj/**/*.assets.json
retention-days: 1
# Unit tests - split into shards for parallel execution
test-unit:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
shard:
- name: Testing
filter: "FullyQualifiedName~Encina.UnitTests.Testing"
- name: Messaging
filter: "FullyQualifiedName~Encina.UnitTests.Messaging|FullyQualifiedName~Encina.UnitTests.Caching"
- name: Data
filter: "FullyQualifiedName~Encina.UnitTests.EntityFrameworkCore|FullyQualifiedName~Encina.UnitTests.Dapper|FullyQualifiedName~Encina.UnitTests.ADO|FullyQualifiedName~Encina.UnitTests.MongoDB|FullyQualifiedName~Encina.UnitTests.Marten"
- name: Cloud
filter: "FullyQualifiedName~Encina.UnitTests.AzureFunctions|FullyQualifiedName~Encina.UnitTests.AzureServiceBus|FullyQualifiedName~Encina.UnitTests.Polly|FullyQualifiedName~Encina.UnitTests.AwsLambda|FullyQualifiedName~Encina.UnitTests.Aspire|FullyQualifiedName~Encina.UnitTests.OpenTelemetry"
- name: Remaining
filter: "FullyQualifiedName~Encina.UnitTests.Core|FullyQualifiedName~Encina.UnitTests.DomainModeling|FullyQualifiedName~Encina.UnitTests.AspNetCore|FullyQualifiedName~Encina.UnitTests.gRPC|FullyQualifiedName~Encina.UnitTests.SignalR|FullyQualifiedName~Encina.UnitTests.GuardClauses|FullyQualifiedName~Encina.UnitTests.MQTT|FullyQualifiedName~Encina.UnitTests.NATS|FullyQualifiedName~Encina.UnitTests.RabbitMQ|FullyQualifiedName~Encina.UnitTests.AmazonSQS|FullyQualifiedName~Encina.UnitTests.Kafka|FullyQualifiedName~Encina.UnitTests.Workflows|FullyQualifiedName~Encina.UnitTests.MiniValidator|FullyQualifiedName~Encina.UnitTests.FluentValidation|FullyQualifiedName~Encina.UnitTests.DataAnnotations|FullyQualifiedName~Encina.UnitTests.Quartz|FullyQualifiedName~Encina.UnitTests.Hangfire|FullyQualifiedName~Encina.UnitTests.Extensions|FullyQualifiedName~Encina.UnitTests.Refit|FullyQualifiedName~Encina.UnitTests.Cli"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run Unit tests (${{ matrix.shard.name }})
run: |
dotnet test tests/Encina.UnitTests/Encina.UnitTests.csproj --no-build -c Release \
--filter "${{ matrix.shard.filter }}" \
--logger "console;verbosity=minimal" \
-- xunit.parallelizeTestCollections=true
continue-on-error: true
# Integration tests - split into shards for parallel execution and reduced disk usage
test-integration:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
shard:
- name: ADO
filter: "FullyQualifiedName~IntegrationTests.ADO"
- name: Dapper
filter: "FullyQualifiedName~IntegrationTests.Dapper"
- name: EFCore
filter: "FullyQualifiedName~IntegrationTests.Infrastructure"
steps:
- name: Free disk space
run: |
echo "=== Disk space before cleanup ==="
df -h /
sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.App/6.0.* || true
sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.App/7.0.* || true
sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.App/8.0.* || true
sudo rm -rf /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.* || true
sudo rm -rf /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.* || true
sudo rm -rf /usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.* || true
sudo rm -rf /usr/local/lib/android || true
sudo rm -rf /opt/ghc || true
sudo rm -rf /opt/hostedtoolcache/CodeQL || true
echo "=== Disk space after cleanup ==="
df -h /
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run Integration tests (${{ matrix.shard.name }})
run: |
dotnet test tests/Encina.IntegrationTests/Encina.IntegrationTests.csproj --no-build -c Release \
--filter "${{ matrix.shard.filter }}" \
--logger "console;verbosity=minimal" \
-- xunit.parallelizeTestCollections=true
continue-on-error: true
# Contract tests - consolidated project
test-contract:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run Contract tests
run: |
dotnet test tests/Encina.ContractTests/Encina.ContractTests.csproj --no-build -c Release \
--logger "console;verbosity=minimal"
continue-on-error: true
# Property tests - consolidated project
test-property:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run Property tests
run: |
dotnet test tests/Encina.PropertyTests/Encina.PropertyTests.csproj --no-build -c Release \
--logger "console;verbosity=minimal"
continue-on-error: true
# Guard tests - consolidated project
test-guard:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run Guard tests
run: |
dotnet test tests/Encina.GuardTests/Encina.GuardTests.csproj --no-build -c Release \
--logger "console;verbosity=minimal"
continue-on-error: true
# EF Core multi-provider integration tests
# Tests EF Core against all 4 database providers (Sqlite, SqlServer, PostgreSQL, MySQL)
# to ensure LINQ translation and provider-specific behavior works correctly across providers.
# MySQL tests are skipped until Pomelo.EntityFrameworkCore.MySql v10 is released.
# Note: Oracle was removed from pre-1.0 scope (see ADR-009)
test-ef-providers:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
database:
- name: Sqlite
# SQLite uses in-process database, no service container needed
trait: "Sqlite"
- name: SqlServer
trait: "SqlServer"
- name: PostgreSQL
trait: "PostgreSQL"
- name: MySQL
trait: "MySQL"
# Service containers for database providers (conditionally started based on matrix)
services:
sqlserver:
image: ${{ matrix.database.name == 'SqlServer' && 'mcr.microsoft.com/mssql/server:2022-latest' || '' }}
env:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: Encina_Test_123!
options: >-
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P Encina_Test_123! -C -Q 'SELECT 1' || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 10
ports:
- 1433:1433
postgres:
image: ${{ matrix.database.name == 'PostgreSQL' && 'postgres:16' || '' }}
env:
POSTGRES_USER: encina
POSTGRES_PASSWORD: encina_test
POSTGRES_DB: encina_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mysql:
image: ${{ matrix.database.name == 'MySQL' && 'mysql:8' || '' }}
env:
MYSQL_ROOT_PASSWORD: encina_test
MYSQL_DATABASE: encina_test
options: >-
--health-cmd "mysqladmin ping -h localhost"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 3306:3306
env:
# Connection strings for each database provider
ConnectionStrings__SqlServer: "Server=localhost,1433;Database=encina_test;User Id=sa;Password=Encina_Test_123!;TrustServerCertificate=true"
ConnectionStrings__PostgreSQL: "Host=localhost;Port=5432;Database=encina_test;Username=encina;Password=encina_test"
ConnectionStrings__MySQL: "Server=localhost;Port=3306;Database=encina_test;User=root;Password=encina_test"
ConnectionStrings__Sqlite: "Data Source=encina_test.db"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- uses: actions/download-artifact@v7
with:
name: build-output
- name: Run EF Core ${{ matrix.database.name }} tests
run: |
# Filter for EF Core tests with specific database trait
# Tests must have [Trait("Database", "{Provider}")] to be included
dotnet test tests/Encina.IntegrationTests/Encina.IntegrationTests.csproj --no-build -c Release \
--filter "FullyQualifiedName~EntityFrameworkCore&Database=${{ matrix.database.trait }}" \
--logger "console;verbosity=minimal" \
-- xunit.parallelizeTestCollections=true
continue-on-error: true
- name: Upload test results
if: always()
uses: actions/upload-artifact@v6
with:
name: ef-test-results-${{ matrix.database.name }}
path: artifacts/test-results
if-no-files-found: ignore
# Pack and publish - runs after all tests
pack:
needs:
- test-unit
- test-integration
- test-contract
- test-property
- test-guard
- test-ef-providers
runs-on: ubuntu-latest
timeout-minutes: 10
if: always() && needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.*.props') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Pack
run: dotnet pack src/Encina/Encina.csproj --configuration Release --output artifacts
- name: Upload package artifacts
uses: actions/upload-artifact@v6
with:
name: encina-nuget
path: artifacts/*.nupkg
- name: Publish to GitHub Packages
if: startsWith(github.ref, 'refs/tags/v')
env:
GITHUB_PACKAGES_SOURCE: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_API_KEY: ${{ secrets.GITHUB_TOKEN }}
run: |
dotnet nuget push artifacts/*.nupkg \
--source "$GITHUB_PACKAGES_SOURCE" \
--api-key "$NUGET_API_KEY" \
--skip-duplicate