diff --git a/.github/workflows/gtc-assertion-ci-cd-nuget.yml b/.github/workflows/gtc-assertion-ci-cd-nuget.yml index 29e0636..0b7a287 100644 --- a/.github/workflows/gtc-assertion-ci-cd-nuget.yml +++ b/.github/workflows/gtc-assertion-ci-cd-nuget.yml @@ -5,47 +5,50 @@ on: branches: - main paths: - - .github/workflows/gtc-assertion-nuget.yml + - .github/workflows/gtc-assertion-ci-cd-nuget.yml - src/** push: branches: - - main + - main paths: - - .github/workflows/gtc-assertion-nuget.yml - - src/** + - .github/workflows/gtc-assertion-ci-cd-nuget.yml + - src/** workflow_dispatch: inputs: environment: - description: 'Environment to run' + description: "Environment to run" required: true - default: 'development' + default: "development" mode: - description: 'Running mode' + description: "Running mode" + required: true permissions: id-token: write contents: read security-events: write +env: + SCRIPTS_PATH: "./.github/scripts" + SRC_PATH: "./src" + PROJECT_PATH: "Goodtocode.Assertion" + PROJECT_FILE: "Goodtocode.Assertion.csproj" + SRC_SLN: "Goodtocode.Assertion.sln" + TEST_PATH: "Goodtocode.Assertion.Tests" + TEST_PROJECT: "Goodtocode.Assertion.Tests.csproj" + jobs: ci: - name: 'CI Build, Test, Code QL, Publish' + name: "CI Build, Test, Code QL, Publish" runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' - environment: development + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' + environment: development strategy: matrix: - DOTNET_VERSION: ['9.x'] - - env: - RUNTIME_ENV: 'Development' - SRC_PATH: './src' - SRC_SLN: 'Goodtocode.Assertion.sln' - PROJECT_PATH: 'Goodtocode.Assertion' - PROJECT_FILE: 'Goodtocode.Assertion.csproj' - TEST_PATH: 'Goodtocode.Assertion.Tests' - TEST_PROJECT: 'Goodtocode.Assertion.Tests.csproj' - SCRIPTS_PATH: './.github/scripts' + DOTNET_VERSION: ["9.x"] + + env: + RUNTIME_ENV: "Development" steps: - name: checkout @@ -58,24 +61,24 @@ jobs: - name: Set-Version.ps1 run: | - $version = ${{ env.SCRIPTS_PATH }}/ci/Set-Version.ps1 -Path ${{ env.SRC_PATH }} -VersionToReplace 1.0.0 + $version = ${{ env.SCRIPTS_PATH }}/ci/Set-Version.ps1 -Path ${{ env.SRC_PATH }} -VersionToReplace 1.0.0 -Major 1 -Minor 1 echo $version echo "VERSION=$version" >> $GITHUB_ENV shell: pwsh - - name: pipeline configuration secrets + - name: pipeline environment configuration run: | echo "ASPNETCORE_ENVIRONMENT=${{ env.RUNTIME_ENV }}" >> $GITHUB_ENV shell: pwsh - + - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: csharp - + - name: Build run: | - dotnet build ${{ env.SRC_PATH }}/${{ env.SRC_SLN }} --configuration Release + dotnet build ${{ env.SRC_PATH }}/${{ env.SRC_SLN }} --configuration Release shell: pwsh - name: Test @@ -84,6 +87,7 @@ jobs: dotnet test ${{ env.SRC_PATH }}/${{ env.TEST_PATH }}/${{ env.TEST_PROJECT }} --logger "trx;LogFileName=test_results.trx" --results-directory TestResults-${{ matrix.DOTNET_VERSION }} --verbosity normal shell: pwsh + - name: Upload test results uses: actions/upload-artifact@v4 with: @@ -91,44 +95,37 @@ jobs: path: TestResults-${{ matrix.DOTNET_VERSION }} if: ${{ always() }} - - name: Perform CodeQL Analysis + - name: Pack NuGet package + run: | + dotnet pack ${{ env.SRC_PATH }}/${{ env.PROJECT_PATH }}/${{ env.PROJECT_FILE }} --configuration Release --no-build --output nupkg_output + shell: pwsh + + - name: Upload NuGet package artifact + uses: actions/upload-artifact@v4 + with: + name: nuget-package + path: nupkg_output/*.nupkg + + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 cd: - name: 'CD Pack and Publish to NuGet.org' + name: "CD Pack and Publish to NuGet.org" runs-on: ubuntu-latest needs: ci - if: | - github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + if: github.event_name == 'push' && github.ref == 'refs/heads/main' environment: production strategy: matrix: - DOTNET_VERSION: ['9.x'] + DOTNET_VERSION: ["9.x"] env: - SRC_PATH: './src' - PROJECT_PATH: 'Goodtocode.Assertion' - PROJECT_FILE: 'Goodtocode.Assertion.csproj' - NUGET_OUTPUT: 'nupkg_output' + NUGET_OUTPUT: "nupkg_output" steps: - - name: checkout - uses: actions/checkout@v3 - - - name: Setup .NET ${{ matrix.DOTNET_VERSION }} - uses: actions/setup-dotnet@v4 + - name: Download NuGet package artifact + uses: actions/download-artifact@v4 with: - dotnet-version: ${{ matrix.DOTNET_VERSION }} - - - name: Restore dependencies - run: dotnet restore ${{ env.SRC_PATH }}/${{ env.PROJECT_PATH }}/${{ env.PROJECT_FILE }} - - - name: Build - run: dotnet build ${{ env.SRC_PATH }}/${{ env.PROJECT_PATH }}/${{ env.PROJECT_FILE }} --configuration Release --no-restore - - - name: Test - run: dotnet test ${{ env.SRC_PATH }}/${{ env.PROJECT_PATH }}/${{ env.PROJECT_FILE }} --configuration Release --no-build --verbosity normal - - - name: Pack NuGet package - run: dotnet pack ${{ env.SRC_PATH }}/${{ env.PROJECT_PATH }}/${{ env.PROJECT_FILE }} --configuration Release --no-build --output ${{ env.NUGET_OUTPUT }} + name: nuget-package + path: nupkg_output - name: Publish to NuGet.org - run: dotnet nuget push ${{ env.NUGET_OUTPUT }}/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate \ No newline at end of file + run: dotnet nuget push nupkg_output/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/README.md b/README.md index 0b662f4..a020a40 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,120 @@ -# aspect-assertion -Fluent Assertion aspect oriented library + +# Goodtocode.Assertion + +Fluent Assertion aspect-oriented library for .NET Standard 2.0+ + +[![CI/CD Build, Test and Deploy](https://github.com/goodtocode/aspect-assertion/actions/workflows/gtc-assertion-ci-cd-nuget.yml/badge.svg)](https://github.com/goodtocode/aspect-assertion/actions/workflows/gtc-assertion-ci-cd-nuget.yml) + +Goodtocode.Assertion is a .NET library providing fluent assertion and validation utilities for C# projects. It enables developers to write expressive, readable, and maintainable assertions for business logic, unit tests, and runtime validation. The library is designed for extensibility and can be integrated into any .NET Standard 2.0+ project. + +## Features +- Fluent assertion syntax for clear, readable code +- Customizable assertion rules and exception handling +- Assertion scopes for grouping related checks +- Lightweight, dependency-free, and compatible with .NET Standard 2.0+ +- Designed for use in both production code and unit tests + +## Quick-Start Steps +1. Clone this repository + ``` + git clone https://github.com/goodtocode/aspect-assertion.git + ``` +2. Install .NET SDK (latest recommended) + ``` + winget install Microsoft.DotNet.SDK --silent + ``` +3. Build the solution + ``` + cd src + dotnet build Goodtocode.Assertion.sln + ``` +4. Run tests + ``` + cd Goodtocode.Assertion.Tests + dotnet test + ``` + +## Install Prerequisites +- [.NET SDK (latest)](https://dotnet.microsoft.com/en-us/download) +- Visual Studio (latest) or VS Code + +## Top Use Case Examples + +### 1. Basic Assertion Scope +```csharp +using Goodtocode.Assertion; + +int value = 5; +AssertionScope.Begin() + .Assert(() => value > 0, "Value must be positive.") + .Assert(() => value < 10, "Value must be less than 10.") + .End(); +``` + +### 2. Validating Object Properties +```csharp +using Goodtocode.Assertion; + +var user = new User { Name = "Alice", Age = 30 }; +AssertionScope.Begin() + .Assert(() => !string.IsNullOrWhiteSpace(user.Name), "Name is required.") + .Assert(() => user.Age >= 18, "User must be an adult.") + .End(); +``` + +### 3. Custom Validator for Business Logic +```csharp +using Goodtocode.Assertion; + +public class GetMyUsersPaginatedQueryValidator : Validator +{ + public GetMyUsersPaginatedQueryValidator() + { + RuleFor(v => v.StartDate).NotEmpty() + .When(v => v.EndDate != null) + .LessThanOrEqualTo(v => v.EndDate); + + RuleFor(v => v.EndDate) + .NotEmpty() + .When(v => v.StartDate != null) + .GreaterThanOrEqualTo(v => v.StartDate); + + RuleFor(x => x.PageNumber).NotEqual(0); + RuleFor(x => x.PageSize).NotEqual(0); + } +} +``` + +### 4. Unit Test Assertion +```csharp +using Goodtocode.Assertion; +using Xunit; + +[Fact] +public void Should_Throw_When_Assertion_Fails() +{ + Assert.Throws(() => + AssertionScope.Begin() + .Assert(() => false, "This should fail.") + .End()); +} +``` + +## Technologies +- [C# .NET](https://docs.microsoft.com/en-us/dotnet/csharp/) +- [.NET Standard](https://docs.microsoft.com/en-us/dotnet/standard/) + +## Version History + + +| Version | Date | Release Notes | +|---------|-------------|--------------------------------------------------| +| 1.0.0 | 2026-Jan-19 | Initial release | + +## License + +This project is licensed with the [MIT license](https://mit-license.org/). + +## Contact +- [GitHub Repo](https://github.com/goodtocode/aspect-assertion) +- [@goodtocode](https://twitter.com/goodtocode) diff --git a/src/Goodtocode.Assertion/Goodtocode.Assertion.csproj b/src/Goodtocode.Assertion/Goodtocode.Assertion.csproj index 573d160..6bb6ba8 100644 --- a/src/Goodtocode.Assertion/Goodtocode.Assertion.csproj +++ b/src/Goodtocode.Assertion/Goodtocode.Assertion.csproj @@ -19,10 +19,12 @@ MIT Copyright © 2026 Goodtocode Goodtocode-icon.png + README.md + \ No newline at end of file