Skip to content

fix: [cherry-pick] update google/protobuf v4.33.4 -> v4.33.6 (GHSA-p2gh-cfq4-4wjc) #126

fix: [cherry-pick] update google/protobuf v4.33.4 -> v4.33.6 (GHSA-p2gh-cfq4-4wjc)

fix: [cherry-pick] update google/protobuf v4.33.4 -> v4.33.6 (GHSA-p2gh-cfq4-4wjc) #126

Workflow file for this run

name: OpenTelemetry PHP Agent Tests
on: pull_request
env:
OTEL_COLLECTOR_GRPC_PORT: 4317
OTEL_COLLECTOR_HTTP_PORT: 4318
jobs:
binary-checks:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- php-version: "8.1"
architecture: amd64
- php-version: "8.1"
architecture: arm64
- php-version: "8.2"
architecture: amd64
- php-version: "8.2"
architecture: arm64
- php-version: "8.3"
architecture: amd64
- php-version: "8.3"
architecture: arm64
- php-version: "8.4"
architecture: amd64
- php-version: "8.4"
architecture: arm64
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checking binary output
run: |
BINARY_OUTPUT=$(file ${{ matrix.php-version }}/bin/${{ matrix.architecture }}/opentelemetry.so)
echo "Binary output: $BINARY_OUTPUT"
# Verify architecture matches expected
if [[ "${{ matrix.architecture }}" == "amd64" ]]; then
if ! echo "$BINARY_OUTPUT" | grep -q "x86-64"; then
echo "❌ Expected x86-64 architecture for amd64, but got: $BINARY_OUTPUT"
exit 1
fi
elif [[ "${{ matrix.architecture }}" == "arm64" ]]; then
if ! echo "$BINARY_OUTPUT" | grep -q "ARM aarch64"; then
echo "❌ Expected ARM aarch64 architecture for arm64, but got: $BINARY_OUTPUT"
exit 1
fi
fi
echo "✅ Architecture verification passed for PHP ${{ matrix.php-version }} on ${{ matrix.architecture }}"
e2e-tests:
needs: binary-checks
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Symfony: v2.4.0 (PHP 8.1+), v2.9.0 (PHP 8.2+), v3.0.0 (PHP 8.4+)
- { php-version: "8.1", framework: symfony, framework-version: "v2.4.0" }
- { php-version: "8.2", framework: symfony, framework-version: "v2.9.0" }
- { php-version: "8.3", framework: symfony, framework-version: "v2.9.0" }
- { php-version: "8.4", framework: symfony, framework-version: "v3.0.0" }
# Laravel: requires PHP 8.2+
- { php-version: "8.2", framework: laravel, framework-version: "" }
- { php-version: "8.3", framework: laravel, framework-version: "" }
- { php-version: "8.4", framework: laravel, framework-version: "" }
# CakePHP: 5.0 supports PHP 8.1+
- { php-version: "8.1", framework: cakephp, framework-version: "~5.0" }
- { php-version: "8.2", framework: cakephp, framework-version: "~5.0" }
- { php-version: "8.3", framework: cakephp, framework-version: "~5.0" }
- { php-version: "8.4", framework: cakephp, framework-version: "~5.0" }
# Yii: 2.x supports PHP 7.4+
- { php-version: "8.1", framework: yii, framework-version: "" }
- { php-version: "8.2", framework: yii, framework-version: "" }
- { php-version: "8.3", framework: yii, framework-version: "" }
- { php-version: "8.4", framework: yii, framework-version: "" }
env:
ARCHITECTURE: "amd64"
SERVICE_NAME: "${{ matrix.framework }}-${{ matrix.php-version }}"
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
extensions: intl, iconv, pdo_sqlite, mbstring, xml, curl, ctype, tokenizer, dom, fileinfo, simplexml
tools: composer:v2
- name: Setup Docker
run: |
sudo systemctl start docker
sudo systemctl status docker || (echo "⚠️ Docker is not running" && exit 1)
- name: Setup OpenTelemetry Collector
run: |
cat > collector-config.yaml << 'EOF'
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [debug]
EOF
- name: Start OpenTelemetry Collector
run: |
docker run -d \
--name otel-collector \
-p 4317:4317 \
-p 4318:4318 \
-v $(pwd)/collector-config.yaml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector:latest \
--config /etc/otelcol/config.yaml
- name: Verify OpenTelemetry Collector is running
run: |
echo "Checking if collector is running..."
for i in {1..30}; do
if docker ps | grep -q otel-collector && netstat -tlnp 2>/dev/null | grep -q ":4317\|:4318"; then
echo "✅ Collector is running"
break
fi
if [ "$i" = 30 ]; then
echo "❌ Collector is not running after 30 attempts"
exit 1
fi
echo "Attempt $i/30: Waiting for collector..."
sleep 2
done
- name: Verify OpenTelemetry Collector is ready
run: |
echo "Checking collector logs for readiness..."
for i in {1..30}; do
COLLECTOR_LOGS=$(docker logs otel-collector 2>&1 || (echo "⚠️ Docker logs failed" && exit 1))
if echo "$COLLECTOR_LOGS" | grep -q "Starting GRPC server" && \
echo "$COLLECTOR_LOGS" | grep -q "Starting HTTP server" && \
echo "$COLLECTOR_LOGS" | grep -q "Everything is ready"; then
echo "✅ Collector is ready"
break
fi
if [ "$i" = 30 ]; then
echo "❌ Collector is not ready after 30 attempts"
exit 1
fi
echo "Attempt $i/30: Waiting for readiness..."
sleep 2
done
- name: Configure Agent
run: |
# Move architecture files
mv ${{ matrix.php-version }}/bin/${{ env.ARCHITECTURE }}/* ${{ matrix.php-version }}/
rm -rf ${{ matrix.php-version }}/bin
# Update paths in configuration files
sed -i "s|/var/odigos/php/${{ matrix.php-version }}|$(pwd)/${{ matrix.php-version }}|g" ${{ matrix.php-version }}/opentelemetry.ini
# Show the final configuration
echo "=== OpenTelemetry INI Configuration ==="
cat ${{ matrix.php-version }}/opentelemetry.ini
# Verify the extension is loadable
# Note: trailing colon means "load custom config FIRST, then default config"
# This ensures phar and other default extensions remain available
echo ""
echo "=== Verifying OpenTelemetry extension ==="
PHP_INI_SCAN_DIR=$(pwd)/${{ matrix.php-version }}: php -m | grep opentelemetry || (echo "⚠️ OpenTelemetry extension not loaded" && exit 1)
echo "✅ OpenTelemetry extension loaded"
# NOTE: PHP_INI_SCAN_DIR is NOT persisted here — the agent's auto_prepend_file
# would interfere with Composer operations in subsequent framework setup steps.
# It is set in the "Start Application" step instead.
- name: Setup Symfony Application
if: matrix.framework == 'symfony'
env:
APP_ENV: prod
run: |
git clone --depth 1 --branch ${{ matrix.framework-version }} https://github.com/symfony/demo.git app
cd app
# Install dependencies (no dev deps needed - demo ships with pre-seeded database)
composer install --no-dev --optimize-autoloader --no-scripts
# Copy .env.local.demo to .env.local if it exists (v2.9.0+ moved APP_SECRET there)
# This must happen BEFORE composer dump-env to include the secret
if [ -f .env.local.demo ]; then
cp .env.local.demo .env.local
fi
# Generate production environment file
composer dump-env prod
# Run post-install scripts (cache:clear, assets:install)
composer run-script --no-dev post-install-cmd || true
# v3.0.0+ needs importmap and sass build (ignore errors for older versions)
php bin/console importmap:install --env=prod 2>/dev/null || true
php bin/console sass:build --env=prod 2>/dev/null || true
# Warmup cache for production
php bin/console cache:warmup --env=prod --no-debug
# Note: No database setup needed - Symfony Demo ships with pre-seeded data/database.sqlite
- name: Setup Laravel Application
if: matrix.framework == 'laravel'
run: |
composer create-project --prefer-dist laravel/laravel app
cd app
touch database/database.sqlite
sed -i 's/DB_CONNECTION=.*/DB_CONNECTION=sqlite/' .env
sed -i 's|DB_DATABASE=.*|DB_DATABASE='$(pwd)'/database/database.sqlite|' .env
php artisan config:clear
php artisan cache:clear
- name: Setup CakePHP Application
if: matrix.framework == 'cakephp'
run: |
composer create-project --prefer-dist cakephp/app:"${{ matrix.framework-version }}" app
- name: Setup Yii Application
if: matrix.framework == 'yii'
run: |
composer create-project --prefer-dist yiisoft/yii2-app-basic app
- name: Start Application
run: |
# Activate the agent INI now (after framework setup steps are done).
# This was deferred from Configure Agent to avoid the auto_prepend_file
# interfering with Composer operations during framework setup.
echo "PHP_INI_SCAN_DIR=$(pwd)/${{ matrix.php-version }}:" >> $GITHUB_ENV
export PHP_INI_SCAN_DIR="$(pwd)/${{ matrix.php-version }}:"
# Determine the public directory and test route based on framework
case "${{ matrix.framework }}" in
symfony)
PUBLIC_DIR="app/public"
TEST_ROUTE="/en/blog/"
;;
laravel)
PUBLIC_DIR="app/public"
TEST_ROUTE="/"
;;
cakephp)
PUBLIC_DIR="app/webroot"
TEST_ROUTE="/"
;;
yii)
PUBLIC_DIR="app/web"
TEST_ROUTE="/"
;;
esac
# Export for use in later steps
echo "PUBLIC_DIR=$PUBLIC_DIR" >> $GITHUB_ENV
echo "TEST_ROUTE=$TEST_ROUTE" >> $GITHUB_ENV
# Verify extension is still loadable before starting server
echo "Pre-flight check: verifying OpenTelemetry extension..."
php -m | grep opentelemetry || (echo "⚠️ Extension not loaded!" && php --ini && exit 1)
# Start PHP built-in server with OTel environment variables
OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_SERVICE_NAME=${{ env.SERVICE_NAME }} \
OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:${{ env.OTEL_COLLECTOR_HTTP_PORT }} \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
php -S localhost:8000 -t $PUBLIC_DIR &
echo $! > php.pid
echo "Started PHP server with PID $(cat php.pid) serving $PUBLIC_DIR"
- name: Generate Traffic
run: |
echo "Waiting for server to start..."
for i in {1..30}; do
if curl -sfL http://localhost:8000${{ env.TEST_ROUTE }} > /dev/null 2>&1; then
echo "✅ Server is ready"
break
fi
if [ "$i" = 30 ]; then
echo "❌ Server is not ready after 30 attempts"
echo "PHP error log (if exists):"
cat /var/log/php*.log 2>/dev/null || true
curl -v http://localhost:8000${{ env.TEST_ROUTE }} 2>&1 || true
exit 1
fi
echo "Attempt $i/30: Server not ready yet..."
sleep 2
done
# Generate additional traffic to ensure traces are captured
echo "Generating additional traffic..."
for i in {1..5}; do
curl -sfL http://localhost:8000${{ env.TEST_ROUTE }} > /dev/null 2>&1 || true
sleep 1
done
# Wait for traces to be exported
echo "Waiting for trace export..."
sleep 10
- name: Verify Trace Generation
run: |
echo "Verifying trace generation for ${{ matrix.framework }} on PHP ${{ matrix.php-version }}..."
COLLECTOR_LOGS=$(docker logs otel-collector 2>&1 || (echo "⚠️ Docker logs failed" && exit 1))
SPAN_ATTRIBUTE="service.name: Str(${{ env.SERVICE_NAME }})"
if echo "$COLLECTOR_LOGS" | grep -q "$SPAN_ATTRIBUTE"; then
echo "✅ Traces detected in collector logs"
echo "$COLLECTOR_LOGS" | grep -A5 -B5 "$SPAN_ATTRIBUTE" | head -30
else
echo "❌ No traces found in collector logs"
echo ""
echo "=== Collector logs ==="
echo "$COLLECTOR_LOGS"
echo ""
echo "=== PHP Configuration ==="
php --ini
echo ""
echo "=== Loaded Extensions ==="
php -m | grep -i otel || echo "No otel extensions found"
exit 1
fi