Bump coverlet.collector from 6.0.2 to 10.0.0 #25
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 | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| backend: | |
| name: Backend (.NET) | |
| runs-on: ubuntu-latest | |
| services: | |
| sqlserver: | |
| image: mcr.microsoft.com/azure-sql-edge:1.0.7 | |
| env: | |
| ACCEPT_EULA: "Y" | |
| MSSQL_SA_PASSWORD: Strong!Passw0rd | |
| MSSQL_PID: Developer | |
| ports: | |
| - 1433:1433 | |
| options: >- | |
| --health-cmd "timeout 3 bash -c 'exec 3<>/dev/tcp/localhost/1433' 2>/dev/null" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| --health-start-period 30s | |
| redis: | |
| image: redis:7-alpine | |
| ports: | |
| - 6379:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 3s | |
| --health-retries 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: 8.0.x | |
| - name: Restore | |
| run: dotnet restore backend/CCE.sln | |
| - name: Build | |
| run: dotnet build backend/CCE.sln --no-restore --nologo -c Debug | |
| - name: Apply EF migrations | |
| env: | |
| CCE_DESIGN_SQL_CONN: "Server=localhost,1433;Database=CCE;User Id=sa;Password=Strong!Passw0rd;TrustServerCertificate=true;" | |
| run: | | |
| dotnet tool install --global dotnet-ef --version 8.0.10 | |
| export PATH="$PATH:$HOME/.dotnet/tools" | |
| dotnet ef database update \ | |
| --project backend/src/CCE.Infrastructure/CCE.Infrastructure.csproj \ | |
| --context CceDbContext \ | |
| --msbuildprojectextensionspath backend/artifacts/obj/CCE.Infrastructure | |
| - name: Test | |
| env: | |
| ASPNETCORE_ENVIRONMENT: Development | |
| Infrastructure__SqlConnectionString: "Server=localhost,1433;Database=CCE;User Id=sa;Password=Strong!Passw0rd;TrustServerCertificate=true;" | |
| Infrastructure__RedisConnectionString: "localhost:6379" | |
| run: dotnet test backend/CCE.sln --no-build --nologo --logger "trx;LogFileName=test-results.trx" | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: backend-test-results | |
| path: backend/**/TestResults/*.trx | |
| frontend: | |
| name: Frontend (Nx + Angular) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Nx affected commands need git history | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20.18.1 | |
| - name: Enable pnpm | |
| run: corepack enable && corepack prepare pnpm@9.15.4 --activate | |
| - name: Install | |
| working-directory: frontend | |
| run: pnpm install --frozen-lockfile | |
| - name: Lint | |
| working-directory: frontend | |
| run: pnpm nx run-many -t lint | |
| - name: Test | |
| working-directory: frontend | |
| run: pnpm nx run-many -t test --watch=false --passWithNoTests | |
| - name: Build | |
| working-directory: frontend | |
| run: pnpm nx run-many -t build | |
| contracts: | |
| name: Contract drift | |
| runs-on: ubuntu-latest | |
| needs: [backend, frontend] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: 8.0.x | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20.18.1 | |
| - name: Enable pnpm | |
| run: corepack enable && corepack prepare pnpm@9.15.4 --activate | |
| - name: Install frontend deps | |
| working-directory: frontend | |
| run: pnpm install --frozen-lockfile | |
| - name: Run drift check | |
| run: ./scripts/check-contracts-clean.sh | |
| docker-build: | |
| name: Production Docker images | |
| runs-on: ubuntu-latest | |
| needs: [backend, frontend] | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Compute image tags | |
| id: tags | |
| run: | | |
| set -euo pipefail | |
| OWNER="${GITHUB_REPOSITORY_OWNER,,}" # ghcr requires lowercase | |
| SHA="${GITHUB_SHA}" | |
| SHORT="${GITHUB_SHA::7}" | |
| REGISTRY="ghcr.io" | |
| # Push on main branch + v* tag pushes only. | |
| if [[ "${GITHUB_REF}" == "refs/heads/main" || "${GITHUB_REF}" == refs/tags/v* ]]; then | |
| PUSH="true" | |
| else | |
| PUSH="false" | |
| fi | |
| if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then | |
| RELEASE="${GITHUB_REF#refs/tags/}" | |
| else | |
| RELEASE="" | |
| fi | |
| tag_set() { | |
| local image=$1 | |
| local base="${REGISTRY}/${OWNER}/${image}" | |
| local tags="${base}:${SHA},${base}:sha-${SHORT},${base}:latest" | |
| if [[ -n "$RELEASE" ]]; then | |
| tags="${tags},${base}:${RELEASE}" | |
| fi | |
| echo "$tags" | |
| } | |
| { | |
| echo "TAGS_API_EXTERNAL=$(tag_set cce-api-external)" | |
| echo "TAGS_API_INTERNAL=$(tag_set cce-api-internal)" | |
| echo "TAGS_WEB_PORTAL=$(tag_set cce-web-portal)" | |
| echo "TAGS_ADMIN_CMS=$(tag_set cce-admin-cms)" | |
| echo "TAGS_MIGRATOR=$(tag_set cce-migrator)" | |
| echo "PUSH=$PUSH" | |
| echo "OWNER=$OWNER" | |
| echo "RELEASE=$RELEASE" | |
| } >> "$GITHUB_ENV" | |
| { | |
| echo "## Production images" | |
| echo "" | |
| echo "| Image | Push | Tags |" | |
| echo "|---|---|---|" | |
| echo "| cce-api-external | $PUSH | \`$(tag_set cce-api-external)\` |" | |
| echo "| cce-api-internal | $PUSH | \`$(tag_set cce-api-internal)\` |" | |
| echo "| cce-web-portal | $PUSH | \`$(tag_set cce-web-portal)\` |" | |
| echo "| cce-admin-cms | $PUSH | \`$(tag_set cce-admin-cms)\` |" | |
| echo "| cce-migrator | $PUSH | \`$(tag_set cce-migrator)\` |" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| - name: Log in to ghcr.io | |
| if: env.PUSH == 'true' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build Api.External | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: backend | |
| file: backend/src/CCE.Api.External/Dockerfile | |
| push: ${{ env.PUSH == 'true' }} | |
| load: true | |
| tags: ${{ env.TAGS_API_EXTERNAL }} | |
| cache-from: type=gha,scope=api-external | |
| cache-to: type=gha,mode=max,scope=api-external | |
| - name: Build Api.Internal | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: backend | |
| file: backend/src/CCE.Api.Internal/Dockerfile | |
| push: ${{ env.PUSH == 'true' }} | |
| load: true | |
| tags: ${{ env.TAGS_API_INTERNAL }} | |
| cache-from: type=gha,scope=api-internal | |
| cache-to: type=gha,mode=max,scope=api-internal | |
| - name: Build web-portal | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: frontend/apps/web-portal/Dockerfile | |
| push: ${{ env.PUSH == 'true' }} | |
| load: true | |
| tags: ${{ env.TAGS_WEB_PORTAL }} | |
| cache-from: type=gha,scope=web-portal | |
| cache-to: type=gha,mode=max,scope=web-portal | |
| - name: Build admin-cms | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: frontend/apps/admin-cms/Dockerfile | |
| push: ${{ env.PUSH == 'true' }} | |
| load: true | |
| tags: ${{ env.TAGS_ADMIN_CMS }} | |
| cache-from: type=gha,scope=admin-cms | |
| cache-to: type=gha,mode=max,scope=admin-cms | |
| - name: Build cce-migrator | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: backend | |
| file: backend/src/CCE.Seeder/Dockerfile | |
| push: ${{ env.PUSH == 'true' }} | |
| load: true | |
| tags: ${{ env.TAGS_MIGRATOR }} | |
| cache-from: type=gha,scope=migrator | |
| cache-to: type=gha,mode=max,scope=migrator | |
| - name: Smoke-probe all five runtime containers | |
| run: | | |
| set -euo pipefail | |
| probe_backend() { | |
| local name=$1 image=$2 host_port=$3 | |
| docker run --rm -d --name "${name}" -p "${host_port}:8080" \ | |
| -e Keycloak__Authority=http://localhost:8080/realms/cce \ | |
| -e Keycloak__Audience=cce-api \ | |
| -e Keycloak__RequireHttpsMetadata=false \ | |
| -e Infrastructure__SqlConnectionString="Server=localhost;Database=CCE;Integrated Security=True" \ | |
| -e Infrastructure__RedisConnectionString="localhost:6379" \ | |
| "${image}" | |
| for i in $(seq 1 15); do | |
| sleep 2 | |
| if curl -fsS "http://localhost:${host_port}/health" >/dev/null 2>&1; then | |
| echo "${name}: PASS" | |
| docker rm -f "${name}" >/dev/null | |
| return 0 | |
| fi | |
| done | |
| echo "${name}: FAIL" | |
| docker logs "${name}" || true | |
| docker rm -f "${name}" >/dev/null | |
| return 1 | |
| } | |
| probe_frontend() { | |
| local name=$1 image=$2 host_port=$3 | |
| docker run --rm -d --name "${name}" -p "${host_port}:8080" "${image}" | |
| for i in $(seq 1 10); do | |
| sleep 1 | |
| if curl -fsS "http://localhost:${host_port}/" | grep -q "<html"; then | |
| echo "${name}: PASS" | |
| docker rm -f "${name}" >/dev/null | |
| return 0 | |
| fi | |
| done | |
| echo "${name}: FAIL" | |
| docker logs "${name}" || true | |
| docker rm -f "${name}" >/dev/null | |
| return 1 | |
| } | |
| # Use the first tag from each comma-list as the local image ref | |
| # (load: true on build-push-action loads the image into the local | |
| # docker engine under all tags, but `docker run` needs a single ref). | |
| probe_backend ext "${TAGS_API_EXTERNAL%%,*}" 18080 | |
| probe_backend int "${TAGS_API_INTERNAL%%,*}" 18081 | |
| probe_frontend portal "${TAGS_WEB_PORTAL%%,*}" 18082 | |
| probe_frontend cms "${TAGS_ADMIN_CMS%%,*}" 18083 | |
| # Migrator flag-validation probe: assert --migrate --demo exits non-zero. | |
| # Cheap (no SQL Server needed); catches Sub-10b regressions in the | |
| # SeederMode.Parse rejection path. | |
| MIGRATOR_IMG="${TAGS_MIGRATOR%%,*}" | |
| if docker run --rm "$MIGRATOR_IMG" --migrate --demo 2>/dev/null; then | |
| echo "migrator: FAIL — should have rejected --migrate --demo" | |
| exit 1 | |
| else | |
| echo "migrator: PASS — rejects --migrate --demo (exit $?)" | |
| fi |