Skip to content

Latest commit

Β 

History

History
490 lines (376 loc) Β· 14 KB

File metadata and controls

490 lines (376 loc) Β· 14 KB

PHP Extension Testing CI/CD Workflow

Overview

This document describes the automated PHP extension validation workflow that runs on every pull request to the main branch. The workflow is designed to ensure that new PHP versions and their extensions are properly configured and functional across multiple Windows environments.

Workflow Location

File: .github/workflows/php-extension-test.yml

Trigger: Automatically runs when a PR is opened, synchronized, or reopened against the main branch.


Current Status

βœ… What is Currently Working

The workflow infrastructure is fully operational and includes:

  1. Automated PR Detection

    • Triggers on PR creation, updates, and reopening
    • Monitors changes to releases.properties file
  2. Version Detection

    • Automatically detects new PHP versions added to releases.properties
    • Extracts version numbers from git diff
    • Parses version entries for testing
  3. Multi-Platform Testing Matrix

    • Tests across 4 Windows configurations:
      • Windows 10 AMD
      • Windows 10 Intel
      • Windows 11 AMD
      • Windows 11 Intel
    • Parallel execution with fail-fast: false to test all platforms
  4. Result Aggregation

    • Collects results from all platform tests
    • Generates visual status badges for each platform
    • Posts consolidated results as a single PR comment
  5. Artifact Management

    • Uploads test results as artifacts
    • Preserves results for debugging and analysis

βœ… Complete Implementation Status

ALL PHASES COMPLETED! The workflow now includes:

Phase 1: Basic PHP Validation βœ…

  1. Task 1.1: Download and Extract PHP

    • βœ… Parses releases.properties to get download URL
    • βœ… Downloads PHP 7z archive
    • βœ… Extracts to temporary directory
    • βœ… Verifies php.exe exists and is accessible
  2. Task 1.2: Verify PHP Executable

    • βœ… Runs php -v to verify version
    • βœ… Checks version output matches expected version
    • βœ… Detects startup errors or warnings
    • βœ… Tests basic PHP code execution
    • βœ… Displays PHP configuration (Thread Safety, Architecture, Compiler)

Phase 2: Extension Validation βœ…

  1. Task 2.1: Download Extensions

    • βœ… Parses exts.properties for extension URLs
    • βœ… Downloads all extensions (imagick, memcache, xdebug)
    • βœ… Extracts ZIP archives automatically
    • βœ… Verifies download integrity
  2. Task 2.2: Validate DLL Architecture

    • βœ… Reads PE headers from DLL files
    • βœ… Validates x64 (AMD64) architecture
    • βœ… Reports architecture mismatches
    • βœ… Saves validation results
  3. Task 2.3: Test Extension Loading

    • βœ… Tests loading with php -m
    • βœ… Handles both regular and Zend extensions
    • βœ… Verifies extensions appear in module list
    • βœ… Captures loading errors

Phase 3: Dependency Validation βœ…

  1. Task 3.1: Download Dependencies

    • βœ… Parses deps.properties for dependencies
    • βœ… Downloads ImageMagick and other dependencies
    • βœ… Extracts 7z and ZIP archives
    • βœ… Handles missing dependencies gracefully
  2. Task 3.2: Test Extensions with Dependencies

    • βœ… Adds dependency paths to system PATH
    • βœ… Tests imagick with ImageMagick present
    • βœ… Verifies extension classes are available
    • βœ… Tests memcache and xdebug functionality

Phase 4: Functional Testing βœ…

  1. Task 4.1: Basic Functionality Tests
    • βœ… Tests imagick image creation
    • βœ… Tests memcache function availability
    • βœ… Tests xdebug extension loading
    • βœ… Captures functional test results

Phase 5: Enhanced Error Reporting βœ…

  1. Comprehensive PR Comments

    • βœ… Shows results for all phases
    • βœ… Lists all tested extensions with status
    • βœ… Displays platform-specific results
    • βœ… Includes error messages and warnings
    • βœ… Updates existing comments instead of creating duplicates
  2. Detailed Artifacts

    • βœ… JSON results for each phase
    • βœ… Architecture validation data
    • βœ… Extension loading results
    • βœ… Dependency test results
    • βœ… Functional test outcomes

What Needs to Be Tested

Based on the repository structure (bin/php{version}/ directories), each PHP version includes:

1. PHP Extensions (exts.properties)

Each PHP version defines external extensions that must be validated:

  • imagick - ImageMagick image processing extension
  • memcache - Memcache caching extension
  • xdebug - Xdebug debugging extension

2. Dependencies (deps.properties)

External dependencies required by extensions:

  • ImageMagick - Binary dependency for imagick extension

