# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0

name: CI Pipeline

on:
  pull_request:
    branches:
      - main

jobs:
  lint-and-build: # Linting and building are combined to save time for setting up Go
    name: Lint and Build
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v5

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: 1.25.x
          cache-dependency-path: "go.sum"

      - name: Install protolint
        run: |
          go install github.com/yoheimuta/protolint/cmd/protolint@latest

      - name: Lint Protobuf Files
        run: |
          protolint .

      - name: Run linters
        uses: golangci/golangci-lint-action@v8
        with:
          version: v2.4.0
          args: --config ./tools/config/.golangci.yaml

      - name: Build all Binaries
        run: |
          make all -j $(nproc)

      - name: Compile check for rabbitmq
        run: |
          SMQ_MESSAGE_BROKER_TYPE=msg_rabbitmq make mqtt

      - name: Compile check for redis
        run: |
          SMQ_ES_TYPE=es_redis make mqtt

  run-tests:
    name: Run tests
    runs-on: ubuntu-latest
    needs: lint-and-build

    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: 1.25.x
          cache-dependency-path: "go.sum"

      - name: Check for changes in specific paths
        uses: dorny/paths-filter@v3
        id: changes
        with:
          base: main
          filters: |
            workflow:
              - ".github/workflows/tests.yaml"

            auth:
              - "auth/**"
              - "cmd/auth/**"
              - "auth.proto"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "pkg/ulid/**"
              - "pkg/uuid/**"

            certs:
              - "certs/**"
              - "cmd/certs/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/sdk/**"

            channels:
              - "channels/**"
              - "cmd/channels/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/sdk/**"
              - "clients/api/grpc/**"
              - "groups/api/grpc/**"
              - "domains/api/grpc/**"
              - "internal/grpc/**"

            cli:
              - "cli/**"
              - "cmd/cli/**"
              - "pkg/sdk/**"

            clients:
              - "clients/**"
              - "cmd/clients/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/ulid/**"
              - "pkg/uuid/**"
              - "pkg/events/**"
              - "groups/api/grpc/**"
              - "channels/api/grpc/**"
              - "domains/api/grpc/**"
              - "internal/grpc/**"

            coap:
              - "coap/**"
              - "cmd/coap/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "clients/**"
              - "pkg/messaging/**"

            domains:
              - "domains/**"
              - "cmd/domains/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "internal/grpc/**"

            groups:
              - "groups/**"
              - "cmd/groups/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/ulid/**"
              - "pkg/uuid/**"
              - "clients/api/grpc/**"
              - "channels/api/grpc/**"
              - "domains/api/grpc/**"
              - "internal/grpc/**"

            http:
              - "http/**"
              - "cmd/http/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "clients/**"
              - "pkg/messaging/**"
              - "logger/**"

            internal:
              - "internal/**"

            journal:
              - "journal/**"
              - "cmd/journal/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/events/**"

            logger:
              - "logger/**"

            mqtt:
              - "mqtt/**"
              - "cmd/mqtt/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "clients/**"
              - "pkg/messaging/**"
              - "logger/**"
              - "pkg/events/**"

            pkg-errors:
              - "pkg/errors/**"

            pkg-events:
              - "pkg/events/**"
              - "pkg/messaging/**"

            pkg-grpcclient:
              - "pkg/grpcclient/**"

            pkg-messaging:
              - "pkg/messaging/**"

            pkg-sdk:
              - "pkg/sdk/**"
              - "pkg/errors/**"
              - "pkg/groups/**"
              - "auth/**"
              - "certs/**"
              - "http/**"
              - "internal/*"
              - "clients/**"
              - "users/**"
              - "channels/**"
              - "domains/**"
              - "groups/**"
              - "journal/**"
              - "api/http/**"

            pkg-transformers:
              - "pkg/transformers/**"

            pkg-ulid:
              - "pkg/ulid/**"

            pkg-uuid:
              - "pkg/uuid/**"

            users:
              - "users/**"
              - "cmd/users/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "auth/**"
              - "pkg/ulid/**"
              - "pkg/uuid/**"
              - "pkg/events/**"

            ws:
              - "ws/**"
              - "cmd/ws/**"
              - "auth.pb.go"
              - "auth_grpc.pb.go"
              - "clients/**"
              - "pkg/messaging/**"

      - name: Create coverage directory
        run: |
          mkdir coverage

      - name: Run journal tests
        if: steps.changes.outputs.journal == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/journal.out ./journal/...

      - name: Run auth tests
        if: steps.changes.outputs.auth == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/auth.out ./auth/...

      - name: Run domains tests
        if: steps.changes.outputs.domains == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/domains.out ./domains/...

      - name: Run certs tests
        if: steps.changes.outputs.certs == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/certs.out ./certs/...

      - name: Run cli tests
        if: steps.changes.outputs.cli == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/cli.out ./cli/...

      - name: Run CoAP tests
        if: steps.changes.outputs.coap == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/coap.out ./coap/...

      - name: Run HTTP tests
        if: steps.changes.outputs.http == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/http.out ./http/...

      - name: Run internal tests
        if: steps.changes.outputs.internal == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/internal.out ./internal/...

      - name: Run logger tests
        if: steps.changes.outputs.logger == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/logger.out ./logger/...

      - name: Run MQTT tests
        if: steps.changes.outputs.mqtt == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/mqtt.out ./mqtt/...

      - name: Run pkg errors tests
        if: steps.changes.outputs.pkg-errors == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-errors.out ./pkg/errors/...

      - name: Run pkg events tests
        if: steps.changes.outputs.pkg-events == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-events.out ./pkg/events/...

      - name: Run pkg grpcclient tests
        if: steps.changes.outputs.pkg-grpcclient == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-grpcclient.out ./pkg/grpcclient/...

      - name: Run pkg messaging tests
        if: steps.changes.outputs.pkg-messaging == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-messaging.out ./pkg/messaging/...

      - name: Run pkg sdk tests
        if: steps.changes.outputs.pkg-sdk == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-sdk.out ./pkg/sdk/...

      - name: Run pkg transformers tests
        if: steps.changes.outputs.pkg-transformers == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-transformers.out ./pkg/transformers/...

      - name: Run pkg ulid tests
        if: steps.changes.outputs.pkg-ulid == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-ulid.out ./pkg/ulid/...

      - name: Run pkg uuid tests
        if: steps.changes.outputs.pkg-uuid == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/pkg-uuid.out ./pkg/uuid/...

      - name: Run clients tests
        if: steps.changes.outputs.clients == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/clients.out ./clients/...

      - name: Run channels tests
        if: steps.changes.outputs.channels == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/channels.out ./channels/...

      - name: Run users tests
        if: steps.changes.outputs.users == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/users.out ./users/...

      - name: Run groups tests
        if: steps.changes.outputs.groups == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/groups.out ./groups/...

      - name: Run WebSocket tests
        if: steps.changes.outputs.ws == 'true' || steps.changes.outputs.workflow == 'true'
        run: |
          go test --race -v -count=1 -coverprofile=coverage/ws.out ./ws/...

      - name: Upload coverage
        uses: codecov/codecov-action@v5
        with:
          token: ${{ secrets.CODECOV }}
          files: ./coverage/*.out
          verbose: true
