name: Backend API CI on: push: paths: - "veza-backend-api/**" - ".github/workflows/backend-ci.yml" pull_request: paths: - "veza-backend-api/**" - ".github/workflows/backend-ci.yml" env: GIT_SSL_NO_VERIFY: "true" NODE_TLS_REJECT_UNAUTHORIZED: "0" jobs: test-unit: runs-on: ubuntu-latest defaults: run: working-directory: veza-backend-api steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: "1.25" cache: true cache-dependency-path: veza-backend-api/go.sum - name: Download deps run: go mod download - name: Go vet and format check run: | go vet ./... test -z "$(gofmt -l .)" working-directory: veza-backend-api - name: Cache govulncheck binary id: govulncheck-cache uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: ~/go/bin/govulncheck key: ${{ runner.os }}-govulncheck-latest - name: Run govulncheck run: | if [ ! -x "$HOME/go/bin/govulncheck" ]; then go install golang.org/x/vuln/cmd/govulncheck@latest fi $HOME/go/bin/govulncheck ./... - name: Run unit tests with coverage run: > go test ./internal/handlers/... ./internal/services/... ./internal/core/... ./internal/middleware/... -short -coverprofile=coverage.out -covermode=atomic -timeout 5m - name: Enforce coverage threshold (>= 70%) run: | COVERAGE=$(go tool cover -func=coverage.out | grep '^total:' | awk '{print $NF}' | tr -d '%') echo "Total coverage: ${COVERAGE}%" if [ -z "$COVERAGE" ]; then echo "::warning::Could not parse coverage percentage" exit 0 fi # Compare as integers (remove decimal) COV_INT=$(echo "$COVERAGE" | cut -d. -f1) if [ "$COV_INT" -lt 75 ]; then echo "::error::Coverage ${COVERAGE}% is below the 75% threshold" exit 1 fi echo "::notice::Coverage ${COVERAGE}% meets the >= 75% threshold" - name: Upload coverage report uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: go-coverage path: veza-backend-api/coverage.out - name: Generate coverage badge if: github.ref == 'refs/heads/main' && github.event_name == 'push' run: | COVERAGE=$(go tool cover -func=coverage.out | grep '^total:' | awk '{print $NF}' | tr -d '%') COV_INT=$(echo "$COVERAGE" | cut -d. -f1) if [ "$COV_INT" -ge 80 ]; then COLOR="brightgreen" elif [ "$COV_INT" -ge 70 ]; then COLOR="green" elif [ "$COV_INT" -ge 50 ]; then COLOR="yellow" else COLOR="red" fi echo "{\"schemaVersion\":1,\"label\":\"Go coverage\",\"message\":\"${COVERAGE}%\",\"color\":\"${COLOR}\"}" > coverage-badge.json echo "Coverage badge: ${COVERAGE}% (${COLOR})" - name: Upload coverage badge if: github.ref == 'refs/heads/main' && github.event_name == 'push' uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: go-coverage-badge path: veza-backend-api/coverage-badge.json test-integration: runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: veza_test ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 redis: image: redis:7-alpine ports: - 6379:6379 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/veza_test?sslmode=disable REDIS_URL: redis://localhost:6379 JWT_SECRET: test-jwt-secret-for-ci APP_ENV: test defaults: run: working-directory: veza-backend-api steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: "1.25" cache: true cache-dependency-path: veza-backend-api/go.sum - name: Download deps run: go mod download - name: Run migrations run: go run cmd/migrate_tool/main.go continue-on-error: true - name: Run integration tests run: go test -tags=integration ./internal/... -timeout 15m