Skip to content

Bump coverlet.collector from 6.0.2 to 10.0.0 #25

Bump coverlet.collector from 6.0.2 to 10.0.0

Bump coverlet.collector from 6.0.2 to 10.0.0 #25

Workflow file for this run

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