Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8701ed6
Add base Linux database compose stack
AGiorgetti Jul 11, 2026
859afb7
Add dynamic port compose override
AGiorgetti Jul 11, 2026
2214cfe
Add debug port compose override
AGiorgetti Jul 11, 2026
ef6f711
Add test port compose override
AGiorgetti Jul 11, 2026
203322b
Add Bash environment start script
AGiorgetti Jul 11, 2026
f33834d
Add Bash environment stop script
AGiorgetti Jul 11, 2026
df4e49b
Add PowerShell environment start script
AGiorgetti Jul 11, 2026
3679fac
Add PowerShell environment stop script
AGiorgetti Jul 11, 2026
5242af8
Load test connection strings from local dotenv file
AGiorgetti Jul 11, 2026
e08be44
Load dotenv values before resolving test connections
AGiorgetti Jul 11, 2026
88f4d79
Ignore generated local connection settings
AGiorgetti Jul 11, 2026
e4b6e6f
Remove legacy platform-specific start script
AGiorgetti Jul 11, 2026
5f623d7
Remove legacy platform-specific stop script
AGiorgetti Jul 11, 2026
8e0feaa
Remove legacy fixed-port Linux compose file
AGiorgetti Jul 11, 2026
7508840
Remove unsupported Windows-container compose file
AGiorgetti Jul 11, 2026
f3f39f8
Update VS Code Docker environment tasks
AGiorgetti Jul 11, 2026
5b4384c
Document isolated database environments
AGiorgetti Jul 11, 2026
7b29804
Document dotenv-based local test setup
AGiorgetti Jul 11, 2026
0d1f91e
Add fixed CI database ports
AGiorgetti Jul 11, 2026
10a2e2a
Reserve the CI environment in Bash startup
AGiorgetti Jul 11, 2026
1cef000
Reserve the CI environment in PowerShell startup
AGiorgetti Jul 11, 2026
3a66d58
Reserve the CI environment in Bash shutdown
AGiorgetti Jul 11, 2026
8b6cc74
Reserve the CI environment in PowerShell shutdown
AGiorgetti Jul 11, 2026
cabf6e0
Run GitHub Actions through the CI environment
AGiorgetti Jul 11, 2026
bda9e00
Invoke CI environment scripts through Bash
AGiorgetti Jul 11, 2026
36f95fa
Document the reserved CI environment
AGiorgetti Jul 11, 2026
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
121 changes: 10 additions & 111 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ concurrency:
cancel-in-progress: true

jobs:
# Keep the Windows build separate so we still validate the .NET Framework target
# and the packaging prerequisites that only exist on Windows runners.
build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -57,98 +55,22 @@ jobs:
run: dotnet restore ./src/NEventStore.Persistence.Sql.Core.sln --verbosity m

- name: Run GitVersion and patch assembly info
id: gitversion
shell: pwsh
working-directory: ${{ github.workspace }}
run: |
$gitVersion = dotnet tool run dotnet-gitversion /targetpath "${{ github.workspace }}" /output json /updateAssemblyInfo | ConvertFrom-Json
dotnet tool run dotnet-gitversion /targetpath "${{ github.workspace }}" /output json /updateAssemblyInfo | Out-Null
dotnet tool run dotnet-gitversion /targetpath "${{ github.workspace }}/dependencies/NEventStore" /updateAssemblyInfo | Out-Null
"semver=$($gitVersion.SemVer)" >> $env:GITHUB_OUTPUT

- name: Build solution
run: dotnet build ./src/NEventStore.Persistence.Sql.Core.sln -c Release --no-restore /p:ContinuousIntegrationBuild=True

