diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yaml similarity index 98% rename from .github/workflows/codeql-analysis.yml rename to .github/workflows/codeql-analysis.yaml index e0809e964..9ca614a88 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yaml @@ -31,9 +31,9 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 2.1.x 3.1.x 6.0.x + 8.0.x # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yaml similarity index 100% rename from .github/workflows/docs.yml rename to .github/workflows/docs.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/pipeline.yaml similarity index 65% rename from .github/workflows/ci.yml rename to .github/workflows/pipeline.yaml index 3132bb332..81928a531 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/pipeline.yaml @@ -1,23 +1,47 @@ -name: CI +name: pipeline on: - push: - branches: [ develop-v1 ] - pull_request: - branches: [ develop-v1 ] + workflow_call: + inputs: + # REQUIRED ============================ + version: + required: true + type: string + # OPTIONAL ============================ + bake-convention: + required: false + default: 'default' + type: string + bake-version: + required: false + type: string + default: '0.30.43-beta' + environment: + required: false + type: string + default: 'develop' + secrets: + nuget-api-key: + required: false jobs: build: - runs-on: ubuntu-20.04 + runs-on: + - ubuntu-20.04 + + environment: + name: ${{ inputs.environment }} + env: HELPZ_POSTGRESQL_PASS: Password12! EVENTFLOW_MSSQL_SERVER: 127.0.0.1,1433 EVENTFLOW_MSSQL_USER: sa - EVENTFLOW_MSSQL_PASS: Password12! + EVENTFLOW_MSSQL_PASS: Password12! + NUGET_APIKEY: ${{ secrets.nuget-api-key }} services: rabbitmq: - image: rabbitmq:3.12.0-management-alpine + image: rabbitmq:3-management-alpine env: RABBITMQ_DEFAULT_USER: guest RABBITMQ_DEFAULT_PASS: guest @@ -65,7 +89,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: + dotnet-version: | 3.1.x 6.0.x 8.0.x @@ -76,19 +100,20 @@ jobs: # https://github.com/rasmus/Bake - name: Install Bake - run: dotnet tool install -g --version 0.30.43-beta Bake + run: dotnet tool install -g --version ${{ inputs.bake-version }} Bake - name: Run Bake - run: | - declare -i REVISION - REVISION=5000+$GITHUB_RUN_NUMBER - bake run --build-version 1.0.$REVISION env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }} + run: | + bake run \ + --convention=${{ inputs.bake-convention }} \ + --build-version ${{ inputs.version }} \ + --destination="nuget>github,nuget,release>github" - name: Upload NuGet packages uses: actions/upload-artifact@v4 - if: success() || failure() + if: success() with: name: packages path: "**/*nupkg" diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml new file mode 100644 index 000000000..4b6b11c8e --- /dev/null +++ b/.github/workflows/pull-requests.yaml @@ -0,0 +1,16 @@ +name: pull-requests + +on: + push: + branches: [ develop-v1 ] + pull_request: + branches: [ develop-v1 ] + +permissions: + contents: read + +jobs: + pipeline: + uses: ./.github/workflows/pipeline.yaml + with: + version: "1.1.0-pr${{ github.event.number }}-b${{ github.run_number }}" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..de433d070 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,19 @@ +name: release + +on: + push: + branches: [ release-v1 ] + +permissions: + contents: write + packages: write + +jobs: + pipeline: + uses: ./.github/workflows/pipeline.yaml + with: + bake-convention: 'Release' + environment: 'release' + version: "1.1.0" + secrets: + nuget-api-key: ${{ secrets.NUGET_APIKEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 87a36b32e..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: Release - -on: - push: - branches: [ release-v1 ] - -permissions: - contents: write - packages: write - -jobs: - build: - runs-on: ubuntu-20.04 - - environment: - name: release - - env: - HELPZ_POSTGRESQL_PASS: Password12! - EVENTFLOW_MSSQL_SERVER: 127.0.0.1,1433 - EVENTFLOW_MSSQL_USER: sa - EVENTFLOW_MSSQL_PASS: Password12! - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_APIKEY: ${{ secrets.NUGET_APIKEY }} - - services: - rabbitmq: - image: rabbitmq:3-management-alpine - env: - RABBITMQ_DEFAULT_USER: guest - RABBITMQ_DEFAULT_PASS: guest - ports: - - 5672:5672 - - 15672:15672 - - eventstore: - image: eventstore/eventstore:release-4.1.3 - ports: - - "1113:1113" - - "2113:2113" - - postgres: - image: postgres:10 - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: Password12! - ports: - - "5432:5432" - - mssql: - image: mcr.microsoft.com/mssql/server:2017-latest - env: - ACCEPT_EULA: Y - SA_PASSWORD: Password12! - ports: - - "1433:1433" - - steps: - - name: Configure sysctl limits for Elasticsearch - run: | - sudo swapoff -a - sudo sysctl -w vm.swappiness=1 - sudo sysctl -w fs.file-max=262144 - sudo sysctl -w vm.max_map_count=262144 - - - name: Run Elasticsearch - uses: elastic/elastic-github-actions/elasticsearch@master - with: - stack-version: 6.8.3 - - - uses: actions/checkout@v3 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: - 3.1.x - 6.0.x - 8.0.x - - # Yes, EventFlow has a custom built build tool. If you are reading this - # you might have a better idea of how to do it alternatively, if so, - # create a PR for EventFlow. - - # https://github.com/rasmus/Bake - - name: Install Bake - run: dotnet tool install -g --version 0.30.43-beta Bake - - - name: Run Bake - run: | - declare -i REVISION - REVISION=5000+$GITHUB_RUN_NUMBER - bake run --convention=Release --build-version 1.0.$REVISION --destination="nuget>github,nuget,release>github" - - - name: Upload test results - uses: actions/upload-artifact@v4 - if: success() || failure() - with: - name: test-results - path: "**/*.trx" - if-no-files-found: error diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yaml similarity index 100% rename from .github/workflows/stale.yml rename to .github/workflows/stale.yaml diff --git a/.github/workflows/test-reports.yml b/.github/workflows/test-reports.yaml similarity index 89% rename from .github/workflows/test-reports.yml rename to .github/workflows/test-reports.yaml index c196d77dd..2e9570cfc 100644 --- a/.github/workflows/test-reports.yml +++ b/.github/workflows/test-reports.yaml @@ -1,10 +1,10 @@ -name: Test report +name: test reports + on: workflow_run: workflows: - - 'CI' - - 'Release' - 'pull-requests' + - 'release' types: - completed diff --git a/Documentation/getting-started.md b/Documentation/getting-started.md index 1401563b8..b39ac6372 100644 --- a/Documentation/getting-started.md +++ b/Documentation/getting-started.md @@ -179,10 +179,10 @@ public class ExampleEvent : AggregateEvent } ``` -We have applied the `[EventVersion("example", 1)]` to our event, marking it as the `example` event version `1`, which directly corresponds to the `event_name` and `event_version` from the metadata stored alongside the event mentioned. The information is used by EventFlow to tie the name and version to a specific .NET type. +We have applied the `[EventVersion("example", 1)]` to our event, marking it as the `example` event version `1`, which directly corresponds to the `event_name` and `event_version` from the metadata stored alongside the event mentioned. The information is used by EventFlow to tie the name and version to a specific .NET type. This is important when reading events from the event store as EventFlow needs to know which type to deserialize the event to. If an alternative default naming convention is needed, read our section on [event naming strategies](additional/event-naming-strategies.md). !!! warning - Even though using the `EventVersion` attribute is optional, it is **highly recommended**. EventFlow will infer the information if it isn't provided, thus making it vulnerable to type renames among other things. + Even though using the `EventVersion` attribute is optional, it is **highly recommended**. EventFlow will infer the information if it isn't provided, thus making it vulnerable to type renames among other things. Read our section on [event naming strategies](additional/event-naming-strategies.md) if an alternative default naming convention is needed. !!! danger Once you have aggregates in your production environment that have emitted an event, you should never change the .NET implementation of the event! You can deprecate it, but you should never change the type or the data stored in the event store. If the event type is changed, EventFlow will not be able to deserialize the event and can produce unexpected results when reading old aggregates. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e579b6e75..ba48f9b7a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,10 @@ -### New in 1.0 (not properly released yet) +### New in 1.1.0 (not released yet) + +* New: More control of event naming by introducing the interface `IEventNamingStrategy`, see the + updated documentation at https://geteventflow.net/additional/event-naming-strategies/ for more + information (thanks @SeWaS) + +### New in 1.0.5007 (released 2024-11-16) Read the complete migration guide to get the full list of changes as well as recommendations on how to do the migration. diff --git a/Test.runsettings b/Test.runsettings deleted file mode 100644 index a08ee59ed..000000000 --- a/Test.runsettings +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - nunit-output.html - - - - - - 0 - - \ No newline at end of file diff --git a/Update-FileHeaders.ps1 b/Update-FileHeaders.ps1 deleted file mode 100644 index d80317523..000000000 --- a/Update-FileHeaders.ps1 +++ /dev/null @@ -1,137 +0,0 @@ -$Script:ErrorActionPreference = 'Stop' - -$exclusions = @( - 'EventFlow\Core\AsyncHelper.cs' - 'EventFlow\Core\HashHelper.cs' - 'EventFlow\Logs\Internals\ImportedLibLog.cs' -) - -$defaultAuthors = @( - 'Rasmus Mikkelsen' - 'eBay Software Foundation' -) - -$files = Get-ChildItem -Path $PSScriptRoot -Directory -Recurse | - Where-Object { $_.FullName -notmatch '\\(bin|obj)(\\|$)' } | - Get-ChildItem -File -Filter *.cs | - Select-Object -ExpandProperty FullName - -$year = [datetime]::Now.Year - -function IsExcluded([string] $File) { - foreach ($exclusion in $exclusions) { - if ($File.EndsWith($exclusion)) { return $true } - } -} - -function CreateCopyright([string] $FromYear, [string] $Name) { - if ($FromYear -eq $year) { - "// Copyright (c) $year $Name" - } - else { - "// Copyright (c) $FromYear-$year $Name" - } -} - -function CreateHeader($Copyrights) { - @" -// The MIT License (MIT) -// -$(@($Copyrights | ForEach-Object { CreateCopyright $_.FromYear $_.Name }) -join "`r`n") -// https://github.com/eventflow/EventFlow -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -"@ -} - -function UpdateFileHeaders { - - $headerRegex = [regex]::new('^\s*\/\/ The MIT License .+(?:\n\/\/.*)+\s*', 'Compiled') - $copyrightRegex = [regex]::new('\/\/ Copyright \(c\) (\d{4})(?:-\d{4})? (.+)', 'Compiled') - - $defaultHeader = CreateHeader ($defaultAuthors | ForEach-Object { - [PSCustomObject]@{ - FromYear = 2015 - Name = $_ - } - }) - - foreach ($file in $files) { - if (IsExcluded $file) { continue } - - $content = Get-Content -Path $file -Raw - $headerMatch = $headerRegex.Match($content) - - $result = if ($headerMatch.Success) { - $currentHeader = $headerMatch.Value - $copyrightMatches = $copyrightRegex.Matches($currentHeader) - $copyrights = $copyrightMatches | ForEach-Object { - [PSCustomObject]@{ - FromYear = $_.Groups[1].Value - Name = $_.Groups[2].Value.Trim() - } - } - - $generatedHeader = CreateHeader($copyrights) - if ($generatedHeader -eq $currentHeader) { continue } - - $newContent = $generatedHeader + $content.Substring($headerMatch.Length) - - $currentLines = $currentHeader -split "`r`n" - $generatedLines = $generatedHeader -split "`r`n" - $differences = Compare-Object $currentLines $generatedLines | - Where-Object SideIndicator -EQ '<=' | - ForEach-Object { - [PSCustomObject]@{ - File = $file - Change = $_.InputObject - } - } - - [PSCustomObject]@{ - NewContent = $newContent - Differences = $differences - } - } - else { - [PSCustomObject]@{ - NewContent = $defaultHeader + $content.TrimStart() - Differences = @( - [PSCustomObject]@{ - File = $file - Change = "New header" - }) - } - } - - $result.NewContent | Set-Content -Path $file -NoNewline - $result.Differences - } -} - -UpdateFileHeaders | - Group-Object Change | - ForEach-Object { - [PSCustomObject]@{ - Count = $_.Count - Change = $_.Name - Files = $_.Group | Select-Object -ExpandProperty File - } - } \ No newline at end of file