name: Build and Test on: push: branches: - main - pulse/v6-release pull_request: branches: - main - pulse/v6-release workflow_dispatch: permissions: contents: read jobs: secret-scan: name: Secret Scan runs-on: ubuntu-24.04 steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - name: Run gitleaks uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} build: name: Frontend & Backend runs-on: ubuntu-24.04 env: FRONTEND_DIR: frontend-modern steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' cache: npm cache-dependency-path: frontend-modern/package-lock.json - name: Install frontend dependencies working-directory: frontend-modern run: npm ci - name: Lint frontend working-directory: frontend-modern run: npm run lint - name: Audit header composition working-directory: frontend-modern run: npm run lint:headers - name: Check frontend copy-paste duplication working-directory: frontend-modern run: npm run lint:cpd - name: Frontend unit tests working-directory: frontend-modern run: npm run test - name: Type-check frontend working-directory: frontend-modern run: npm run type-check - name: Build frontend bundle (with embed copy) run: make frontend - name: Check frontend bundle size budget working-directory: frontend-modern run: npm run check:bundlesize - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 with: go-version-file: go.mod cache: true - name: Script smoke tests run: scripts/tests/run.sh - name: Go unit tests env: PULSE_DATA_DIR: /tmp/pulse-test-data run: go test -race -timeout 10m ./... - name: Go benchmarks env: PULSE_DATA_DIR: /tmp/pulse-bench-data run: | set -o pipefail go test -bench=. -benchmem -count=5 -run=^$ -timeout=10m \ ./pkg/metrics/ \ ./pkg/auth/ \ ./internal/api/ \ ./internal/monitoring/ \ ./internal/unifiedresources/ \ ./internal/dockeragent/ \ ./cmd/pulse-agent/ \ ./internal/hostagent/ \ ./internal/hostmetrics/ \ | tee bench-results.txt - name: Upload benchmark results if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: bench-results path: bench-results.txt retention-days: 90 - name: Install benchstat run: go install golang.org/x/perf/cmd/benchstat@v0.0.0-20260211190930-8161c38c6cdc - name: Save benchmark baseline (main branch) if: github.ref == 'refs/heads/main' run: cp bench-results.txt bench-baseline.txt - name: Cache benchmark baseline (main branch) if: github.ref == 'refs/heads/main' uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: bench-baseline.txt key: go-bench-baseline-${{ github.sha }} - name: Restore benchmark baseline (PRs) if: github.event_name == 'pull_request' uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: bench-baseline.txt key: go-bench-baseline- restore-keys: go-bench-baseline- - name: Compare benchmarks against baseline if: github.event_name == 'pull_request' run: | set -eo pipefail if [ ! -f bench-baseline.txt ]; then echo "No benchmark baseline found (first PR against main?). Skipping comparison." exit 0 fi echo "=== Benchmark comparison (baseline vs current) ===" benchstat bench-baseline.txt bench-results.txt | tee bench-comparison.txt echo "" bash scripts/check-bench-regression.sh bench-comparison.txt - name: Build Pulse backend run: go build ./cmd/pulse