# Tests run on Linux with database services (PostgreSQL, MySQL, SQLite).
# Each database provider runs independently to isolate failures and validate
# database-specific persistence logic.
test-sql-databases:
needs: build
name: Test (Linux, ${{ matrix.tfm }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Run each modern TFM independently so failures are isolated and easy to read.
tfm:
- net8.0
- net9.0
- net10.0

services:
sqlexpress:
image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
env:
SA_PASSWORD: Password12!
ACCEPT_EULA: Y
MSSQL_PID: Express
options: >-
--health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Password12!' -Q 'SELECT 1'"
--health-interval 20s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 1433:1433

postgresql:
image: postgres:15-alpine
env:
POSTGRES_DB: NEventStore
POSTGRES_USER: postgres
POSTGRES_PASSWORD: Password12!
options: >-
--health-cmd pg_isready
--health-interval 20s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 5432:5432

mysql:
image: mysql:8
env:
MYSQL_DATABASE: NEventStore
MYSQL_ROOT_PASSWORD: Password12!
options: >-
--health-cmd "mysqladmin ping -h localhost"
--health-interval 20s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 3306:3306

oracle:
image: gvenzl/oracle-xe
env:
ORACLE_ALLOW_REMOTE: true
ORACLE_PASSWORD: Password12!
options: >-
--health-cmd "sqlplus -L -S / as sysdba @/dev/null"
--health-interval 25s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 1521:1521

env:
NEventStore.MsSql: Server=localhost;Database=NEventStore;User Id=SA;Password=Password12!;TrustServerCertificate=True;
NEventStore.PostgreSql: Server=localhost;Database=NEventStore;Uid=postgres;Pwd=Password12!;Enlist=false;
NEventStore.MySql: Server=localhost;Database=NEventStore;Uid=root;Pwd=Password12!;AutoEnlist=false;
NEventStore.Sqlite: Data Source=:memory:;Cache=Shared;
NEventStore.Oracle: Data Source=localhost:1521/XE;User Id=system;Password=Password12!;Persist Security Info=True;
tfm: [net8.0, net9.0, net10.0]

steps:
- name: Checkout
Expand All @@ -174,46 +96,23 @@ jobs:
restore-keys: |
nuget-${{ runner.os }}-

- name: Create NEventStore database once SQL Server is healthy
- name: Start CI database environment
shell: bash
run: |
set -euo pipefail

# Find the SQL Server service container by ancestor image (more reliable in GH Actions)
container_id="$(/usr/bin/docker ps --filter "ancestor=mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04" --format "{{.ID}}" | head -n 1)"
if [ -z "$container_id" ]; then
echo "SQL Server service container not found."
/usr/bin/docker ps --format "{{.ID}} {{.Image}} {{.Names}}" || true
exit 1
fi

# Wait until container reports healthy
for i in $(seq 1 60); do
health_status="$(/usr/bin/docker inspect --format='{{.State.Health.Status}}' "$container_id" 2>/dev/null || echo starting)"
if [ "$health_status" = "healthy" ]; then
echo "SQL Server container healthy"
break
fi
echo "Waiting for SQL Server to be healthy: $health_status ($i/60)"
sleep 2
done

if [ "$health_status" != "healthy" ]; then
echo "SQL Server container is not healthy. Logs follow (last 200 lines):"
/usr/bin/docker logs "$container_id" --tail 200 || true
exit 1
fi

# Create database using sqlcmd inside the container
/usr/bin/docker exec "$container_id" /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password12!" -Q "IF DB_ID(N'NEventStore') IS NULL CREATE DATABASE [NEventStore];"
run: bash ./docker/start-environment.sh ci

- name: Run tests for ${{ matrix.tfm }}
run: dotnet test ./src/NEventStore.Persistence.Sql.Core.sln -c Release -f ${{ matrix.tfm }} --logger "trx;LogFileName=test-results-${{ matrix.tfm }}.trx"

- name: Upload test results
if: always()
uses: actions/upload-artifact@v7
with:
name: test-results-${{ matrix.tfm }}
path: "**/test-results-${{ matrix.tfm }}.trx"
if-no-files-found: ignore
retention-days: 14

- name: Stop CI database environment
if: always()
shell: bash
run: bash ./docker/stop-environment.sh ci --remove-data
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,5 @@ UpgradeLog*.XML

# Custom
artifacts/
.tokensave/
.tokensave/
.env
14 changes: 7 additions & 7 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
{
"label": "Docker Up",
"options": {
"cwd": "${workspaceFolder}/docker/"
"cwd": "${workspaceFolder}"
},
"type": "shell",
"command": "powershell",
"args": [
"-ExecutionPolicy",
"Bypass",
"-File",
"${workspaceFolder}/docker/DockerComposeUp.ps1",
"linux"
"${workspaceFolder}/docker/start-environment.ps1",
"debug"
],
"presentation": {
"echo": true,
Expand All @@ -26,16 +26,16 @@
{
"label": "Docker Down",
"options": {
"cwd": "${workspaceFolder}/docker/"
"cwd": "${workspaceFolder}"
},
"type": "shell",
"command": "powershell",
"args": [
"-ExecutionPolicy",
"Bypass",
"-File",
"${workspaceFolder}/docker/DockerComposeDown.ps1",
"linux"
"${workspaceFolder}/docker/stop-environment.ps1",
"debug"
],
"presentation": {
"echo": true,
Expand All @@ -56,4 +56,4 @@
"label": "dotnet: build"
}
]
}
}
51 changes: 27 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,32 @@ git submodule update

To build the project locally on a Windows Machine:

- Optional: update `.\src\.nuget\NEventStore.Persistence.Sql.nuspec` file if needed (before creating relase packages).
- Optional: update `.\src\.nuget\NEventStore.Persistence.Sql.nuspec` file if needed (before creating release packages).
- Open a Powershell console in Administrative mode and run the build script `build.ps1` in the root of the repository.

## How to Run Unit Tests (locally)

- Install Database engines or use Docker to run them in a container (you can use the scripts in `./docker` folder).
- Define the following environment variables:
Start the complete Linux-container database environment with one of the scripts under `docker/`:

```
NEventStore.MsSql="Server=localhost,50001;Database=NEventStore;User Id=sa;Password=Password1;TrustServerCertificate=True;"
NEventStore.MySql="Server=localhost;Port=50003;Database=NEventStore;Uid=sa;Pwd=Password1;AutoEnlist=false;"
NEventStore.PostgreSql="Server=localhost;Port=50004;Database=NEventStore;Uid=sa;Pwd=Password1;Enlist=false;"
NEventStore.Oracle="Data Source=localhost:50005/XE;User Id=system;Password=Password1;Persist Security Info=True;"
```
```powershell
./docker/start-environment.ps1 debug
```

```bash
./docker/start-environment.sh debug
```

The scripts generate a repository-root `.env` file containing the database connection strings. The test projects load that file automatically unless the corresponding process environment variables are already defined.

Dynamic environment names may be used for parallel worktrees and agents:

```bash
./docker/start-environment.sh issue-142
dotnet test ./src/NEventStore.Persistence.Sql.Core.sln
./docker/stop-environment.sh issue-142
```

See [`docker/Readme.md`](docker/Readme.md) for fixed ports, data removal, and environment isolation details.

## How to contribute

Expand All @@ -81,19 +93,19 @@ This repository uses GitFlow to develop, if you are not familiar with GitFlow yo

### Installing and configuring Git Flow

Probably the most straightforward way to install GitFlow on your machine is installing [Git Command Line](https://git-for-windows.github.io/), then install the [Visual Studio Plugin for Git-Flow](https://visualstudiogallery.msdn.microsoft.com/27f6d087-9b6f-46b0-b236-d72907b54683). This plugin is accessible from the **Team Explorer** menu and allows you to install GitFlow extension directly from Visual Studio with a simple click. The installer installs standard GitFlow extension both for command line and for Visual Studio Plugin.
Probably the most straightforward way to install GitFlow on your machine is installing [Git Command Line](https://git-for-windows.github.io/), then install the [Visual Studio Plugin for Git-Flow](https://visualstudiogallery.msdn.microsoft.com/27f6d087-9b6f-46b0-b236-d72907b54683). This plugin is accessible from the **Team Explorer** menu and allows you to install GitFlow extension directly from Visual Studio. The installer installs standard GitFlow extension both for command line and for Visual Studio Plugin.

Once installed you can use GitFlow right from Visual Studio or from Command line, which one you prefer.

### Build machine and GitVersion

Build machine uses [GitVersion](https://github.com/GitTools/GitVersion) to manage automatic versioning of assemblies and Nuget Packages. You need to be aware that there are a rule that does not allow you to directly commit on master, or the build will fail.
Build machine uses GitVersion to manage automatic versioning of assemblies and Nuget Packages. You need to be aware that there are a rule that does not allow you to directly commit on master, or the build will fail.

A commit on master can be done only following the [Git-Flow](http://nvie.com/posts/a-successful-git-branching-model/) model, as a result of a new release coming from develop, or with an hotfix.
A commit on master can be done only following the Git-Flow model, as a result of a new release coming from develop, or with an hotfix.

### Quick Info for NEventstore projects

Just clone the repository and from command line checkout develop branch with
Just clone the repository and from command line checkout develop branch with

```
git checkout develop
Expand All @@ -109,17 +121,8 @@ You can leave all values as default. Now your repository is GitFlow enabled.

### Note on Nuget version on Nuspec

Remember to update `.\src\.nuget\NEventStore.Persistence.Sql.nuspec` file if needed (before creating relase packages).
Remember to update `.\src\.nuget\NEventStore.Persistence.Sql.nuspec` file if needed (before creating release packages).

The .nuspec file is needed because the new `dotnet pack` command has problems dealing with ProjectReferences, submodules get the wrong version number.

While we are on develop branch, (suppose we just bumped major number so the driver version number is 6.0.0-unstablexxxx), we need to declare that this persistence driver depends from a version greater than the latest published. If the latest version of NEventStore 5.x.x wave iw 5.4.0 we need to declare this package dependency as

(5.4, 7)

This means, that we need a NEventStore greater than the latest published, but lesser than the next main version. This allows version 6.0.0-unstable of NEventStore to satisfy the dependency. We remember that prerelease package are considered minor than the stable package. Es.

5.4.0
5.4.1
6.0.0-unstable00001
6.0.0
While we are on develop branch, suppose we just bumped major number so the driver version number is 6.0.0-unstablexxxx. We need to declare that this persistence driver depends from a version greater than the latest published. If the latest version of NEventStore 5.x.x wave is 5.4.0 we need to declare that dependency as `(5.4, 7)`.
24 changes: 0 additions & 24 deletions docker/DockerComposeDown.ps1

This file was deleted.

21 changes: 0 additions & 21 deletions docker/DockerComposeUp.ps1

This file was deleted.

Loading
Loading