3. Configuration Files

  • php.ini - PHP configuration with extension paths
  • bearsampp.conf - Bearsampp-specific configuration
  • pear.properties - PEAR package manager configuration

Required Implementation Tasks

Phase 1: Basic PHP Validation

Task 1.1: Download and Extract PHP

# Parse releases.properties to get download URL
# Download the PHP 7z archive
# Extract to temporary directory
# Verify php.exe exists and is executable

Validation Points:

  • Archive downloads successfully
  • Extraction completes without errors
  • PHP executable is present
  • PHP version matches expected version

Task 1.2: Verify PHP Executable

# Run: php -v
# Verify version output matches expected
# Check for any startup errors or warnings

Validation Points:

  • PHP starts without errors
  • Version string is correct
  • No missing DLL errors

Phase 2: Extension Validation

Task 2.1: Download Extensions

# Parse bin/php{version}/exts.properties
# Download each extension from specified URL
# Verify download integrity
# Extract if archived (e.g., imagick comes as .zip)

Validation Points:

  • All extension URLs are accessible
  • Downloads complete successfully
  • Archives extract properly
  • DLL files are present

Task 2.2: Validate DLL Architecture

# Use PowerShell to check DLL architecture
# Example:
$dllPath = "path/to/php_imagick.dll"
$peHeader = [System.Reflection.PortableExecutable.PEHeaders]::new(
    [System.IO.FileStream]::new($dllPath, [System.IO.FileMode]::Open)
)
$architecture = $peHeader.CoffHeader.Machine
# Verify: AMD64 for x64, I386 for x86

Validation Points:

  • Extension DLL architecture matches PHP architecture (x64)
  • Thread-safe (TS) vs non-thread-safe (NTS) compatibility
  • Visual Studio version compatibility (VS16, VS17, etc.)

Task 2.3: Test Extension Loading

# For each extension, test loading:
php -d extension=php_imagick.dll -m | Select-String "imagick"
php -d extension=php_memcache.dll -m | Select-String "memcache"
php -d zend_extension=php_xdebug.dll -m | Select-String "xdebug"

Validation Points:

  • Extension appears in php -m output
  • No error messages during loading
  • No missing dependency errors

Phase 3: Dependency Validation

Task 3.1: Download Dependencies

# Parse bin/php{version}/deps.properties
# Download ImageMagick portable package
# Extract to appropriate location

Validation Points:

  • Dependency downloads successfully
  • Extraction completes
  • Required DLLs are present

Task 3.2: Test Extension with Dependencies

# Set PATH to include dependency DLLs
$env:PATH = "path/to/imagemagick;$env:PATH"
# Test imagick extension loads with ImageMagick present
php -d extension=php_imagick.dll -r "echo class_exists('Imagick') ? 'OK' : 'FAIL';"

Validation Points:

  • Extension loads with dependencies
  • Extension classes/functions are available
  • No runtime errors

Phase 4: Functional Testing (Optional)

Task 4.1: Basic Functionality Tests

# Test imagick can create an image
php -d extension=php_imagick.dll -r "
  $img = new Imagick();
  $img->newImage(100, 100, new ImagickPixel('red'));
  echo 'imagick: OK';
"

# Test memcache extension functions exist
php -d extension=php_memcache.dll -r "
  echo function_exists('memcache_connect') ? 'memcache: OK' : 'FAIL';
"

# Test xdebug is loaded
php -d zend_extension=php_xdebug.dll -r "
  echo extension_loaded('xdebug') ? 'xdebug: OK' : 'FAIL';
"

Validation Points:

  • Extensions provide expected functionality
  • No runtime errors during basic operations
  • Classes and functions are accessible

Phase 5: Error Handling and Reporting

Task 5.1: Capture Detailed Errors

# Capture stderr and stdout
# Log all PHP warnings and errors
# Save failed DLL information

Task 5.2: Enhanced PR Comments

# Include in PR comment:
# - PHP version tested
# - Extension test results (pass/fail per extension)
# - Specific error messages
# - Download URLs that failed
# - Architecture mismatches
# - Missing dependencies

Example Enhanced Comment:

### βœ… PHP Extension Tests - Partial Success

#### PHP 8.3.27
- βœ… win10-amd: All tests passed
- ❌ win10-intel: imagick failed to load
  - Error: Missing CORE_RL_MagickCore_.dll
  - ImageMagick dependency not found
- βœ… win11-amd: All tests passed
- βœ… win11-intel: All tests passed

#### PHP 8.4.14
- βœ… All platforms: All tests passed

**Extensions Tested:**
- βœ… imagick (3.7.0)
- βœ… memcache (8.3.x)
- βœ… xdebug (3.5.0alpha2)

