name: macOS CI
on:
  push:
jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ github.ref_name }}
      - name: Install Homebrew
        run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      - name: Wait for Homebrew to settle and clean up taps
        run: |
          # Wait for any background brew processes (auto-update, upgrade)
          # to finish before we run brew bundle
          echo "Waiting for background brew processes to finish..."
          while pgrep -qf 'brew (install|upgrade|update|fetch|cleanup)'; do
            echo "  brew process still running, waiting..."
            sleep 5
          done
          echo "No background brew processes detected."
          # Remove third-party taps pre-installed on the runner image
          # that we don't use — avoids Homebrew 6.x tap trust warnings
          for tap in $(brew tap | grep -v '^homebrew/'); do
            echo "Removing unused tap: $tap"
            brew untap "$tap" || true
          done
          # Upgrade pkg-config/pkgconf before brew bundle so it doesn't
          # race with other parallel installs that depend on pkgconf
          brew upgrade pkg-config 2>/dev/null || true
      - name: Install Homebrew deps
        id: install-brew-deps
        run: brew bundle
      - name: Set up Python build environment
        id: install-python-deps
        run: |
          python3 --version
          ./build/mac/setup-python-env.sh build/mac/requirements-test.txt
          python3 -c "import requests; print('requests', requests.__version__)"
      - name: Build on macOS
        id: Build
        run: |
          xcodebuild -version
          ./Makepkgs --ci
      # Validate PMID consistency
      - name: Validate PMID Consistency
        id: pmid-validation
        if: success()
        run: |
          echo "Validating PMID consistency across pmns, metrics.c, and darwin.h..."
          ./build/mac/test/integration/test-pmid-consistency.sh
      # Darwin PMDA Unit Tests (pre-installation)
      - name: Run Darwin PMDA Unit Tests
        id: unit-tests
        if: success()
        run: |
          echo "Running all PMDA unit tests..."
          cd build/mac/test
          ./run-unit-tests.sh
      - name: Debug on unit test failure
        if: failure() && steps.unit-tests.conclusion == 'failure'
        run: |
          echo "Unit tests failed. Checking build artifacts..."
          find . -name "pmda_darwin.dylib" -o -name "pmdadarwin"
          echo "Checking for dbpmda..."
          find . -name "dbpmda"
      - name: Debug on failure
        if: failure() && steps.Build.conclusion == 'failure'
        run: |
          cat /Users/runner/work/pcp/pcp/Logs/pcp
      - name: Debug on Python installation failure
        if: failure() && steps.install-python-deps.conclusion == 'failure'
        run: |
          echo "Python installation failed. Collecting debug info..."
          brew --version
          brew config
          brew doctor
          ls -la /usr/local/bin | grep python
          df -h
          brew list
      - name: Debug on brew dependency installation failure
        if: failure() && steps.install-brew-deps.conclusion == 'failure'
        run: |
          echo "Dependency installation failed. Collecting debug info..."
          brew --version
          brew config
          brew doctor
          ls -la /usr/local/bin | grep python
          df -h
          brew list
      # Start valkey before install so pmproxy can connect on startup
      - name: Start valkey
        run: brew services start valkey
      # Installation testing steps
      - name: Mount DMG and Install PKG
        if: success()
        id: install-test
        run: |
          # Find the generated DMG
          DMG_PATH=$(find pcp-**/build/mac -name "pcp-*.dmg" | head -1)
          echo "Found DMG: $DMG_PATH"

          # Mount the DMG
          MOUNT_OUTPUT=$(hdiutil attach "$DMG_PATH" | tail -1)
          VOLUME_PATH=$(echo "$MOUNT_OUTPUT" | awk '{print $3}')
          echo "Mounted at: $VOLUME_PATH"

          # Find and install the PKG
          PKG_PATH=$(find "$VOLUME_PATH" -name "*.pkg" | head -1)
          echo "Found PKG: $PKG_PATH"

          # Install (sudo is passwordless in GitHub Actions)
          sudo installer -pkg "$PKG_PATH" -target / -verbose -dumplog
      - name: Debug on install failure
        if: failure() && steps.install-test.conclusion == 'failure'
        run: |
          echo "=== /var/log/install.log (last 100 lines) ==="
          sudo tail -100 /var/log/install.log
      - name: Verify Installation
        if: success() && steps.install-test.conclusion == 'success'
        run: |
          # Check critical binaries exist (will fail build if not found)
          echo "Checking for installed binaries..."
          which pminfo && echo "✓ pminfo found at $(which pminfo)"
          which pmval && echo "✓ pmval found at $(which pmval)"
          which pmlogger && echo "✓ pmlogger found at $(which pmlogger)"

          # Check for expected directories (will fail build if not found)
          echo "Checking for expected directories..."
          test -d /etc/pcp && echo "✓ /etc/pcp exists"
          test -d /var/lib/pcp && echo "✓ /var/lib/pcp exists"
      # Darwin PMDA Integration Tests (post-installation)
      - name: Wait for pmcd to start
        if: success() && steps.install-test.conclusion == 'success'
        id: wait-for-pmcd
        run: |
          echo "=== Installation Verification ==="
          echo "PCP installation check:"
          which pmcd && echo "pmcd binary: $(which pmcd)" || echo "pmcd not in PATH"
          which pminfo && echo "pminfo binary: $(which pminfo)" || echo "pminfo not in PATH"
          which pcp && echo "pcp binary: $(which pcp)" || echo "pcp not in PATH"

          echo ""
          echo "Critical directories:"
          test -d /etc/pcp && echo "✓ /etc/pcp exists" || echo "✗ /etc/pcp MISSING"
          test -d /var/lib/pcp && echo "✓ /var/lib/pcp exists" || echo "✗ /var/lib/pcp MISSING"
          test -d /var/log/pcp && echo "✓ /var/log/pcp exists" || echo "✗ /var/log/pcp MISSING"
          test -d /var/log/pcp/pmcd && echo "✓ /var/log/pcp/pmcd exists" || echo "✗ /var/log/pcp/pmcd MISSING"

          echo ""
          echo "pmcd.conf contents:"
          cat /etc/pcp/pmcd/pmcd.conf 2>/dev/null || echo "pmcd.conf not found"

          echo ""
          echo "Checking launchd plist:"
          test -f /Library/LaunchDaemons/org.pcp.pmcd.plist && echo "✓ org.pcp.pmcd.plist exists" || echo "✗ org.pcp.pmcd.plist MISSING"

          echo ""
          echo "=== Waiting for pmcd service to start (post-install) ==="
          echo "The installer should have started pmcd via launchd..."

          TIMEOUT=60  # Wait up to 60 seconds
          ELAPSED=0
          INTERVAL=3

          while [ $ELAPSED -lt $TIMEOUT ]; do
            echo "Checking if pmcd is responding (${ELAPSED}s elapsed)..."

            # Check if pcp command works (like in .cirrus.yml)
            if pcp 2>/dev/null; then
              echo "✓ pmcd service is responding!"
              break
            fi

            # Also check if pminfo can connect
            if pminfo -h localhost -f hinv.ncpu 2>/dev/null; then
              echo "✓ pmcd is accepting connections!"
              break
            fi

            sleep $INTERVAL
            ELAPSED=$((ELAPSED + INTERVAL))
          done

          if [ $ELAPSED -ge $TIMEOUT ]; then
            echo "✗ ERROR: pmcd service failed to start within $TIMEOUT seconds"

            echo ""
            echo "=== Diagnostic Information ==="
            echo "pmcd process status:"
            pgrep pmcd && echo "pmcd is running (PID: $(pgrep pmcd))" || echo "pmcd NOT running"

            echo ""
            echo "pmcd full process details:"
            ps aux | grep pmcd | grep -v grep || echo "No pmcd process found"

            echo ""
            echo "pmcd command line:"
            sudo ps -p $(pgrep pmcd) -o pid,ppid,user,command 2>/dev/null || echo "Cannot get process details"

            echo ""
            echo "pmcd network connections:"
            sudo lsof -i -P | grep pmcd || echo "No network connections"

            echo ""
            echo "pmcd log (last 30 lines):"
            sudo tail -30 /var/log/pcp/pmcd/pmcd.log 2>/dev/null || echo "No pmcd.log"

            echo ""
            echo "launchd plist stdout/stderr:"
            sudo cat /var/log/pcp/pmcd/plist.stdout 2>/dev/null || echo "No plist.stdout"
            sudo cat /var/log/pcp/pmcd/plist.stderr 2>/dev/null || echo "No plist.stderr"

            exit 1
          fi

          echo ""
          echo "=== pmcd Service Verification ==="
          echo "pmcd process status:"
          pgrep pmcd && echo "✓ pmcd is running (PID: $(pgrep pmcd))" || echo "✗ pmcd failed to start"

          echo ""
          echo "pmcd command line:"
          sudo ps -p $(pgrep pmcd) -o pid,ppid,user,command || echo "Cannot get process details"

          echo ""
          echo "pmcd listening ports:"
          sudo lsof -i -P | grep pmcd || echo "No network connections found for pmcd"

          echo ""
          echo "Test localhost connectivity to pmcd port (44321):"
          nc -z localhost 44321 && echo "✓ Can connect to localhost:44321" || echo "✗ Cannot connect to localhost:44321"

          echo ""
          echo "Test 127.0.0.1 connectivity to pmcd port (44321):"
          nc -z 127.0.0.1 44321 && echo "✓ Can connect to 127.0.0.1:44321" || echo "✗ Cannot connect to 127.0.0.1:44321"
      - name: Run Darwin PMDA Integration Tests
        id: integration-tests
        if: success() && steps.wait-for-pmcd.conclusion == 'success'
        run: |
          echo "=== Python and pmrep debugging ==="
          echo "pmrep location:"
          which pmrep
          head -1 $(which pmrep)

          echo ""
          echo "Python versions available:"
          which python3 && python3 --version || echo "python3 not found"
          which python && python --version || echo "python not found"

          echo ""
          echo "Python sys.path for pmrep's Python:"
          $(head -1 $(which pmrep) | sed 's/#!//') -c "import sys; print('\n'.join(sys.path))"

          echo ""
          echo "Looking for pcp module:"
          find /usr/local -name "pcp.py" -o -name "pcp" -type d 2>/dev/null | grep -i python || echo "No pcp module found in /usr/local"
          cat python3-pcp.list || echo "Doesn't look like the Python3 installation bit triggered"

          echo ""
          echo "Check if pcp module is installed:"
          $(head -1 $(which pmrep) | sed 's/#!//') -c "import pcp; print('pcp module location:', pcp.__file__)" 2>&1 || echo "pcp module not importable"

          echo ""
          echo "Running Darwin PMDA integration tests..."
          cd build/mac/test/integration
          ./run-integration-tests.sh
      - name: Test pmstat with Darwin metrics
        if: success() && steps.integration-tests.conclusion == 'success'
        run: |
          echo "Testing pmstat output..."
          cd build/mac/test/integration
          ./test-pmstat.sh
      - name: Verify openmetrics PMDA enabled
        if: success() && steps.wait-for-pmcd.conclusion == 'success'
        run: |
          echo "Checking openmetrics PMDA status..."
          if pminfo openmetrics 2>/dev/null | head -5; then
            echo "openmetrics PMDA is active"
          else
            echo "WARNING: openmetrics PMDA not active (may need pmcd restart for .NeedInstall processing)"
            test -f /var/lib/pcp/pmdas/openmetrics/.NeedInstall && echo ".NeedInstall marker exists (pending)" || true
            test -f /var/lib/pcp/pmdas/openmetrics/.NeedInstall.failed && echo ".NeedInstall.failed exists (installation failed)" || true
            sudo grep -i "openmetrics\|NeedInstall\|pmda_setup" /var/log/pcp/pmcd/pmcd.log 2>/dev/null | tail -20 || true
          fi
      - name: Verify zeroconf pmlogconf configs installed
        if: success() && steps.install-test.conclusion == 'success'
        run: |
          echo "Checking for zeroconf pmlogconf configs..."
          if test -d /var/lib/pcp/config/pmlogconf/zeroconf; then
            echo "zeroconf configs installed:"
            ls /var/lib/pcp/config/pmlogconf/zeroconf/
          else
            echo "ERROR: zeroconf config directory not found"
            exit 1
          fi
      - name: Wait for pmproxy to start
        id: wait-for-pmproxy
        if: success() && steps.integration-tests.conclusion == 'success'
        run: |
          echo "=== Waiting for pmproxy service to start ==="
          echo "The installer should have started pmproxy via launchd..."

          TIMEOUT=60
          ELAPSED=0
          INTERVAL=3

          while [ $ELAPSED -lt $TIMEOUT ]; do
            echo "Checking pmproxy (${ELAPSED}s elapsed)..."

            # Check if pmproxy responds to ping
            if curl -s http://localhost:44322/series/ping 2>/dev/null | grep -q '"success":true'; then
              echo "✓ pmproxy is responding!"
              break
            fi

            sleep $INTERVAL
            ELAPSED=$((ELAPSED + INTERVAL))
          done

          echo ""
          echo "=== pmproxy log files debug ==="
          if [ -d /var/log/pcp/pmproxy ]; then
            echo "✓ pmproxy log directory exists"
            echo "Log directory contents:"
            ls -la /var/log/pcp/pmproxy/ 2>/dev/null || echo "Cannot list directory"

            echo ""
            for logfile in /var/log/pcp/pmproxy/*.log; do
              if [ -f "$logfile" ]; then
                echo "=== Contents of $logfile ==="
                sudo cat "$logfile" 2>/dev/null || echo "Cannot read $logfile"
                echo ""
              fi
            done
          else
            echo "✗ pmproxy log directory does not exist"
          fi

          if [ $ELAPSED -ge $TIMEOUT ]; then
            echo "✗ Timeout waiting for pmproxy"
            exit 1
          fi

          echo ""
          echo "=== pmproxy connectivity checks ==="
          nc -z localhost 44322 && echo "✓ Port 44322 open" || echo "✗ Port 44322 closed"

          echo ""
          echo "=== pmproxy process status ==="
          pgrep pmproxy && echo "✓ pmproxy running (PID: $(pgrep pmproxy))" || echo "✗ pmproxy not running"

          echo ""
          echo "pmproxy command line:"
          sudo ps -p $(pgrep pmproxy) -o pid,ppid,user,command 2>/dev/null || echo "Cannot get process details"

          echo ""
          echo "pmproxy listening ports:"
          sudo lsof -i -P | grep pmproxy || echo "No network connections found for pmproxy"
      - name: Debug on integration test failure
        if: failure() && (steps.integration-tests.conclusion == 'failure' || steps.wait-for-pmcd.conclusion == 'failure')
        run: |
          echo "Integration tests failed. Collecting diagnostics..."

          echo "=== PCP Configuration ==="
          pmconfig 2>&1 || echo "pmconfig failed"

          echo ""
          echo "=== pmcd.conf contents ==="
          cat /etc/pcp/pmcd/pmcd.conf 2>/dev/null || echo "pmcd.conf not found"

          echo ""
          echo "=== pmcd status ==="
          pgrep pmcd && echo "pmcd is running (PID: $(pgrep pmcd))" || echo "pmcd not running"

          echo ""
          echo "=== pmcd network connections ==="
          sudo lsof -i -P | grep pmcd || echo "No network connections for pmcd"

          echo ""
          echo "=== All listening ports ==="
          sudo lsof -i -P | grep LISTEN || echo "No listening ports found"

          echo ""
          echo "=== Connectivity tests ==="
          nc -z localhost 44321 && echo "✓ localhost:44321 is reachable" || echo "✗ localhost:44321 is NOT reachable"
          nc -z 127.0.0.1 44321 && echo "✓ 127.0.0.1:44321 is reachable" || echo "✗ 127.0.0.1:44321 is NOT reachable"

          echo ""
          echo "=== pmcd log (last 50 lines) ==="
          sudo tail -50 /var/log/pcp/pmcd/pmcd.log 2>/dev/null || echo "No pmcd log found"

          echo ""
          echo "=== darwin PMDA log (last 50 lines) ==="
          sudo tail -50 /var/log/pcp/pmcd/darwin.log 2>/dev/null || echo "No darwin PMDA log found"

          echo ""
          echo "=== darwin PMDA status ==="
          pminfo -f pmcd.agent.status 2>/dev/null | grep darwin || echo "Darwin PMDA not loaded"

          echo ""
          echo "=== Available PMDAs ==="
          ls -la /usr/local/lib/pcp/pmdas/ 2>/dev/null || ls -la /Library/PCP/pmdas/ 2>/dev/null || echo "PMDA directory not found"

          echo ""
          echo "=== Test simple metric with explicit localhost ==="
          pminfo -h localhost -f hinv.ncpu 2>&1 || echo "pminfo with localhost failed"

          echo ""
          echo "=== Test simple metric with explicit 127.0.0.1 ==="
          pminfo -h 127.0.0.1 -f hinv.ncpu 2>&1 || echo "pminfo with 127.0.0.1 failed"

          echo ""
          echo "=== Test simple metric with default host ==="
          pminfo -f hinv.ncpu 2>&1 || echo "pminfo with default host failed"

          echo ""
          echo "=== PCP environment variables ==="
          env | grep PCP || echo "No PCP env vars set"
      - name: Cleanup - Unmount DMG
        if: always()
        run: |
          # Unmount any mounted PCP volumes
          hdiutil detach /Volumes/pcp* 2>/dev/null || true
      # New steps for handling releases on version tags below
      - name: Check if version tag
        if: github.ref_type == 'tag'
        id: check_tag
        uses: actions-ecosystem/action-regex-match@v2
        with:
          text: ${{ github.ref_name }}
          regex: '^[0-9]+\.[0-9]+\.[0-9]+$'
          flags: g  # Global flag, but optional if just checking match
      - name: Generate Github Summary - version tag detected
        if: steps.check_tag.outputs.match != ''
        run: |
          echo "RELEASE DETECTED!" >> $GITHUB_STEP_SUMMARY
      - name: Generate Github Summary - no version tag
        if: steps.check_tag.outputs.match == ''
        run: |
          echo "Not a Release!" >> $GITHUB_STEP_SUMMARY
      - name: Release
        uses: softprops/action-gh-release@v3
        if: steps.check_tag.outputs.match != ''
        with:
          files: |
              pcp-**/build/mac/pcp-*.dmg
