name: CI - Build & Test run-name: 🔍 CI ${{ gitea.ref_name }} by @${{ gitea.actor }} # ── Concurrency: cancel in-progress CI when new push arrives ── concurrency: group: ci-${{ gitea.ref }} cancel-in-progress: true on: push: branches: - main - 'codex/**' pull_request: branches: [main] workflow_dispatch: jobs: # ─── Backend ─────────────────────────────────── backend: name: Backend (.NET) runs-on: linux steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET SDK uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Restore run: dotnet restore backend-tests/Nexus.Api.Tests.csproj - name: Build run: dotnet build backend-tests/Nexus.Api.Tests.csproj --no-restore --configuration Release - name: Verify EF migration model run: | dotnet tool restore dotnet tool run dotnet-ef migrations has-pending-model-changes \ --project backend/Nexus.Api.csproj \ --startup-project backend/Nexus.Api.csproj \ --configuration Release \ --no-build - name: Block high or critical backend vulnerabilities run: | dotnet list backend/Nexus.Api.csproj package --vulnerable --include-transitive --format json > /tmp/nexus-dotnet-vulnerabilities.json if grep -Eiq '"severity"[[:space:]]*:[[:space:]]*"(high|critical)"' /tmp/nexus-dotnet-vulnerabilities.json; then cat /tmp/nexus-dotnet-vulnerabilities.json exit 1 fi - name: Verify OpenAPI contract run: | test -f backend/openapi/Nexus.Api.json test -z "$(git status --porcelain --untracked-files=all -- backend/openapi/Nexus.Api.json)" - name: Test run: dotnet test backend-tests/Nexus.Api.Tests.csproj --no-build --configuration Release --verbosity normal backend-integration: name: Backend integration (PostgreSQL/Toxiproxy) runs-on: linux timeout-minutes: 20 env: NEXUS_RUN_DOCKER_INTEGRATION_TESTS: "true" NEXUS_RUN_TOXIPROXY_INTEGRATION_TESTS: "true" steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET SDK uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Verify Docker endpoint run: docker info - name: Restore and build run: | dotnet restore backend-tests/Nexus.Api.Tests.csproj dotnet build backend-tests/Nexus.Api.Tests.csproj --no-restore --configuration Release - name: Run all container-backed contracts run: >- dotnet test backend-tests/Nexus.Api.Tests.csproj --no-build --configuration Release --filter "Category=DockerIntegration|Category=ToxiproxyIntegration" --verbosity normal # ─── Frontend ────────────────────────────────── frontend: name: Frontend (Vue/TS) runs-on: linux steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '24' - name: Setup pnpm run: | corepack enable corepack prepare pnpm@10.12.1 --activate - name: Install dependencies run: pnpm install --frozen-lockfile working-directory: frontend - name: Verify release version run: test "$(node -p "require('./package.json').version")" = "$(tr -d '[:space:]' < ../VERSION)" working-directory: frontend - name: Block high or critical production vulnerabilities run: pnpm audit --prod --audit-level high working-directory: frontend - name: Type check run: pnpm typecheck working-directory: frontend - name: Verify generated API types run: | pnpm openapi:generate test -z "$(git status --porcelain --untracked-files=all -- src/api/generated/schema.d.ts)" working-directory: frontend - name: Test run: pnpm test working-directory: frontend - name: Build run: pnpm build working-directory: frontend - name: Install Playwright Chromium run: pnpm exec playwright install --with-deps chromium working-directory: frontend - name: Browser end-to-end tests run: pnpm test:e2e working-directory: frontend # ─── Security ────────────────────────────────── security: name: Security Check runs-on: linux if: gitea.ref == 'refs/heads/main' || startsWith(gitea.ref, 'refs/heads/codex/') steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Gitleaks v8.30.1 env: GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb run: | curl -fsSL https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz -o /tmp/gitleaks.tar.gz echo "$GITLEAKS_SHA256 /tmp/gitleaks.tar.gz" | sha256sum -c - tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks /tmp/gitleaks git --redact --no-banner --exit-code 1 . deploy: name: Deploy Nexus runs-on: linux needs: [backend, backend-integration, frontend, security] concurrency: group: deploy-production cancel-in-progress: false if: | gitea.event_name == 'push' && gitea.ref == 'refs/heads/main' env: DEPLOY_PATH: /home/projekte_bao/nexus ENV_POSTGRES_PASSWORD: ${{ secrets.ENV_POSTGRES_PASSWORD }} ENV_JWT_KEY: ${{ secrets.ENV_JWT_KEY }} ENV_BOOTSTRAP_OWNER_PASSWORD: ${{ secrets.ENV_BOOTSTRAP_OWNER_PASSWORD }} ENV_OPENCLAW_TOKEN: ${{ secrets.ENV_OPENCLAW_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 - name: Deploy after green CI run: sh .gitea/scripts/deploy-nexus.sh