fix: reject stale session belonging to different user in StartSession… #68
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI — Build, Test & Security | |
| on: | |
| push: | |
| branches: [master, develop] | |
| pull_request: | |
| branches: [master] | |
| workflow_dispatch: | |
| env: | |
| DOTNET_VERSION: '8.0.x' | |
| DOTNET_NOLOGO: 'true' | |
| DOTNET_CLI_TELEMETRY_OPTOUT: 'true' | |
| # Cancel in-progress CI runs for the same branch/PR to save runner minutes | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ── 1. Build & Test ────────────────────────────────────────────────────────── | |
| build-and-test: | |
| name: Build & Test (.NET ${{ matrix.dotnet }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| dotnet: ['8.0.x'] | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_DB: aqlliagronom_test | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: ci_test_password_123 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7-alpine | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET ${{ matrix.dotnet }} | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ matrix.dotnet }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore SmartAgronom.sln | |
| - name: Build (Release) | |
| run: > | |
| dotnet build SmartAgronom.sln | |
| --configuration Release | |
| --no-restore | |
| - name: Run tests | |
| run: > | |
| dotnet test SmartAgronom.sln | |
| --configuration Release | |
| --no-build | |
| --verbosity normal | |
| --logger "trx;LogFileName=test-results.trx" | |
| --collect:"XPlat Code Coverage" | |
| --results-directory "${{ github.workspace }}/test-results" | |
| env: | |
| ASPNETCORE_ENVIRONMENT: Testing | |
| ConnectionStrings__PostgreSQL: >- | |
| Host=localhost;Port=5432;Database=aqlliagronom_test; | |
| Username=postgres;Password=ci_test_password_123 | |
| Redis__ConnectionString: "localhost:6379" | |
| Qdrant__Host: "localhost" | |
| Jwt__SecretKey: "ci_only_secret_key_min_256_bits_padding_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | |
| Claude__ApiKey: "test_key" | |
| Embedding__ApiKey: "test_key" | |
| Telegram__BotToken: "123456789:test_token" | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ github.run_number }} | |
| path: ${{ github.workspace }}/test-results/**/*.trx | |
| retention-days: 14 | |
| - name: Upload code coverage | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report-${{ github.run_number }} | |
| path: ${{ github.workspace }}/test-results/**/coverage.cobertura.xml | |
| retention-days: 14 | |
| # ── 2. Security Scan (filesystem) ──────────────────────────────────────────── | |
| security-scan: | |
| name: Security Scan (Trivy) | |
| runs-on: ubuntu-latest | |
| needs: build-and-test | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy filesystem scan | |
| uses: aquasecurity/[email protected] | |
| with: | |
| scan-type: fs | |
| scan-ref: . | |
| format: sarif | |
| output: trivy-fs.sarif | |
| severity: CRITICAL,HIGH | |
| exit-code: '0' # Report only, don't fail CI | |
| - name: Upload Trivy results to GitHub Security tab | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: trivy-fs.sarif | |
| # ── 3. Docker Build & Image Security Scan ──────────────────────────────────── | |
| docker-build-verify: | |
| name: Docker Build & Image Scan | |
| runs-on: ubuntu-latest | |
| needs: build-and-test | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image (no push) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: aqlliagronom-api:ci-${{ github.sha }} | |
| build-args: | | |
| BUILD_VERSION=0.0.0-ci | |
| BUILD_REVISION=${{ github.sha }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Scan Docker image with Trivy | |
| uses: aquasecurity/[email protected] | |
| with: | |
| image-ref: aqlliagronom-api:ci-${{ github.sha }} | |
| format: table | |
| severity: CRITICAL,HIGH | |
| ignore-unfixed: true # Skip CVEs with no available fix (base OS packages) | |
| exit-code: '1' # Fail CI only if a FIXABLE critical/high CVE exists | |
| - name: Verify container entrypoint | |
| run: | | |
| docker run --rm \ | |
| --entrypoint dotnet \ | |
| aqlliagronom-api:ci-${{ github.sha }} \ | |
| --info | |
| echo "Container entrypoint verification passed." |