Implementation Priority

High Priority (Must Have)

  1. βœ… COMPLETED - Download and extract PHP version
  2. βœ… COMPLETED - Verify PHP executable runs
  3. βœ… COMPLETED - Download extensions from exts.properties
  4. βœ… COMPLETED - Validate DLL architecture
  5. βœ… COMPLETED - Test extension loading with php -m

Medium Priority (Should Have)

  1. βœ… COMPLETED - Download and validate dependencies
  2. βœ… COMPLETED - Test extensions with dependencies present
  3. βœ… COMPLETED - Enhanced error reporting in PR comments
  4. βœ… COMPLETED - Upload failed artifacts for debugging

Low Priority (Nice to Have)

  1. βœ… COMPLETED - Basic functionality tests per extension
  2. β­• Performance benchmarks (future enhancement)
  3. β­• Memory leak detection (future enhancement)
  4. β­• Compatibility matrix documentation (future enhancement)

Testing Workflow Locally

To test the validation logic locally before committing:

# 1. Navigate to module-php directory
cd E:\Bearsampp-development\module-php

# 2. Get a PHP version from releases.properties
$version = "8.3.27"
$url = (Get-Content releases.properties | Select-String "^$version =").Line.Split('=')[1].Trim()

# 3. Download and extract
Invoke-WebRequest -Uri $url -OutFile "php-$version.7z"
7z x "php-$version.7z" -o"test-php-$version"

# 4. Test PHP
& "test-php-$version\php.exe" -v

# 5. Download and test extensions
$exts = Get-Content "bin\php$version\exts.properties"
# ... continue with extension testing

Architecture Validation Script

Here's a PowerShell script to validate DLL architecture (to be integrated into workflow):

function Test-DllArchitecture {
    param(
        [string]$DllPath,
        [string]$ExpectedArch = "AMD64"  # or "I386" for x86
    )
    
    try {
        $fs = [System.IO.FileStream]::new($DllPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
        $br = [System.IO.BinaryReader]::new($fs)
        
        # Read DOS header
        $dosHeader = $br.ReadBytes(64)
        $peOffset = [BitConverter]::ToInt32($dosHeader, 60)
        
        # Seek to PE header
        $fs.Seek($peOffset, [System.IO.SeekOrigin]::Begin) | Out-Null
        $peSignature = $br.ReadBytes(4)
        
        # Read COFF header
        $machine = $br.ReadUInt16()
        
        $fs.Close()
        
        $arch = switch ($machine) {
            0x014c { "I386" }   # x86
            0x8664 { "AMD64" }  # x64
            default { "UNKNOWN" }
        }
        
        return @{
            Success = ($arch -eq $ExpectedArch)
            Detected = $arch
            Expected = $ExpectedArch
        }
    }
    catch {
        return @{
            Success = $false
            Error = $_.Exception.Message
        }
    }
}

# Usage:
$result = Test-DllArchitecture -DllPath "php_imagick.dll" -ExpectedArch "AMD64"
if ($result.Success) {
    Write-Host "βœ… DLL architecture is correct: $($result.Detected)"
} else {
    Write-Host "❌ DLL architecture mismatch: Expected $($result.Expected), got $($result.Detected)"
}

File Structure Reference

Each PHP version in the repository follows this structure:

bin/
└── php{version}/
    β”œβ”€β”€ bearsampp.conf      # Bearsampp configuration
    β”œβ”€β”€ deps.properties     # External dependencies (ImageMagick, etc.)
    β”œβ”€β”€ exts.properties     # PHP extensions (imagick, memcache, xdebug)
    ���── pear.properties     # PEAR configuration
    β”œβ”€β”€ php.ini             # PHP configuration
    └── deps/
        └── README.txt      # Dependency documentation

Example for PHP 8.3.27:

  • bin/php8.3.27/exts.properties - Lists 3 extensions
  • bin/php8.3.27/deps.properties - Lists ImageMagick dependency
  • bin/php8.3.27/php.ini - Contains extension configuration

Related Documentation


Contributing

To contribute to the extension testing workflow:

  1. Review this document to understand current status
  2. Implement one or more tasks from the priority list
  3. Test locally using the provided scripts
  4. Submit a PR with your changes
  5. The workflow will run on your PR (though validation is incomplete)

Questions or Issues?

  • Workflow Issues: Check .github/workflows/php-extension-test.yml
  • Extension Issues: Check bin/php{version}/exts.properties
  • Dependency Issues: Check bin/php{version}/deps.properties
  • General Issues: Report on Bearsampp repository

Last Updated: 2025-02-18
Status: πŸŽ‰ ALL PHASES COMPLETE - Full CI/CD testing workflow operational!