libpcp_web: accept NaN/Inf in series_pmAtomValue_conv_str on float/do… #438
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: macOS CI | |
| on: | |
| push: | |
| jobs: | |
| build: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| 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 install to settle | |
| run: sleep 3 | |
| - name: Install Homebrew deps | |
| id: install-brew-deps | |
| run: | | |
| PACKAGES=$(grep -v '^#' build/mac/brew-packages.txt | grep -v '^$' | tr '\n' ' ') | |
| echo "Installing: $PACKAGES" | |
| brew install $PACKAGES | |
| - 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 -verbose | |
| # 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 |