# CI Pipeline: Validates code on PRs, builds images on push
#
# Flow:
#   PR → dev/main     : Runs validation (required status check)
#   Push → dev/main   : Builds Docker images (only changed services)
#
# Selective Builds:
#   - Only builds services that have changed files
#   - Detects changes in service path, shared packages, and root config
#   - Use workflow_dispatch to force rebuild all services
#
# Deployments are triggered separately:
#   - Manual: workflow_dispatch on cd-staging.yml / cd-production.yml
#   - Tag-based: push tag like "chat-staging-v1.0.0" triggers cd-staging-tagged.yml

name: CI

on:
  push:
    branches:
      - main
      - dev
  pull_request:
    branches:
      - main
      - dev
  workflow_dispatch:
    inputs:
      force_build_all:
        description: 'Force rebuild all services'
        required: false
        default: 'false'
        type: boolean

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  NODE_VERSION: '20'
  PNPM_VERSION: '9.15.0'

jobs:
  # ===========================================
  # Detect Changes - determines which services to build
  # ===========================================
  detect-changes:
    name: Detect Changes
    runs-on: ubuntu-latest
    if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
    outputs:
      mana-core-auth: ${{ steps.changes.outputs.mana-core-auth }}
      mana-search: ${{ steps.changes.outputs.mana-search }}
      api-gateway: ${{ steps.changes.outputs.api-gateway }}
      manacore-web: ${{ steps.changes.outputs.manacore-web }}
      chat-backend: ${{ steps.changes.outputs.chat-backend }}
      chat-web: ${{ steps.changes.outputs.chat-web }}
      todo-backend: ${{ steps.changes.outputs.todo-backend }}
      todo-web: ${{ steps.changes.outputs.todo-web }}
      calendar-backend: ${{ steps.changes.outputs.calendar-backend }}
      calendar-web: ${{ steps.changes.outputs.calendar-web }}
      clock-backend: ${{ steps.changes.outputs.clock-backend }}
      clock-web: ${{ steps.changes.outputs.clock-web }}
      contacts-backend: ${{ steps.changes.outputs.contacts-backend }}
      contacts-web: ${{ steps.changes.outputs.contacts-web }}
      presi-backend: ${{ steps.changes.outputs.presi-backend }}
      presi-web: ${{ steps.changes.outputs.presi-web }}
      storage-backend: ${{ steps.changes.outputs.storage-backend }}
      storage-web: ${{ steps.changes.outputs.storage-web }}
      telegram-stats-bot: ${{ steps.changes.outputs.telegram-stats-bot }}
      nutriphi-backend: ${{ steps.changes.outputs.nutriphi-backend }}
      nutriphi-web: ${{ steps.changes.outputs.nutriphi-web }}
      skilltree-backend: ${{ steps.changes.outputs.skilltree-backend }}
      skilltree-web: ${{ steps.changes.outputs.skilltree-web }}
      matrix-mana-bot: ${{ steps.changes.outputs.matrix-mana-bot }}
      matrix-ollama-bot: ${{ steps.changes.outputs.matrix-ollama-bot }}
      matrix-stats-bot: ${{ steps.changes.outputs.matrix-stats-bot }}
      matrix-project-doc-bot: ${{ steps.changes.outputs.matrix-project-doc-bot }}
      matrix-todo-bot: ${{ steps.changes.outputs.matrix-todo-bot }}
      matrix-calendar-bot: ${{ steps.changes.outputs.matrix-calendar-bot }}
      matrix-nutriphi-bot: ${{ steps.changes.outputs.matrix-nutriphi-bot }}
      matrix-zitare-bot: ${{ steps.changes.outputs.matrix-zitare-bot }}
      matrix-clock-bot: ${{ steps.changes.outputs.matrix-clock-bot }}
      matrix-tts-bot: ${{ steps.changes.outputs.matrix-tts-bot }}
      zitare-backend: ${{ steps.changes.outputs.zitare-backend }}
      any-changes: ${{ steps.changes.outputs.any-changes }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Check for changes
        id: changes
        run: |
          # Force build all if workflow_dispatch with force_build_all
          if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.force_build_all }}" == "true" ]; then
            echo "Force rebuild all services requested"
            echo "mana-core-auth=true" >> $GITHUB_OUTPUT
            echo "mana-search=true" >> $GITHUB_OUTPUT
            echo "api-gateway=true" >> $GITHUB_OUTPUT
            echo "manacore-web=true" >> $GITHUB_OUTPUT
            echo "chat-backend=true" >> $GITHUB_OUTPUT
            echo "chat-web=true" >> $GITHUB_OUTPUT
            echo "todo-backend=true" >> $GITHUB_OUTPUT
            echo "todo-web=true" >> $GITHUB_OUTPUT
            echo "calendar-backend=true" >> $GITHUB_OUTPUT
            echo "calendar-web=true" >> $GITHUB_OUTPUT
            echo "clock-backend=true" >> $GITHUB_OUTPUT
            echo "clock-web=true" >> $GITHUB_OUTPUT
            echo "contacts-backend=true" >> $GITHUB_OUTPUT
            echo "contacts-web=true" >> $GITHUB_OUTPUT
            echo "presi-backend=true" >> $GITHUB_OUTPUT
            echo "presi-web=true" >> $GITHUB_OUTPUT
            echo "storage-backend=true" >> $GITHUB_OUTPUT
            echo "storage-web=true" >> $GITHUB_OUTPUT
            echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
            echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
            echo "nutriphi-web=true" >> $GITHUB_OUTPUT
            echo "skilltree-backend=true" >> $GITHUB_OUTPUT
            echo "skilltree-web=true" >> $GITHUB_OUTPUT
            echo "matrix-mana-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-ollama-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-stats-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-project-doc-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-todo-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-calendar-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-nutriphi-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-zitare-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-clock-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-tts-bot=true" >> $GITHUB_OUTPUT
            echo "zitare-backend=true" >> $GITHUB_OUTPUT
            echo "any-changes=true" >> $GITHUB_OUTPUT
            exit 0
          fi

          # Get changed files between current commit and previous
          if [ "${{ github.event_name }}" == "push" ]; then
            BASE_SHA="${{ github.event.before }}"
            HEAD_SHA="${{ github.sha }}"
            # Handle initial commit case
            if [ "$BASE_SHA" == "0000000000000000000000000000000000000000" ]; then
              CHANGED_FILES=$(git ls-files)
            else
              CHANGED_FILES=$(git diff --name-only $BASE_SHA $HEAD_SHA 2>/dev/null || git ls-files)
            fi
          else
            # workflow_dispatch without force - build all
            echo "Workflow dispatch without force_build_all - building all"
            echo "mana-core-auth=true" >> $GITHUB_OUTPUT
            echo "mana-search=true" >> $GITHUB_OUTPUT
            echo "api-gateway=true" >> $GITHUB_OUTPUT
            echo "manacore-web=true" >> $GITHUB_OUTPUT
            echo "chat-backend=true" >> $GITHUB_OUTPUT
            echo "chat-web=true" >> $GITHUB_OUTPUT
            echo "todo-backend=true" >> $GITHUB_OUTPUT
            echo "todo-web=true" >> $GITHUB_OUTPUT
            echo "calendar-backend=true" >> $GITHUB_OUTPUT
            echo "calendar-web=true" >> $GITHUB_OUTPUT
            echo "clock-backend=true" >> $GITHUB_OUTPUT
            echo "clock-web=true" >> $GITHUB_OUTPUT
            echo "contacts-backend=true" >> $GITHUB_OUTPUT
            echo "contacts-web=true" >> $GITHUB_OUTPUT
            echo "presi-backend=true" >> $GITHUB_OUTPUT
            echo "presi-web=true" >> $GITHUB_OUTPUT
            echo "storage-backend=true" >> $GITHUB_OUTPUT
            echo "storage-web=true" >> $GITHUB_OUTPUT
            echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
            echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
            echo "nutriphi-web=true" >> $GITHUB_OUTPUT
            echo "skilltree-backend=true" >> $GITHUB_OUTPUT
            echo "skilltree-web=true" >> $GITHUB_OUTPUT
            echo "matrix-mana-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-ollama-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-stats-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-project-doc-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-todo-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-calendar-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-nutriphi-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-zitare-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-clock-bot=true" >> $GITHUB_OUTPUT
            echo "matrix-tts-bot=true" >> $GITHUB_OUTPUT
            echo "zitare-backend=true" >> $GITHUB_OUTPUT
            echo "any-changes=true" >> $GITHUB_OUTPUT
            exit 0
          fi

          echo "Changed files:"
          echo "$CHANGED_FILES"

          # Common files that trigger all builds
          COMMON_PATTERNS="pnpm-lock.yaml|pnpm-workspace.yaml|package.json|.github/workflows/ci.yml"

          # Shared packages that affect multiple services
          SHARED_AUTH_PATTERN="packages/shared-auth/|packages/shared-types/"
          SHARED_UI_PATTERN="packages/shared-ui/|packages/shared-theme/|packages/shared-icons/|packages/shared-tailwind/|packages/shared-branding/"
          SHARED_WEB_PATTERN="packages/shared-auth-ui/|packages/shared-theme-ui/|packages/shared-feedback-ui/|packages/shared-profile-ui/|packages/shared-subscription-ui/|packages/shared-splitscreen/"
          SHARED_BOT_PATTERN="packages/bot-services/|packages/matrix-bot-common/"

          # Function to check if any pattern matches
          check_pattern() {
            echo "$CHANGED_FILES" | grep -qE "$1" && echo "true" || echo "false"
          }

          # Check common changes
          COMMON_CHANGED=$(check_pattern "$COMMON_PATTERNS")
          SHARED_AUTH_CHANGED=$(check_pattern "$SHARED_AUTH_PATTERN")
          SHARED_UI_CHANGED=$(check_pattern "$SHARED_UI_PATTERN")
          SHARED_WEB_CHANGED=$(check_pattern "$SHARED_WEB_PATTERN")

          SHARED_BOT_CHANGED=$(check_pattern "$SHARED_BOT_PATTERN")

          echo "Common changed: $COMMON_CHANGED"
          echo "Shared auth changed: $SHARED_AUTH_CHANGED"
          echo "Shared UI changed: $SHARED_UI_CHANGED"
          echo "Shared web changed: $SHARED_WEB_CHANGED"
          echo "Shared bot changed: $SHARED_BOT_CHANGED"

          # mana-core-auth: services/mana-core-auth + packages/shared-nestjs-auth
          AUTH_CHANGED=$(check_pattern "services/mana-core-auth/|packages/shared-nestjs-auth/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$AUTH_CHANGED" == "true" ]; then
            echo "mana-core-auth=true" >> $GITHUB_OUTPUT
          else
            echo "mana-core-auth=false" >> $GITHUB_OUTPUT
          fi

          # mana-search: services/mana-search
          SEARCH_CHANGED=$(check_pattern "services/mana-search/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SEARCH_CHANGED" == "true" ]; then
            echo "mana-search=true" >> $GITHUB_OUTPUT
          else
            echo "mana-search=false" >> $GITHUB_OUTPUT
          fi

          # api-gateway: services/mana-api-gateway + packages/shared-nestjs-auth
          GATEWAY_CHANGED=$(check_pattern "services/mana-api-gateway/|packages/shared-nestjs-auth/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$GATEWAY_CHANGED" == "true" ]; then
            echo "api-gateway=true" >> $GITHUB_OUTPUT
          else
            echo "api-gateway=false" >> $GITHUB_OUTPUT
          fi

          # manacore-web: apps/manacore/apps/web + shared packages
          MANACORE_WEB_CHANGED=$(check_pattern "apps/manacore/apps/web/|apps/manacore/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$MANACORE_WEB_CHANGED" == "true" ]; then
            echo "manacore-web=true" >> $GITHUB_OUTPUT
          else
            echo "manacore-web=false" >> $GITHUB_OUTPUT
          fi

          # chat-backend: apps/chat/apps/backend + packages
          CHAT_BACKEND_CHANGED=$(check_pattern "apps/chat/apps/backend/|apps/chat/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$CHAT_BACKEND_CHANGED" == "true" ]; then
            echo "chat-backend=true" >> $GITHUB_OUTPUT
          else
            echo "chat-backend=false" >> $GITHUB_OUTPUT
          fi

          # chat-web: apps/chat/apps/web + packages + shared web
          CHAT_WEB_CHANGED=$(check_pattern "apps/chat/apps/web/|apps/chat/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$CHAT_WEB_CHANGED" == "true" ]; then
            echo "chat-web=true" >> $GITHUB_OUTPUT
          else
            echo "chat-web=false" >> $GITHUB_OUTPUT
          fi

          # todo-backend
          TODO_BACKEND_CHANGED=$(check_pattern "apps/todo/apps/backend/|apps/todo/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$TODO_BACKEND_CHANGED" == "true" ]; then
            echo "todo-backend=true" >> $GITHUB_OUTPUT
          else
            echo "todo-backend=false" >> $GITHUB_OUTPUT
          fi

          # todo-web
          TODO_WEB_CHANGED=$(check_pattern "apps/todo/apps/web/|apps/todo/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$TODO_WEB_CHANGED" == "true" ]; then
            echo "todo-web=true" >> $GITHUB_OUTPUT
          else
            echo "todo-web=false" >> $GITHUB_OUTPUT
          fi

          # calendar-backend
          CALENDAR_BACKEND_CHANGED=$(check_pattern "apps/calendar/apps/backend/|apps/calendar/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$CALENDAR_BACKEND_CHANGED" == "true" ]; then
            echo "calendar-backend=true" >> $GITHUB_OUTPUT
          else
            echo "calendar-backend=false" >> $GITHUB_OUTPUT
          fi

          # calendar-web
          CALENDAR_WEB_CHANGED=$(check_pattern "apps/calendar/apps/web/|apps/calendar/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$CALENDAR_WEB_CHANGED" == "true" ]; then
            echo "calendar-web=true" >> $GITHUB_OUTPUT
          else
            echo "calendar-web=false" >> $GITHUB_OUTPUT
          fi

          # clock-backend
          CLOCK_BACKEND_CHANGED=$(check_pattern "apps/clock/apps/backend/|apps/clock/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$CLOCK_BACKEND_CHANGED" == "true" ]; then
            echo "clock-backend=true" >> $GITHUB_OUTPUT
          else
            echo "clock-backend=false" >> $GITHUB_OUTPUT
          fi

          # clock-web
          CLOCK_WEB_CHANGED=$(check_pattern "apps/clock/apps/web/|apps/clock/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$CLOCK_WEB_CHANGED" == "true" ]; then
            echo "clock-web=true" >> $GITHUB_OUTPUT
          else
            echo "clock-web=false" >> $GITHUB_OUTPUT
          fi

          # contacts-backend
          CONTACTS_BACKEND_CHANGED=$(check_pattern "apps/contacts/apps/backend/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$CONTACTS_BACKEND_CHANGED" == "true" ]; then
            echo "contacts-backend=true" >> $GITHUB_OUTPUT
          else
            echo "contacts-backend=false" >> $GITHUB_OUTPUT
          fi

          # contacts-web
          CONTACTS_WEB_CHANGED=$(check_pattern "apps/contacts/apps/web/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$CONTACTS_WEB_CHANGED" == "true" ]; then
            echo "contacts-web=true" >> $GITHUB_OUTPUT
          else
            echo "contacts-web=false" >> $GITHUB_OUTPUT
          fi

          # presi-backend
          PRESI_BACKEND_CHANGED=$(check_pattern "apps/presi/apps/backend/|apps/presi/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$PRESI_BACKEND_CHANGED" == "true" ]; then
            echo "presi-backend=true" >> $GITHUB_OUTPUT
          else
            echo "presi-backend=false" >> $GITHUB_OUTPUT
          fi

          # presi-web
          PRESI_WEB_CHANGED=$(check_pattern "apps/presi/apps/web/|apps/presi/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$PRESI_WEB_CHANGED" == "true" ]; then
            echo "presi-web=true" >> $GITHUB_OUTPUT
          else
            echo "presi-web=false" >> $GITHUB_OUTPUT
          fi

          # storage-backend
          STORAGE_BACKEND_CHANGED=$(check_pattern "apps/storage/apps/backend/|apps/storage/packages/|packages/shared-storage/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$STORAGE_BACKEND_CHANGED" == "true" ]; then
            echo "storage-backend=true" >> $GITHUB_OUTPUT
          else
            echo "storage-backend=false" >> $GITHUB_OUTPUT
          fi

          # storage-web
          STORAGE_WEB_CHANGED=$(check_pattern "apps/storage/apps/web/|apps/storage/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$STORAGE_WEB_CHANGED" == "true" ]; then
            echo "storage-web=true" >> $GITHUB_OUTPUT
          else
            echo "storage-web=false" >> $GITHUB_OUTPUT
          fi

          # telegram-stats-bot
          TELEGRAM_STATS_BOT_CHANGED=$(check_pattern "services/telegram-stats-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$TELEGRAM_STATS_BOT_CHANGED" == "true" ]; then
            echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
          else
            echo "telegram-stats-bot=false" >> $GITHUB_OUTPUT
          fi

          # nutriphi-backend
          NUTRIPHI_BACKEND_CHANGED=$(check_pattern "apps/nutriphi/apps/backend/|apps/nutriphi/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$NUTRIPHI_BACKEND_CHANGED" == "true" ]; then
            echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
          else
            echo "nutriphi-backend=false" >> $GITHUB_OUTPUT
          fi

          # nutriphi-web
          NUTRIPHI_WEB_CHANGED=$(check_pattern "apps/nutriphi/apps/web/|apps/nutriphi/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$NUTRIPHI_WEB_CHANGED" == "true" ]; then
            echo "nutriphi-web=true" >> $GITHUB_OUTPUT
          else
            echo "nutriphi-web=false" >> $GITHUB_OUTPUT
          fi

          # skilltree-backend
          SKILLTREE_BACKEND_CHANGED=$(check_pattern "apps/skilltree/apps/backend/|apps/skilltree/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SKILLTREE_BACKEND_CHANGED" == "true" ]; then
            echo "skilltree-backend=true" >> $GITHUB_OUTPUT
          else
            echo "skilltree-backend=false" >> $GITHUB_OUTPUT
          fi

          # skilltree-web
          SKILLTREE_WEB_CHANGED=$(check_pattern "apps/skilltree/apps/web/|apps/skilltree/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$SKILLTREE_WEB_CHANGED" == "true" ]; then
            echo "skilltree-web=true" >> $GITHUB_OUTPUT
          else
            echo "skilltree-web=false" >> $GITHUB_OUTPUT
          fi

          # matrix-mana-bot
          MATRIX_MANA_BOT_CHANGED=$(check_pattern "services/matrix-mana-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_MANA_BOT_CHANGED" == "true" ]; then
            echo "matrix-mana-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-mana-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-ollama-bot
          MATRIX_OLLAMA_BOT_CHANGED=$(check_pattern "services/matrix-ollama-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_OLLAMA_BOT_CHANGED" == "true" ]; then
            echo "matrix-ollama-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-ollama-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-stats-bot
          MATRIX_STATS_BOT_CHANGED=$(check_pattern "services/matrix-stats-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_STATS_BOT_CHANGED" == "true" ]; then
            echo "matrix-stats-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-stats-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-project-doc-bot
          MATRIX_PROJECT_DOC_BOT_CHANGED=$(check_pattern "services/matrix-project-doc-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_PROJECT_DOC_BOT_CHANGED" == "true" ]; then
            echo "matrix-project-doc-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-project-doc-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-todo-bot
          MATRIX_TODO_BOT_CHANGED=$(check_pattern "services/matrix-todo-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_TODO_BOT_CHANGED" == "true" ]; then
            echo "matrix-todo-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-todo-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-calendar-bot
          MATRIX_CALENDAR_BOT_CHANGED=$(check_pattern "services/matrix-calendar-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_CALENDAR_BOT_CHANGED" == "true" ]; then
            echo "matrix-calendar-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-calendar-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-nutriphi-bot
          MATRIX_NUTRIPHI_BOT_CHANGED=$(check_pattern "services/matrix-nutriphi-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_NUTRIPHI_BOT_CHANGED" == "true" ]; then
            echo "matrix-nutriphi-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-nutriphi-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-zitare-bot
          MATRIX_ZITARE_BOT_CHANGED=$(check_pattern "services/matrix-zitare-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_ZITARE_BOT_CHANGED" == "true" ]; then
            echo "matrix-zitare-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-zitare-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-clock-bot
          MATRIX_CLOCK_BOT_CHANGED=$(check_pattern "services/matrix-clock-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_CLOCK_BOT_CHANGED" == "true" ]; then
            echo "matrix-clock-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-clock-bot=false" >> $GITHUB_OUTPUT
          fi

          # matrix-tts-bot
          MATRIX_TTS_BOT_CHANGED=$(check_pattern "services/matrix-tts-bot/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_BOT_CHANGED" == "true" ] || [ "$MATRIX_TTS_BOT_CHANGED" == "true" ]; then
            echo "matrix-tts-bot=true" >> $GITHUB_OUTPUT
          else
            echo "matrix-tts-bot=false" >> $GITHUB_OUTPUT
          fi

          # zitare-backend
          ZITARE_BACKEND_CHANGED=$(check_pattern "apps/zitare/apps/backend/|apps/zitare/packages/")
          if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$ZITARE_BACKEND_CHANGED" == "true" ]; then
            echo "zitare-backend=true" >> $GITHUB_OUTPUT
          else
            echo "zitare-backend=false" >> $GITHUB_OUTPUT
          fi

          # Check if any service needs building
          if grep -q "=true" $GITHUB_OUTPUT; then
            echo "any-changes=true" >> $GITHUB_OUTPUT
          else
            echo "any-changes=false" >> $GITHUB_OUTPUT
          fi

      - name: Summary
        run: |
          echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| Service | Will Build |" >> $GITHUB_STEP_SUMMARY
          echo "|---------|------------|" >> $GITHUB_STEP_SUMMARY
          echo "| mana-core-auth | ${{ steps.changes.outputs.mana-core-auth }} |" >> $GITHUB_STEP_SUMMARY
          echo "| mana-search | ${{ steps.changes.outputs.mana-search }} |" >> $GITHUB_STEP_SUMMARY
          echo "| api-gateway | ${{ steps.changes.outputs.api-gateway }} |" >> $GITHUB_STEP_SUMMARY
          echo "| manacore-web | ${{ steps.changes.outputs.manacore-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| chat-backend | ${{ steps.changes.outputs.chat-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| chat-web | ${{ steps.changes.outputs.chat-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| todo-backend | ${{ steps.changes.outputs.todo-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| todo-web | ${{ steps.changes.outputs.todo-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| calendar-backend | ${{ steps.changes.outputs.calendar-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| calendar-web | ${{ steps.changes.outputs.calendar-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| clock-backend | ${{ steps.changes.outputs.clock-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| clock-web | ${{ steps.changes.outputs.clock-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| contacts-backend | ${{ steps.changes.outputs.contacts-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| contacts-web | ${{ steps.changes.outputs.contacts-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| presi-backend | ${{ steps.changes.outputs.presi-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| presi-web | ${{ steps.changes.outputs.presi-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| storage-backend | ${{ steps.changes.outputs.storage-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| storage-web | ${{ steps.changes.outputs.storage-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| telegram-stats-bot | ${{ steps.changes.outputs.telegram-stats-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| nutriphi-backend | ${{ steps.changes.outputs.nutriphi-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| nutriphi-web | ${{ steps.changes.outputs.nutriphi-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| skilltree-backend | ${{ steps.changes.outputs.skilltree-backend }} |" >> $GITHUB_STEP_SUMMARY
          echo "| skilltree-web | ${{ steps.changes.outputs.skilltree-web }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-mana-bot | ${{ steps.changes.outputs.matrix-mana-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-ollama-bot | ${{ steps.changes.outputs.matrix-ollama-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-stats-bot | ${{ steps.changes.outputs.matrix-stats-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-project-doc-bot | ${{ steps.changes.outputs.matrix-project-doc-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-todo-bot | ${{ steps.changes.outputs.matrix-todo-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-calendar-bot | ${{ steps.changes.outputs.matrix-calendar-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-nutriphi-bot | ${{ steps.changes.outputs.matrix-nutriphi-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-zitare-bot | ${{ steps.changes.outputs.matrix-zitare-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-clock-bot | ${{ steps.changes.outputs.matrix-clock-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| matrix-tts-bot | ${{ steps.changes.outputs.matrix-tts-bot }} |" >> $GITHUB_STEP_SUMMARY
          echo "| zitare-backend | ${{ steps.changes.outputs.zitare-backend }} |" >> $GITHUB_STEP_SUMMARY

  # ===========================================
  # Validation job - runs on PRs
  # ===========================================
  validate:
    name: Validate
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup pnpm
        uses: pnpm/action-setup@v2
        with:
          version: ${{ env.PNPM_VERSION }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Validate monorepo best practices
        run: pnpm run validate:monorepo

      - name: Type check
        run: pnpm run type-check

      - name: Lint
        run: pnpm run lint || echo "Lint warnings found"

      - name: Security Audit
        run: |
          # Run pnpm audit and capture exit code
          # Exit 0 if only moderate/low vulnerabilities
          pnpm audit --audit-level=high || {
            echo "::warning::Security vulnerabilities found. Run 'pnpm audit' locally for details."
            exit 0  # Don't fail build on audit issues (just warn)
          }

      - name: Check for known vulnerable packages
        run: |
          # Check for packages with known critical vulnerabilities
          # This is a basic check - for production, consider Snyk or similar
          if grep -r "lodash@[0-3]\." pnpm-lock.yaml 2>/dev/null; then
            echo "::warning::Potentially vulnerable lodash version detected"
          fi
          if grep -r "axios@0\.[0-9]\." pnpm-lock.yaml 2>/dev/null; then
            echo "::warning::Potentially vulnerable axios version detected"
          fi

  # ===========================================
  # Build Docker images - only changed services
  # ===========================================

  build-mana-core-auth:
    name: Build mana-core-auth
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.mana-core-auth == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/mana-core-auth
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/mana-core-auth/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-mana-search:
    name: Build mana-search
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.mana-search == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/mana-search
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/mana-search/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-api-gateway:
    name: Build api-gateway
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.api-gateway == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/api-gateway
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/mana-api-gateway/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-manacore-web:
    name: Build manacore-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.manacore-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/manacore-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/manacore/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-chat-backend:
    name: Build chat-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.chat-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/chat-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/chat/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-chat-web:
    name: Build chat-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.chat-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/chat-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/chat/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-todo-backend:
    name: Build todo-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.todo-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/todo-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/todo/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-todo-web:
    name: Build todo-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.todo-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/todo-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/todo/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-calendar-backend:
    name: Build calendar-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.calendar-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/calendar-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/calendar/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-calendar-web:
    name: Build calendar-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.calendar-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/calendar-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/calendar/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-clock-backend:
    name: Build clock-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.clock-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/clock-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/clock/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-clock-web:
    name: Build clock-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.clock-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/clock-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/clock/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-contacts-backend:
    name: Build contacts-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.contacts-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/contacts-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/contacts/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-contacts-web:
    name: Build contacts-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.contacts-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/contacts-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/contacts/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-presi-backend:
    name: Build presi-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.presi-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/presi-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/presi/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-presi-web:
    name: Build presi-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.presi-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/presi-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/presi/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-storage-backend:
    name: Build storage-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.storage-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/storage-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/storage/apps/backend/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-storage-web:
    name: Build storage-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.storage-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/storage-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/storage/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-telegram-stats-bot:
    name: Build telegram-stats-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.telegram-stats-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/telegram-stats-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/telegram-stats-bot/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-nutriphi-backend:
    name: Build nutriphi-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.nutriphi-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/nutriphi-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/nutriphi/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-nutriphi-web:
    name: Build nutriphi-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.nutriphi-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/nutriphi-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/nutriphi/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-skilltree-backend:
    name: Build skilltree-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.skilltree-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/skilltree-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/skilltree/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-skilltree-web:
    name: Build skilltree-web
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.skilltree-web == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/skilltree-web
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/skilltree/apps/web/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # ===========================================
  # Matrix Bots
  # ===========================================

  build-matrix-mana-bot:
    name: Build matrix-mana-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-mana-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-mana-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-mana-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native dependencies
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-ollama-bot:
    name: Build matrix-ollama-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-ollama-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-ollama-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-ollama-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-stats-bot:
    name: Build matrix-stats-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-stats-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-stats-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-stats-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-project-doc-bot:
    name: Build matrix-project-doc-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-project-doc-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-project-doc-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-project-doc-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-todo-bot:
    name: Build matrix-todo-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-todo-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-todo-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-todo-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-calendar-bot:
    name: Build matrix-calendar-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-calendar-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-calendar-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-calendar-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-nutriphi-bot:
    name: Build matrix-nutriphi-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-nutriphi-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-nutriphi-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-nutriphi-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-zitare-bot:
    name: Build matrix-zitare-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-zitare-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-zitare-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-zitare-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-clock-bot:
    name: Build matrix-clock-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-clock-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-clock-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-clock-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-matrix-tts-bot:
    name: Build matrix-tts-bot
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.matrix-tts-bot == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/matrix-tts-bot
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: services/matrix-tts-bot/Dockerfile
          # Note: arm64 disabled due to QEMU emulation issues with native deps
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # ===========================================
  # Zitare Backend
  # ===========================================

  build-zitare-backend:
    name: Build zitare-backend
    runs-on: ubuntu-latest
    needs: detect-changes
    if: needs.detect-changes.outputs.zitare-backend == 'true'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository_owner }}/zitare-backend
          tags: type=raw,value=latest
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: apps/zitare/apps/backend/Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
