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.
File: .github/workflows/php-extension-test.yml
Trigger: Automatically runs when a PR is opened, synchronized, or reopened against the main branch.
The workflow infrastructure is fully operational and includes:
-
Automated PR Detection
- Triggers on PR creation, updates, and reopening
- Monitors changes to
releases.propertiesfile
-
Version Detection
- Automatically detects new PHP versions added to
releases.properties - Extracts version numbers from git diff
- Parses version entries for testing
- Automatically detects new PHP versions added to
-
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: falseto test all platforms
- Tests across 4 Windows configurations:
-
Result Aggregation
- Collects results from all platform tests
- Generates visual status badges for each platform
- Posts consolidated results as a single PR comment
-
Artifact Management
- Uploads test results as artifacts
- Preserves results for debugging and analysis
ALL PHASES COMPLETED! The workflow now includes:
Phase 1: Basic PHP Validation β
-
Task 1.1: Download and Extract PHP
- β
Parses
releases.propertiesto get download URL - β Downloads PHP 7z archive
- β Extracts to temporary directory
- β
Verifies
php.exeexists and is accessible
- β
Parses
-
Task 1.2: Verify PHP Executable
- β
Runs
php -vto 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)
- β
Runs
Phase 2: Extension Validation β
-
Task 2.1: Download Extensions
- β
Parses
exts.propertiesfor extension URLs - β Downloads all extensions (imagick, memcache, xdebug)
- β Extracts ZIP archives automatically
- β Verifies download integrity
- β
Parses
-
Task 2.2: Validate DLL Architecture
- β Reads PE headers from DLL files
- β Validates x64 (AMD64) architecture
- β Reports architecture mismatches
- β Saves validation results
-
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
- β
Tests loading with
Phase 3: Dependency Validation β
-
Task 3.1: Download Dependencies
- β
Parses
deps.propertiesfor dependencies - β Downloads ImageMagick and other dependencies
- β Extracts 7z and ZIP archives
- β Handles missing dependencies gracefully
- β
Parses
-
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 β
- 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 β
-
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
-
Detailed Artifacts
- β JSON results for each phase
- β Architecture validation data
- β Extension loading results
- β Dependency test results
- β Functional test outcomes
Based on the repository structure (bin/php{version}/ directories), each PHP version includes:
Each PHP version defines external extensions that must be validated:
- imagick - ImageMagick image processing extension
- memcache - Memcache caching extension
- xdebug - Xdebug debugging extension
External dependencies required by extensions:
- ImageMagick - Binary dependency for imagick extension
php.ini- PHP configuration with extension pathsbearsampp.conf- Bearsampp-specific configurationpear.properties- PEAR package manager configuration
# Parse releases.properties to get download URL
# Download the PHP 7z archive
# Extract to temporary directory
# Verify php.exe exists and is executableValidation Points:
- Archive downloads successfully
- Extraction completes without errors
- PHP executable is present
- PHP version matches expected version
# Run: php -v
# Verify version output matches expected
# Check for any startup errors or warningsValidation Points:
- PHP starts without errors
- Version string is correct
- No missing DLL errors
# 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
# 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 x86Validation Points:
- Extension DLL architecture matches PHP architecture (x64)
- Thread-safe (TS) vs non-thread-safe (NTS) compatibility
- Visual Studio version compatibility (VS16, VS17, etc.)
# 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 -moutput - No error messages during loading
- No missing dependency errors
# Parse bin/php{version}/deps.properties
# Download ImageMagick portable package
# Extract to appropriate locationValidation Points:
- Dependency downloads successfully
- Extraction completes
- Required DLLs are present
# 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
# 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
# Capture stderr and stdout
# Log all PHP warnings and errors
# Save failed DLL information# Include in PR comment:
# - PHP version tested
# - Extension test results (pass/fail per extension)
# - Specific error messages
# - Download URLs that failed
# - Architecture mismatches
# - Missing dependenciesExample 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)- β COMPLETED - Download and extract PHP version
- β COMPLETED - Verify PHP executable runs
- β COMPLETED - Download extensions from exts.properties
- β COMPLETED - Validate DLL architecture
- β
COMPLETED - Test extension loading with
php -m
- β COMPLETED - Download and validate dependencies
- β COMPLETED - Test extensions with dependencies present
- β COMPLETED - Enhanced error reporting in PR comments
- β COMPLETED - Upload failed artifacts for debugging
- β COMPLETED - Basic functionality tests per extension
- β Performance benchmarks (future enhancement)
- β Memory leak detection (future enhancement)
- β Compatibility matrix documentation (future enhancement)
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 testingHere'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)"
}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 extensionsbin/php8.3.27/deps.properties- Lists ImageMagick dependencybin/php8.3.27/php.ini- Contains extension configuration
- Workflow File:
.github/workflows/php-extension-test.yml - Build System: .gradle-docs/README.md
- Task Reference: .gradle-docs/TASKS.md
- Configuration Guide: .gradle-docs/CONFIGURATION.md
To contribute to the extension testing workflow:
- Review this document to understand current status
- Implement one or more tasks from the priority list
- Test locally using the provided scripts
- Submit a PR with your changes
- The workflow will run on your PR (though validation is incomplete)
- 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!