diff --git a/.github/workflows/phpmyadmin-test.yml b/.github/workflows/phpmyadmin-test.yml new file mode 100644 index 0000000..260b3f5 --- /dev/null +++ b/.github/workflows/phpmyadmin-test.yml @@ -0,0 +1,1070 @@ +name: phpMyAdmin Module Tests + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + branches: + - main + workflow_dispatch: + inputs: + test_mode: + description: 'Test mode' + required: true + default: 'latest' + type: choice + options: + - latest + - specific + version: + description: 'Specific version to test (only used if test_mode is "specific")' + required: false + type: string + +jobs: + detect-versions: + name: Detect Versions to Test + runs-on: ubuntu-latest + outputs: + versions: ${{ steps.get-versions.outputs.versions }} + has-changes: ${{ steps.get-versions.outputs.has-changes }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get phpMyAdmin Versions + id: get-versions + run: | + set -e + + echo "=== Detecting phpMyAdmin Versions to Test ===" + + # Function to extract versions from releases.properties + get_versions_from_properties() { + if [ ! -f "releases.properties" ]; then + echo "āŒ ERROR: releases.properties not found" + exit 1 + fi + + # Extract version numbers (lines starting with digits) + grep "^[0-9]" releases.properties | cut -d'=' -f1 | tr -d ' ' | sort -V -r + } + + # Determine which versions to test based on trigger type + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "šŸ“‹ Trigger: Manual workflow dispatch" + + if [ "${{ github.event.inputs.test_mode }}" = "specific" ]; then + VERSION="${{ github.event.inputs.version }}" + if [ -z "$VERSION" ]; then + echo "āŒ ERROR: Version not specified for specific test mode" + exit 1 + fi + + echo "šŸŽÆ Testing specific version: $VERSION" + + # Verify version exists in releases.properties + if ! grep -q "^${VERSION} *=" releases.properties; then + echo "āŒ ERROR: Version $VERSION not found in releases.properties" + echo "Available versions:" + get_versions_from_properties + exit 1 + fi + + VERSIONS="[\"$VERSION\"]" + HAS_CHANGES="true" + else + echo "šŸ“Š Testing latest 5 versions" + VERSIONS=$(get_versions_from_properties | head -5 | jq -R -s -c 'split("\n") | map(select(length > 0))') + HAS_CHANGES="true" + fi + elif [ "${{ github.event_name }}" = "pull_request" ]; then + echo "šŸ“‹ Trigger: Pull Request #${{ github.event.pull_request.number }}" + + # Get the base branch for comparison + BASE_REF="${{ github.event.pull_request.base.ref }}" + HEAD_REF="${{ github.event.pull_request.head.ref }}" + + echo "Comparing $HEAD_REF against $BASE_REF" + + # Primary Method: Check for changed files in /bin directory + echo "šŸ” Checking for version changes in /bin directory..." + CHANGED_BIN_DIRS=$(git diff --name-only origin/$BASE_REF...HEAD | grep "^bin/" | cut -d'/' -f2 | sort -u) + + if [ -n "$CHANGED_BIN_DIRS" ]; then + echo "āœ… Found changes in /bin directory" + echo "Changed directories:" + echo "$CHANGED_BIN_DIRS" | sed 's/^/ - /' + + # Extract version numbers from directory names (e.g., phpmyadmin5.2.3 -> 5.2.3) + VERSIONS_FROM_BIN="" + while IFS= read -r dir; do + # Extract version pattern from directory name + # Supports patterns like: phpmyadmin5.2.3, phpmyadmin-5.2.3, 5.2.3 + VERSION=$(echo "$dir" | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1) + if [ -n "$VERSION" ]; then + # Verify version exists in releases.properties + if grep -q "^${VERSION} *=" releases.properties; then + echo " āœ… $VERSION (from $dir) exists in releases.properties" + VERSIONS_FROM_BIN="${VERSIONS_FROM_BIN}${VERSION}\n" + else + echo " āš ļø $VERSION (from $dir) not found in releases.properties, skipping" + fi + fi + done <<< "$CHANGED_BIN_DIRS" + + if [ -n "$VERSIONS_FROM_BIN" ]; then + echo "šŸ“¦ Versions detected from /bin directory:" + echo -e "$VERSIONS_FROM_BIN" | sed '/^$/d' | sed 's/^/ - /' + VERSIONS=$(echo -e "$VERSIONS_FROM_BIN" | sed '/^$/d' | sort -V -r | uniq | jq -R -s -c 'split("\n") | map(select(length > 0))') + HAS_CHANGES="true" + else + echo "āš ļø No valid versions extracted from /bin directory changes" + echo "šŸ“Š Falling back to PR title detection..." + + # Fallback Method: Check PR title for version numbers + PR_TITLE="${{ github.event.pull_request.title }}" + echo "PR Title: $PR_TITLE" + + VERSIONS_FROM_TITLE=$(echo "$PR_TITLE" | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | sort -V -r | uniq) + + if [ -n "$VERSIONS_FROM_TITLE" ]; then + echo "šŸ” Version numbers found in PR title:" + echo "$VERSIONS_FROM_TITLE" | sed 's/^/ - /' + + # Verify these versions exist in releases.properties + VALID_VERSIONS="" + while IFS= read -r version; do + if grep -q "^${version} *=" releases.properties; then + echo " āœ… $version exists in releases.properties" + VALID_VERSIONS="${VALID_VERSIONS}${version}\n" + else + echo " āš ļø $version not found in releases.properties, skipping" + fi + done <<< "$VERSIONS_FROM_TITLE" + + if [ -n "$VALID_VERSIONS" ]; then + VERSIONS=$(echo -e "$VALID_VERSIONS" | sed '/^$/d' | jq -R -s -c 'split("\n") | map(select(length > 0))') + HAS_CHANGES="true" + else + echo "āš ļø No valid versions found in PR title" + echo "ā­ļø Skipping tests - no versions to test" + VERSIONS="[]" + HAS_CHANGES="false" + fi + else + echo "ā„¹ļø No version numbers found in PR title" + echo "ā­ļø Skipping tests - no versions to test" + VERSIONS="[]" + HAS_CHANGES="false" + fi + fi + else + echo "ā„¹ļø No changes detected in /bin directory" + echo "šŸ“Š Falling back to PR title detection..." + + # Fallback Method: Check PR title for version numbers + PR_TITLE="${{ github.event.pull_request.title }}" + echo "PR Title: $PR_TITLE" + + VERSIONS_FROM_TITLE=$(echo "$PR_TITLE" | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | sort -V -r | uniq) + + if [ -n "$VERSIONS_FROM_TITLE" ]; then + echo "šŸ” Version numbers found in PR title:" + echo "$VERSIONS_FROM_TITLE" | sed 's/^/ - /' + + # Verify these versions exist in releases.properties + VALID_VERSIONS="" + while IFS= read -r version; do + if grep -q "^${version} *=" releases.properties; then + echo " āœ… $version exists in releases.properties" + VALID_VERSIONS="${VALID_VERSIONS}${version}\n" + else + echo " āš ļø $version not found in releases.properties, skipping" + fi + done <<< "$VERSIONS_FROM_TITLE" + + if [ -n "$VALID_VERSIONS" ]; then + VERSIONS=$(echo -e "$VALID_VERSIONS" | sed '/^$/d' | jq -R -s -c 'split("\n") | map(select(length > 0))') + HAS_CHANGES="true" + else + echo "āš ļø No valid versions found in PR title" + echo "ā­ļø Skipping tests - no versions to test" + VERSIONS="[]" + HAS_CHANGES="false" + fi + else + echo "ā„¹ļø No version numbers found in PR title" + echo "ā­ļø Skipping tests - no versions to test" + VERSIONS="[]" + HAS_CHANGES="false" + fi + fi + else + echo "ā„¹ļø Unknown trigger type, testing latest 5 versions" + VERSIONS=$(get_versions_from_properties | head -5 | jq -R -s -c 'split("\n") | map(select(length > 0))') + HAS_CHANGES="true" + fi + + echo "" + echo "=== Test Configuration ===" + echo "Versions to test: $VERSIONS" + echo "Has changes: $HAS_CHANGES" + + echo "versions=$VERSIONS" >> $GITHUB_OUTPUT + echo "has-changes=$HAS_CHANGES" >> $GITHUB_OUTPUT + + test-phpmyadmin: + name: Test phpMyAdmin ${{ matrix.version }} + needs: detect-versions + if: needs.detect-versions.outputs.has-changes == 'true' + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + version: ${{ fromJson(needs.detect-versions.outputs.versions) }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Create test directory + run: | + New-Item -ItemType Directory -Force -Path "test-phpmyadmin" + New-Item -ItemType Directory -Force -Path "test-results" + + - name: Phase 1.1 - Download and Extract phpMyAdmin + id: download-phpmyadmin + continue-on-error: true + run: | + $ErrorActionPreference = "Continue" + $version = "${{ matrix.version }}" + + Write-Host "=== Phase 1.1: Download and Extract phpMyAdmin $version ===" + + # Read releases.properties + $releasesFile = "releases.properties" + if (-not (Test-Path $releasesFile)) { + Write-Host "āŒ ERROR: releases.properties not found" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=releases.properties not found" >> $env:GITHUB_OUTPUT + exit 1 + } + + # Find the download URL for the specified version + $downloadUrl = $null + Get-Content $releasesFile | ForEach-Object { + if ($_ -match "^$version\s*=\s*(.+)$") { + $downloadUrl = $matches[1].Trim() + } + } + + if (-not $downloadUrl) { + Write-Host "āŒ ERROR: Version $version not found in releases.properties" + Write-Host "Available versions in releases.properties:" + Get-Content $releasesFile | Select-String "^[0-9]" | ForEach-Object { Write-Host " - $($_.Line.Split('=')[0].Trim())" } + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Version $version not found in releases.properties" >> $env:GITHUB_OUTPUT + exit 1 + } + + Write-Host "Download URL: $downloadUrl" + + try { + $fileName = [System.IO.Path]::GetFileName($downloadUrl) + $downloadPath = Join-Path "test-phpmyadmin" $fileName + + Write-Host "Downloading phpMyAdmin $version..." + Write-Host "Target file: $downloadPath" + + try { + Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadPath -UseBasicParsing -TimeoutSec 300 + } catch { + Write-Host "āŒ ERROR: Download failed!" + Write-Host "Error details: $($_.Exception.Message)" + Write-Host "Status Code: $($_.Exception.Response.StatusCode.value__)" + Write-Host "URL attempted: $downloadUrl" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Download failed: $($_.Exception.Message)" >> $env:GITHUB_OUTPUT + exit 1 + } + + if (Test-Path $downloadPath) { + $fileSize = (Get-Item $downloadPath).Length / 1MB + Write-Host "āœ… Downloaded: $fileName ($([math]::Round($fileSize, 2)) MB)" + + # Verify file is not empty or too small + if ($fileSize -lt 0.1) { + Write-Host "āŒ ERROR: Downloaded file is too small ($([math]::Round($fileSize, 2)) MB), likely corrupted" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Downloaded file is too small or corrupted" >> $env:GITHUB_OUTPUT + exit 1 + } + + # Extract the archive + Write-Host "Extracting archive..." + $extractOutput = & 7z x $downloadPath -o"test-phpmyadmin" -y 2>&1 + + if ($LASTEXITCODE -eq 0) { + Write-Host "āœ… Extraction successful" + + # List extracted contents + Write-Host "Extracted contents:" + Get-ChildItem -Path "test-phpmyadmin" -Directory | ForEach-Object { Write-Host " - $($_.Name)" } + + # Find the phpmyadmin directory + $phpmyadminDir = Get-ChildItem -Path "test-phpmyadmin" -Directory | Where-Object { $_.Name -match "^phpmyadmin" } | Select-Object -First 1 + + if ($phpmyadminDir) { + $phpmyadminPath = $phpmyadminDir.FullName + Write-Host "āœ… phpMyAdmin directory found: $phpmyadminPath" + + # Verify required files exist + $requiredFiles = @("index.php", "config.sample.inc.php") + $allFilesExist = $true + + foreach ($file in $requiredFiles) { + $filePath = Join-Path $phpmyadminPath $file + if (Test-Path $filePath) { + Write-Host "āœ… Found: $file" + } else { + Write-Host "āŒ Missing: $file" + $allFilesExist = $false + } + } + + if ($allFilesExist) { + echo "phpmyadmin-path=$phpmyadminPath" >> $env:GITHUB_OUTPUT + echo "success=true" >> $env:GITHUB_OUTPUT + } else { + Write-Host "āŒ ERROR: Required files missing in $phpmyadminPath" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Required files missing in extracted archive" >> $env:GITHUB_OUTPUT + exit 1 + } + } else { + Write-Host "āŒ ERROR: phpMyAdmin directory not found after extraction" + Write-Host "Expected directory pattern: phpmyadmin*" + Write-Host "Found directories:" + Get-ChildItem -Path "test-phpmyadmin" -Directory | ForEach-Object { Write-Host " - $($_.Name)" } + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=phpMyAdmin directory not found after extraction" >> $env:GITHUB_OUTPUT + exit 1 + } + } else { + Write-Host "āŒ ERROR: Extraction failed with exit code: $LASTEXITCODE" + Write-Host "7z output:" + Write-Host $extractOutput + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Extraction failed with exit code $LASTEXITCODE" >> $env:GITHUB_OUTPUT + exit 1 + } + } else { + Write-Host "āŒ ERROR: Download file not found at expected path: $downloadPath" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=Download file not found after download attempt" >> $env:GITHUB_OUTPUT + exit 1 + } + } catch { + Write-Host "āŒ ERROR: Unexpected error occurred" + Write-Host "Error message: $($_.Exception.Message)" + Write-Host "Stack trace: $($_.ScriptStackTrace)" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=$($_.Exception.Message)" >> $env:GITHUB_OUTPUT + exit 1 + } + + - name: Phase 1.2 - Verify phpMyAdmin Installation + id: verify-phpmyadmin + if: steps.download-phpmyadmin.outputs.success == 'true' + continue-on-error: true + run: | + $ErrorActionPreference = "Continue" + $phpmyadminPath = "${{ steps.download-phpmyadmin.outputs.phpmyadmin-path }}" + + Write-Host "=== Phase 1.2: Verify phpMyAdmin Installation ===" + + # Check for required files and directories + $requiredItems = @{ + "index.php" = "file" + "config.sample.inc.php" = "file" + "libraries" = "directory" + "templates" = "directory" + "themes" = "directory" + "vendor" = "directory" + } + + $allFound = $true + $verifyResults = @{} + + foreach ($item in $requiredItems.Keys) { + $itemPath = Join-Path $phpmyadminPath $item + $itemType = $requiredItems[$item] + + if ($itemType -eq "file") { + if (Test-Path $itemPath -PathType Leaf) { + Write-Host "āœ… Found file: $item" + $verifyResults[$item] = @{ found = $true; path = $itemPath; type = "file" } + } else { + Write-Host "āŒ Missing file: $item" + $verifyResults[$item] = @{ found = $false; type = "file" } + $allFound = $false + } + } elseif ($itemType -eq "directory") { + if (Test-Path $itemPath -PathType Container) { + Write-Host "āœ… Found directory: $item" + $verifyResults[$item] = @{ found = $true; path = $itemPath; type = "directory" } + } else { + Write-Host "āŒ Missing directory: $item" + $verifyResults[$item] = @{ found = $false; type = "directory" } + $allFound = $false + } + } + } + + # Check for version information + $versionFile = Join-Path $phpmyadminPath "libraries/classes/Version.php" + if (Test-Path $versionFile) { + try { + $versionContent = Get-Content $versionFile -Raw + if ($versionContent -match "VERSION\s*=\s*'([^']+)'") { + $detectedVersion = $matches[1] + Write-Host "Version detected: $detectedVersion" + $verifyResults["version"] = $detectedVersion + } + } catch { + Write-Host "āš ļø Could not detect version: $_" + } + } + + $verifyResults | ConvertTo-Json -Depth 10 | Out-File "test-results/verify.json" + + if ($allFound) { + echo "success=true" >> $env:GITHUB_OUTPUT + } else { + echo "success=false" >> $env:GITHUB_OUTPUT + exit 1 + } + + - name: Setup PHP + if: steps.verify-phpmyadmin.outputs.success == 'true' + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: mysqli, mbstring, zip, gd, xml, json + ini-values: post_max_size=256M, max_execution_time=180 + coverage: none + tools: composer + + - name: Phase 2 - Test Basic Functionality + id: test-basic + if: steps.verify-phpmyadmin.outputs.success == 'true' + continue-on-error: true + run: | + $ErrorActionPreference = "Stop" + $phpmyadminPath = "${{ steps.download-phpmyadmin.outputs.phpmyadmin-path }}" + + Write-Host "=== Phase 2: Test Basic Functionality ===" + + try { + $allFunctional = $true + $testResults = @() + + # Test 1: Check if index.php is valid PHP + Write-Host "`nTest 1: Validating index.php syntax..." + $indexPath = Join-Path $phpmyadminPath "index.php" + try { + $phpContent = Get-Content $indexPath -Raw + if ($phpContent -match "<\?php") { + Write-Host "āœ… index.php contains valid PHP opening tag" + $testResults += "index.php syntax: PASS" + } else { + Write-Host "āŒ index.php does not contain PHP opening tag" + $allFunctional = $false + $testResults += "index.php syntax: FAIL" + } + } catch { + Write-Host "āŒ Error reading index.php: $_" + $allFunctional = $false + $testResults += "index.php syntax: ERROR" + } + + # Test 2: Check config.sample.inc.php + Write-Host "`nTest 2: Validating config.sample.inc.php..." + $configPath = Join-Path $phpmyadminPath "config.sample.inc.php" + try { + $configContent = Get-Content $configPath -Raw + if ($configContent -match "\$cfg\[") { + Write-Host "āœ… config.sample.inc.php contains configuration array" + $testResults += "config.sample.inc.php: PASS" + } else { + Write-Host "āŒ config.sample.inc.php does not contain configuration array" + $allFunctional = $false + $testResults += "config.sample.inc.php: FAIL" + } + } catch { + Write-Host "āŒ Error reading config.sample.inc.php: $_" + $allFunctional = $false + $testResults += "config.sample.inc.php: ERROR" + } + + # Test 3: Check vendor directory (Composer dependencies) + Write-Host "`nTest 3: Checking Composer dependencies..." + $vendorPath = Join-Path $phpmyadminPath "vendor" + $autoloadPath = Join-Path $vendorPath "autoload.php" + try { + if (Test-Path $autoloadPath) { + Write-Host "āœ… Composer autoload file exists" + $testResults += "Composer dependencies: PASS" + } else { + Write-Host "āŒ Composer autoload file missing" + $allFunctional = $false + $testResults += "Composer dependencies: FAIL" + } + } catch { + Write-Host "āŒ Error checking Composer dependencies: $_" + $allFunctional = $false + $testResults += "Composer dependencies: ERROR" + } + + # Test 4: Check themes directory + Write-Host "`nTest 4: Checking themes..." + $themesPath = Join-Path $phpmyadminPath "themes" + try { + $themes = Get-ChildItem -Path $themesPath -Directory + if ($themes.Count -gt 0) { + Write-Host "āœ… Found $($themes.Count) theme(s):" + $themes | ForEach-Object { Write-Host " - $($_.Name)" } + $testResults += "Themes: PASS ($($themes.Count) found)" + } else { + Write-Host "āŒ No themes found" + $allFunctional = $false + $testResults += "Themes: FAIL" + } + } catch { + Write-Host "āŒ Error checking themes: $_" + $allFunctional = $false + $testResults += "Themes: ERROR" + } + + Write-Host "`nTest Results:" + $testResults | ForEach-Object { Write-Host " $_" } + + if ($allFunctional) { + Write-Host "`nāœ… All tests passed" + echo "success=true" >> $env:GITHUB_OUTPUT + } else { + Write-Host "`nāŒ Some tests failed" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=One or more functionality tests failed" >> $env:GITHUB_OUTPUT + exit 1 + } + } catch { + Write-Host "āŒ Error during testing: $_" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=$($_.Exception.Message)" >> $env:GITHUB_OUTPUT + exit 1 + } + + - name: Phase 3 - Test Database Connectivity + id: test-database + if: steps.test-basic.outputs.success == 'true' + continue-on-error: true + run: | + $ErrorActionPreference = "Stop" + $phpmyadminPath = "${{ steps.download-phpmyadmin.outputs.phpmyadmin-path }}" + + Write-Host "=== Phase 3: Test Database Connectivity ===" + + try { + $allFunctional = $true + $testResults = @() + + # Test 1: Setup MySQL service + Write-Host "`nTest 1: Setting up MySQL service..." + try { + # Download and setup MySQL (using Chocolatey for quick setup) + Write-Host "Installing MySQL via Chocolatey (this may take 3-5 minutes)..." + $chocoOutput = choco install mysql -y --version=8.0.33 --params="/port:3306" 2>&1 + Write-Host "Chocolatey output: $chocoOutput" + + # Wait for MySQL service to start (increased timeout) + Write-Host "Waiting for MySQL service to start..." + Start-Sleep -Seconds 30 + + # Check if MySQL service is running + $mysqlService = Get-Service -Name "MySQL" -ErrorAction SilentlyContinue + if ($mysqlService -and $mysqlService.Status -eq "Running") { + Write-Host "āœ… MySQL service is running" + $testResults += "MySQL Service: PASS" + } else { + Write-Host "āŒ MySQL service is not running" + $allFunctional = $false + $testResults += "MySQL Service: FAIL" + } + } catch { + Write-Host "āŒ Error setting up MySQL: $_" + $allFunctional = $false + $testResults += "MySQL Service: ERROR" + } + + # Test 2: Create test database and user + if ($allFunctional) { + Write-Host "`nTest 2: Creating test database and user..." + try { + # Set root password and create test database + $mysqlExe = "C:\tools\mysql\current\bin\mysql.exe" + if (Test-Path $mysqlExe) { + # Create test database + & $mysqlExe -u root -e "CREATE DATABASE IF NOT EXISTS phpmyadmin_test;" 2>&1 | Out-Null + & $mysqlExe -u root -e "CREATE USER IF NOT EXISTS 'pma_test'@'localhost' IDENTIFIED BY 'test_password';" 2>&1 | Out-Null + & $mysqlExe -u root -e "GRANT ALL PRIVILEGES ON phpmyadmin_test.* TO 'pma_test'@'localhost';" 2>&1 | Out-Null + & $mysqlExe -u root -e "FLUSH PRIVILEGES;" 2>&1 | Out-Null + + Write-Host "āœ… Test database and user created" + $testResults += "Database Setup: PASS" + } else { + Write-Host "āŒ MySQL executable not found" + $allFunctional = $false + $testResults += "Database Setup: FAIL" + } + } catch { + Write-Host "āŒ Error creating database: $_" + $allFunctional = $false + $testResults += "Database Setup: ERROR" + } + } + + # Test 3: Create phpMyAdmin config file + if ($allFunctional) { + Write-Host "`nTest 3: Creating phpMyAdmin configuration..." + try { + $configPath = Join-Path $phpmyadminPath "config.inc.php" + $configLines = @( + "" + ) + $configContent = $configLines -join "`n" + Set-Content -Path $configPath -Value $configContent + + if (Test-Path $configPath) { + Write-Host "āœ… Configuration file created" + $testResults += "Config Creation: PASS" + } else { + Write-Host "āŒ Configuration file not created" + $allFunctional = $false + $testResults += "Config Creation: FAIL" + } + } catch { + Write-Host "āŒ Error creating config: $_" + $allFunctional = $false + $testResults += "Config Creation: ERROR" + } + } + + # Test 4: Start PHP built-in server + if ($allFunctional) { + Write-Host "`nTest 4: Starting PHP built-in server..." + try { + # Start PHP server in background + $serverJob = Start-Job -ScriptBlock { + param($path) + Set-Location $path + php -S localhost:8080 2>&1 + } -ArgumentList $phpmyadminPath + + # Wait for server readiness with retries + $ready = $false + for ($i=0; $i -lt 10; $i++) { + Start-Sleep -Seconds 1 + try { + $resp = Invoke-WebRequest -Uri "http://localhost:8080/" -UseBasicParsing -TimeoutSec 2 + if ($resp.StatusCode -ge 200 -and $resp.StatusCode -lt 500) { $ready = $true; break } + } catch { } + if ($serverJob.State -ne "Running") { break } + } + + if ($ready) { + Write-Host "āœ… PHP server started on localhost:8080" + $testResults += "PHP Server: PASS" + } else { + Write-Host "āŒ PHP server failed to become ready" + # Fetch job output for diagnostics + $output = Receive-Job -Job $serverJob -Keep -ErrorAction SilentlyContinue + if ($output) { Write-Host "Server output:`n$output" } + $allFunctional = $false + $testResults += "PHP Server: FAIL" + } + } catch { + Write-Host "āŒ Error starting PHP server: $_" + $allFunctional = $false + $testResults += "PHP Server: ERROR" + } + } + + # Test 5: Test phpMyAdmin web interface + if ($allFunctional) { + Write-Host "`nTest 5: Testing phpMyAdmin web interface..." + try { + # Test if phpMyAdmin loads + $response = Invoke-WebRequest -Uri "http://localhost:8080/index.php" -UseBasicParsing -TimeoutSec 10 + + if ($response.StatusCode -eq 200) { + Write-Host "āœ… phpMyAdmin interface loads successfully" + $testResults += "Web Interface: PASS" + + # Check if it contains phpMyAdmin elements + if ($response.Content -match "phpMyAdmin" -or $response.Content -match "pma") { + Write-Host "āœ… phpMyAdmin content detected" + $testResults += "Content Validation: PASS" + } else { + Write-Host "āš ļø phpMyAdmin content not clearly detected" + $testResults += "Content Validation: PARTIAL" + } + } else { + Write-Host "āŒ phpMyAdmin interface returned status: $($response.StatusCode)" + $allFunctional = $false + $testResults += "Web Interface: FAIL" + } + } catch { + Write-Host "āŒ Error accessing phpMyAdmin interface: $_" + $allFunctional = $false + $testResults += "Web Interface: ERROR" + } + } + + # Test 6: Test database operations through phpMyAdmin + if ($allFunctional) { + Write-Host "`nTest 6: Testing database operations through phpMyAdmin..." + try { + # Test database listing endpoint + $dbListUrl = "http://localhost:8080/index.php?route=/server/databases" + $dbResponse = Invoke-WebRequest -Uri $dbListUrl -UseBasicParsing -TimeoutSec 10 + + if ($dbResponse.StatusCode -eq 200) { + Write-Host "āœ… Database listing accessible" + + # Check if our test database appears + if ($dbResponse.Content -match "phpmyadmin_test") { + Write-Host "āœ… Test database visible in phpMyAdmin" + $testResults += "Database Operations: PASS" + } else { + Write-Host "āš ļø Test database not visible (may require authentication)" + $testResults += "Database Operations: PARTIAL" + } + } else { + Write-Host "āš ļø Database operations returned status: $($dbResponse.StatusCode)" + $testResults += "Database Operations: PARTIAL" + } + } catch { + Write-Host "āš ļø Database operations test inconclusive: $_" + $testResults += "Database Operations: PARTIAL" + } + } + + # Cleanup: Stop PHP server + if ($serverJob) { + Write-Host "`nStopping PHP server..." + Stop-Job -Job $serverJob -ErrorAction SilentlyContinue + Remove-Job -Job $serverJob -Force -ErrorAction SilentlyContinue + Write-Host "āœ… PHP server stopped" + } + + Write-Host "`nTest Results:" + $testResults | ForEach-Object { Write-Host " $_" } + + if ($allFunctional) { + Write-Host "`nāœ… All database tests passed" + echo "success=true" >> $env:GITHUB_OUTPUT + } else { + Write-Host "`nāš ļø Some database tests failed or were skipped" + echo "success=partial" >> $env:GITHUB_OUTPUT + echo "error=Some database tests failed or were skipped" >> $env:GITHUB_OUTPUT + } + } catch { + Write-Host "āŒ Error during database testing: $_" + echo "success=false" >> $env:GITHUB_OUTPUT + echo "error=$($_.Exception.Message)" >> $env:GITHUB_OUTPUT + exit 1 + } + + - name: Generate Test Summary + if: always() + run: | + $version = "${{ matrix.version }}" + + Write-Host "`n=== Test Summary for phpMyAdmin $version ===" + + $phase1_1 = "${{ steps.download-phpmyadmin.outputs.success }}" -eq "true" + $phase1_2 = "${{ steps.verify-phpmyadmin.outputs.success }}" -eq "true" + $phase2 = "${{ steps.test-basic.outputs.success }}" -eq "true" + $phase3 = "${{ steps.test-database.outputs.success }}" -eq "true" + + # Get error messages if any + $error1_1 = "${{ steps.download-phpmyadmin.outputs.error }}" + $error2 = "${{ steps.test-basic.outputs.error }}" + $error3 = "${{ steps.test-database.outputs.error }}" + + $summary = "### phpMyAdmin $version`n`n" + + $summary += "**Phase 1: Installation Validation**`n" + $summary += "- Download & Extract: $(if ($phase1_1) { 'āœ… PASS' } else { 'āŒ FAIL' })`n" + if (-not $phase1_1 -and $error1_1) { + $summary += " - Error: $error1_1`n" + } + $summary += "- Verify Files & Directories: $(if ($phase1_2) { 'āœ… PASS' } else { 'āŒ FAIL' })`n`n" + + if ($phase1_2) { + $summary += "**Phase 2: Basic Functionality**`n" + $summary += "- Test PHP Files & Dependencies: $(if ($phase2) { 'āœ… PASS' } else { 'āŒ FAIL' })`n" + if (-not $phase2 -and $error2) { + $summary += " - Error: $error2`n" + } + $summary += "`n" + } + + if ($phase2) { + $phase3Status = "${{ steps.test-database.outputs.success }}" + if ($phase3Status -eq "true") { + $summary += "**Phase 3: Database Connectivity**`n" + $summary += "- MySQL Database Tests: āœ… PASS`n`n" + } elseif ($phase3Status -eq "partial") { + $summary += "**Phase 3: Database Connectivity**`n" + $summary += "- MySQL Database Tests: āš ļø PARTIAL`n" + if ($error3) { + $summary += " - Note: $error3`n" + } + $summary += "`n" + } elseif ($phase3Status -eq "false") { + $summary += "**Phase 3: Database Connectivity**`n" + $summary += "- MySQL Database Tests: āŒ FAIL`n" + if ($error3) { + $summary += " - Error: $error3`n" + } + $summary += "`n" + } + } + + # Overall status (all phases must pass) + $allPassed = $phase1_1 -and $phase1_2 -and $phase2 -and $phase3 + + if ($allPassed) { + $summary += "**Overall Status:** āœ… ALL TESTS PASSED`n" + } else { + $summary += "**Overall Status:** āŒ SOME TESTS FAILED`n" + $summary += "`n" + $summary += "
`n" + $summary += "šŸ’” Click here for troubleshooting tips`n`n" + $summary += "- Check the workflow logs for detailed error messages`n" + $summary += "- Download the test artifacts for complete logs`n" + $summary += "- Verify the .7z archive structure matches expected format`n" + $summary += "- Ensure all required PHP files and dependencies are included`n" + $summary += "
`n" + } + + Write-Host $summary + $summary | Out-File "test-results/summary.md" + + # Set job outcome based on test results + if (-not $allPassed) { + Write-Host "##[error]Tests failed for phpMyAdmin $version" + exit 1 + } + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-phpmyadmin-${{ matrix.version }} + path: test-results/ + retention-days: 30 + + report-results: + name: Report Test Results + needs: [detect-versions, test-phpmyadmin] + if: always() && needs.detect-versions.outputs.has-changes == 'true' + runs-on: ubuntu-latest + steps: + - name: Download all test results + uses: actions/download-artifact@v4 + with: + path: all-results + continue-on-error: true + + - name: Generate PR Comment + run: | + echo "## 🐘 phpMyAdmin Module Tests - Results" > comment.md + echo "" >> comment.md + echo "**Test Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> comment.md + + # Determine overall test status + TEST_STATUS="${{ needs.test-phpmyadmin.result }}" + VERSIONS='${{ needs.detect-versions.outputs.versions }}' + + if [ "$TEST_STATUS" = "skipped" ] || [ "$VERSIONS" = "[]" ]; then + echo "**Status:** ā­ļø Tests skipped - no versions to test" >> comment.md + echo "" >> comment.md + echo "ā„¹ļø **Why were tests skipped?**" >> comment.md + echo "" >> comment.md + echo "Tests are only run when:" >> comment.md + echo "- Version directories are added/modified in \`/bin\` (e.g., \`bin/phpmyadmin5.2.3/\`), OR" >> comment.md + echo "- PR title contains version numbers (e.g., \"5.2.3\", \"4.9.10\") that exist in \`releases.properties\`" >> comment.md + echo "" >> comment.md + echo "**To trigger tests:**" >> comment.md + echo "1. Add/modify version directories in \`/bin\` (e.g., \`bin/phpmyadmin5.2.3/\`)" >> comment.md + echo "2. Or add version numbers to your PR title (e.g., \"Update phpMyAdmin 5.2.3\")" >> comment.md + echo "3. Or manually trigger the workflow from the Actions tab" >> comment.md + elif [ "$TEST_STATUS" = "success" ]; then + echo "**Status:** āœ… All tests passed" >> comment.md + elif [ "$TEST_STATUS" = "failure" ]; then + echo "**Status:** āŒ Some tests failed" >> comment.md + else + echo "**Status:** āš ļø Tests completed with issues" >> comment.md + fi + + echo "" >> comment.md + + # Generate badges for each version + if [ "$TEST_STATUS" != "skipped" ] && [ "$VERSIONS" != "[]" ]; then + echo "### šŸ“Š Test Results by Version" >> comment.md + echo "" >> comment.md + + # Parse versions and check results + VERSION_LIST=$(echo '${{ needs.detect-versions.outputs.versions }}' | jq -r '.[]') + + for version in $VERSION_LIST; do + # Check if summary file exists for this version + SUMMARY_FILE="all-results/test-results-phpmyadmin-${version}/summary.md" + + if [ -f "$SUMMARY_FILE" ]; then + # Check if tests passed by looking for "ALL TESTS PASSED" in summary + if grep -q "ALL TESTS PASSED" "$SUMMARY_FILE"; then + # Success badge (green) + echo "![phpMyAdmin ${version}](https://img.shields.io/badge/phpMyAdmin_${version}-PASS-success?style=flat-square&logo=phpmyadmin&logoColor=white)" >> comment.md + else + # Failure badge (red) + echo "![phpMyAdmin ${version}](https://img.shields.io/badge/phpMyAdmin_${version}-FAIL-critical?style=flat-square&logo=phpmyadmin&logoColor=white)" >> comment.md + fi + else + # No results badge (gray) + echo "![phpMyAdmin ${version}](https://img.shields.io/badge/phpMyAdmin_${version}-NO_RESULTS-inactive?style=flat-square&logo=phpmyadmin&logoColor=white)" >> comment.md + fi + done + + echo "" >> comment.md + fi + + echo "" >> comment.md + + # Check if artifacts exist + if [ -d "all-results" ]; then + # Count expected vs actual results + EXPECTED_COUNT=$(echo '${{ needs.detect-versions.outputs.versions }}' | jq '. | length') + ACTUAL_COUNT=$(find all-results -name "summary.md" 2>/dev/null | wc -l) + + echo "**Results:** $ACTUAL_COUNT of $EXPECTED_COUNT versions tested" >> comment.md + echo "" >> comment.md + + # Check if there are any failures + HAS_FAILURES=false + for version_dir in all-results/test-results-phpmyadmin-*; do + if [ -d "$version_dir" ]; then + for summary_file in "$version_dir"/summary.md; do + if [ -f "$summary_file" ]; then + if ! grep -q "ALL TESTS PASSED" "$summary_file"; then + HAS_FAILURES=true + break 2 + fi + fi + done + fi + done + + # Only show detailed results if there are failures + if [ "$HAS_FAILURES" = true ]; then + echo "### šŸ“‹ Detailed Test Results" >> comment.md + echo "" >> comment.md + + for version_dir in all-results/test-results-phpmyadmin-*; do + if [ -d "$version_dir" ]; then + for summary_file in "$version_dir"/summary.md; do + if [ -f "$summary_file" ]; then + cat "$summary_file" >> comment.md + echo "" >> comment.md + fi + done + fi + done + else + echo "_All tests passed successfully! ✨_" >> comment.md + echo "" >> comment.md + fi + elif [ "$TEST_STATUS" != "skipped" ] && [ "$VERSIONS" != "[]" ]; then + echo "āš ļø No test results available" >> comment.md + echo "" >> comment.md + fi + + if [ "$TEST_STATUS" != "skipped" ] && [ "$VERSIONS" != "[]" ]; then + echo "---" >> comment.md + echo "" >> comment.md + echo "### šŸ“‹ Test Phases" >> comment.md + echo "" >> comment.md + echo "Each version is tested through the following phases:" >> comment.md + echo "- **Phase 1:** Installation Validation (Download, Extract, Verify Files & Directories)" >> comment.md + echo "- **Phase 2:** Basic Functionality (Test PHP Files, Config, Dependencies, Themes)" >> comment.md + echo "- **Phase 3:** Database Connectivity (phpMyAdmin web interface & MySQL tests)" >> comment.md + echo "" >> comment.md + echo "_Check artifacts for detailed logs._" >> comment.md + fi + + cat comment.md + + - name: Comment on PR + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const comment = fs.readFileSync('comment.md', 'utf8'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const botComment = comments.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('🐘 phpMyAdmin Module Tests') + ); + + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: comment + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); + } + + - name: Display Results Summary (Manual Run) + if: github.event_name == 'workflow_dispatch' + run: | + echo "## 🐘 phpMyAdmin Module Tests - Manual Run Results" + echo "" + cat comment.md diff --git a/docs/CI-CD-TESTING.md b/docs/CI-CD-TESTING.md new file mode 100644 index 0000000..34f4feb --- /dev/null +++ b/docs/CI-CD-TESTING.md @@ -0,0 +1,576 @@ +# phpMyAdmin Module CI/CD Testing + +## Overview + +This document describes the automated testing workflow for the Bearsampp phpMyAdmin module. The CI/CD pipeline ensures that phpMyAdmin builds are properly packaged, can be extracted, and that all required files and dependencies are present and functional. + +## Workflow Triggers + +The phpMyAdmin testing workflow is triggered automatically on: + +- **Pull Request Events**: When a PR is opened, synchronized (new commits pushed), reopened, or edited + - Target branches: `main` +- **Manual Workflow Dispatch**: Can be triggered manually with options to test specific versions + +## Test Scope + +The workflow intelligently determines which versions to test based on the context: + +### Pull Request Testing + +- **Smart Detection**: Automatically detects which phpMyAdmin versions are included in the PR from pre-release + - **Primary Method**: Extracts version numbers from changed files in `/bin` directory (e.g., `bin/phpmyadmin5.2.3/`) + - **Fallback Method**: If no versions found in `/bin`, extracts version numbers from PR title + - **Skip Behavior**: If no versions detected by either method, tests are skipped +- **Efficiency**: Reduces CI runtime by testing only relevant versions +- **Comprehensive**: Tests all versions including major and minor releases + +**How it works:** + +1. New versions are created and added to a pre-release (tagged with date, e.g., "2025.11.23") +2. Version directories are created in `/bin` (e.g., `bin/phpmyadmin5.2.3/`, `bin/phpmyadmin5.2.2/`) +3. The `releases.properties` file is updated via the releases.properties workflow +4. A PR is created from a release branch (e.g., "November") to `main` +5. This workflow detects changed files in `/bin` and extracts version numbers from directory names +6. Tests are run against the version(s) found in `releases.properties` from that PR branch + +### Manual Testing +- **Latest 5 Versions**: Tests the 5 most recent versions from `releases.properties` +- **Specific Version**: Tests a single version provided as input parameter +- **Flexibility**: Useful for re-testing or validating specific versions + +### Example Scenarios +- **Add phpMyAdmin 5.2.3**: Only version 5.2.3 is tested +- **Add versions 5.2.2 and 5.2.3**: Both versions are tested +- **PR with version in title (e.g., "Update docs for 5.2.3")**: Version 5.2.3 is tested +- **Non-version changes (e.g., documentation only)**: Tests are skipped + +## Test Phases + +### Phase 1: Installation Validation + +**Purpose**: Verify the phpMyAdmin package can be downloaded and extracted correctly. + +**Steps**: +1. **Download phpMyAdmin** (Phase 1.1) + - Reads the download URL from `releases.properties` + - Downloads the `.7z` archive from GitHub releases + - Reports download size and success status + - Validates file size (must be > 0.1 MB) + +2. **Extract Archive** (Phase 1.1) + - Extracts the `.7z` file using 7-Zip + - Locates the `phpmyadmin*` subfolder + - Validates the directory structure + - Verifies required files exist (`index.php`, `config.sample.inc.php`) + +3. **Verify Files & Directories** (Phase 1.2) + - Checks for required files: + - `index.php` - Main entry point + - `config.sample.inc.php` - Sample configuration file + - Checks for required directories: + - `libraries/` - Core phpMyAdmin libraries + - `templates/` - Template files + - `themes/` - Theme files + - `vendor/` - Composer dependencies + - Attempts to detect version from `libraries/classes/Version.php` + - Saves verification results to JSON + +### PHP Setup + +**Purpose**: Ensure PHP is available for testing phpMyAdmin functionality. + +**Steps**: +1. **Install PHP** using `shivammathur/setup-php@v2` action + - PHP Version: 8.2 + - Extensions: mysqli, mbstring, zip, gd, xml, json + - Configuration: `post_max_size=256M`, `max_execution_time=180` + - Tools: Composer included + +### Phase 2: Basic Functionality + +**Purpose**: Verify phpMyAdmin files are valid and dependencies are present. + +**Steps**: +1. **Test PHP Files** (Phase 2) + - Validates `index.php` contains valid PHP opening tag + - Checks `config.sample.inc.php` contains configuration array (`$cfg`) + - Verifies Composer autoload file exists (`vendor/autoload.php`) + - Checks themes directory and lists available themes + - Reports pass/fail status for each test + +### Phase 3: Database Connectivity + +**Purpose**: Test phpMyAdmin's web interface and ability to connect to a MySQL database through the application itself. + +**Steps**: +1. **Setup MySQL Service** + - Installs MySQL 8.0.33 via Chocolatey + - Verifies MySQL service is running + - Waits for service initialization + +2. **Create Test Database** + - Creates `phpmyadmin_test` database + - Creates test user `pma_test` with password + - Grants necessary privileges + - Flushes privileges + +3. **Configure phpMyAdmin** + - Creates `config.inc.php` with test database credentials + - Sets authentication type to 'config' + - Configures connection parameters + +4. **Start PHP Built-in Server** + - Launches PHP development server on localhost:8080 + - Serves phpMyAdmin web interface + - Runs in background for testing + +5. **Test phpMyAdmin Web Interface** + - Accesses phpMyAdmin via HTTP (http://localhost:8080/index.php) + - Verifies HTTP 200 response + - Validates phpMyAdmin content is present + - Confirms interface loads correctly + +6. **Test Database Operations Through phpMyAdmin** + - Accesses database listing page via phpMyAdmin interface + - Verifies phpMyAdmin can connect to MySQL + - Checks if test database is visible in phpMyAdmin + - Validates database operations work through the web interface + +7. **Cleanup** + - Stops PHP development server + - Cleans up background processes + +**Note**: Phase 3 is **mandatory** and must pass for the overall test to succeed. This ensures phpMyAdmin can actually function as a web application and connect to MySQL databases, which is its primary purpose. + +## Test Results + +### Artifacts + +The workflow generates and uploads the following artifacts: + +1. **Test Results** (`test-results-phpmyadmin-VERSION`) + - `verify.json` - File and directory verification results + - `summary.md` - Human-readable test summary + - Retention: 30 days + +### PR Comments + +For pull requests, the workflow automatically posts a comment with: +- Test date and time (UTC) +- Summary for each tested version +- Pass/fail status for each phase +- Overall test status +- Troubleshooting tips for failures +- Links to detailed artifacts + +The comment is updated if it already exists (no duplicate comments). + +### Test Summary Format + +Each version's summary includes: + +``` +### phpMyAdmin X.Y.Z + +**Phase 1: Installation Validation** +- Download & Extract: āœ… PASS / āŒ FAIL +- Verify Files & Directories: āœ… PASS / āŒ FAIL + +**Phase 2: Basic Functionality** +- Test PHP Files & Dependencies: āœ… PASS / āŒ FAIL + +**Overall Status:** āœ… ALL TESTS PASSED / āŒ SOME TESTS FAILED +``` + +If tests fail, additional troubleshooting information is provided: +- Specific error messages +- Collapsible troubleshooting tips +- Links to workflow logs +- References to test artifacts + +## Error Handling + +The workflow provides comprehensive error reporting at multiple levels: + +### Detailed Error Messages + +Each phase captures and reports specific error information: + +- **Download failures**: + - HTTP status codes and error messages + - Attempted URLs + - File size validation errors + +- **Extraction failures**: + - 7-Zip exit codes and output logs + - Directory listings showing actual structure + - Expected vs. actual directory patterns + +- **Missing files**: + - List of expected files and directories + - Actual directory contents + - Specific missing items highlighted + +- **Validation failures**: + - PHP syntax check results + - Configuration file validation + - Dependency check results + +### Error Propagation + +- Each phase uses `continue-on-error: true` to allow subsequent phases to run +- Failed phases are clearly marked in the summary with āŒ indicators +- Error messages are included inline in test summaries +- All test results are uploaded regardless of success/failure +- Overall workflow status reflects any failures + +### Troubleshooting Assistance + +When tests fail, the summary includes: +- Specific error messages for each failed phase +- Collapsible troubleshooting tips section with: + - Links to detailed workflow logs + - Instructions to download test artifacts + - Common issues and solutions + - Archive structure validation tips + - PHP file and dependency checks + +## Platform + +- **Runner**: `windows-latest` +- **Reason**: Consistent testing environment for Windows-based deployments +- **Tools**: Native Windows PowerShell, 7-Zip (pre-installed) +- **OS**: Windows Server (latest GitHub Actions runner) + +## Matrix Strategy + +- **Parallel Execution**: Tests run in parallel for different versions +- **Fail-Fast**: Disabled (`fail-fast: false`) to test all versions even if one fails +- **Dynamic Matrix**: Version list is generated dynamically based on trigger context +- **Resource Efficiency**: Only tests relevant versions to minimize CI time + +## Workflow File Location + +`.github/workflows/phpmyadmin-test.yml` + +## Maintenance + +### Adding New Test Cases + +To add new functionality tests: + +1. Add a new step after Phase 2 +2. Use `continue-on-error: true` to prevent blocking other tests +3. Check previous phase success with `if: steps.PREVIOUS_STEP.outputs.success == 'true'` +4. Set output variable: `echo "success=true/false" >> $env:GITHUB_OUTPUT` +5. Update the test summary generation to include the new phase +6. Document the new phase in this file + +### Modifying Version Selection + +To change which versions are tested, edit the `Get phpMyAdmin Versions` step: + +```bash +# Current: Latest 5 versions +VERSIONS=$(... | head -5 | ...) + +# Example: Latest 3 versions +VERSIONS=$(... | head -3 | ...) + +# Example: Latest 10 versions +VERSIONS=$(... | head -10 | ...) +``` + +### Adjusting Test Parameters + +Key parameters that can be adjusted: + +- **Download timeout**: `TimeoutSec 300` (5 minutes) in Phase 1.1 +- **Minimum file size**: `0.1 MB` validation in Phase 1.1 +- **Artifact retention**: `retention-days: 30` in Upload Test Results step + +### Adding New Files/Directories to Verify + +To verify additional phpMyAdmin files or directories: + +1. Edit Phase 1.2 in the workflow file +2. Add the item to the `$requiredItems` hashtable: + ```powershell + $requiredItems = @{ + "index.php" = "file" + "config.sample.inc.php" = "file" + "libraries" = "directory" + "templates" = "directory" + "themes" = "directory" + "vendor" = "directory" + "NEW_FILE.php" = "file" # Add new file + "NEW_DIR" = "directory" # Add new directory + } + ``` +3. Optionally add specific tests in Phase 2 + +## Troubleshooting + +### Common Issues + +1. **Download Failures** + - **Symptom**: Phase 1.1 fails with download error + - **Causes**: + - Invalid URL in `releases.properties` + - GitHub release not published or deleted + - Network connectivity issues + - Rate limiting from GitHub + - **Solutions**: + - Verify the release URL is accessible in a browser + - Check GitHub releases page for the module + - Ensure the version number matches exactly + - Wait and retry if rate limited + +2. **Extraction Failures** + - **Symptom**: Phase 1.1 fails after successful download + - **Causes**: + - Corrupted `.7z` file + - Incorrect archive structure + - Insufficient disk space + - **Solutions**: + - Re-download and re-upload the release + - Verify archive structure locally before uploading + - Check that archive contains `phpmyadmin*` directory with required files + +3. **Missing Files or Directories** + - **Symptom**: Phase 1.2 fails with missing items + - **Causes**: + - Incomplete phpMyAdmin build + - Wrong directory structure in archive + - Missing Composer dependencies + - **Solutions**: + - Verify all required files and directories are present + - Check that the build is complete and not a partial package + - Ensure Composer dependencies are installed (`composer install --no-dev`) + +4. **PHP File Validation Failures** + - **Symptom**: Phase 2 fails when validating PHP files + - **Causes**: + - Corrupted PHP files + - Missing PHP opening tags + - Invalid configuration file + - **Solutions**: + - Verify PHP files are not corrupted + - Check that files contain proper PHP syntax + - Test the build locally before uploading + +5. **Missing Composer Dependencies** + - **Symptom**: Phase 2 fails on vendor/autoload.php check + - **Causes**: + - Composer dependencies not installed + - `vendor/` directory not included in archive + - **Solutions**: + - Run `composer install --no-dev` before packaging + - Ensure `vendor/` directory is included in the archive + - Verify `vendor/autoload.php` exists + +### Debugging Steps + +To debug a specific version failure: + +1. **Check Workflow Logs** + - Navigate to the failed workflow run in GitHub Actions + - Expand the failed step to see detailed output + - Look for specific error messages + +2. **Download Artifacts** + - Download the `test-results-phpmyadmin-VERSION` artifact + - Review `verify.json` for file/directory validation details + - Check `summary.md` for formatted results + +3. **Local Testing** + - Download the same `.7z` file from releases + - Extract it locally on Windows + - Verify all required files and directories are present + - Check for any missing dependencies + +4. **Compare with Working Versions** + - Compare directory structure with a passing version + - Check file sizes and contents + - Verify all dependencies are present + +### Manual Workflow Testing + +To manually test a specific version: + +1. Go to the Actions tab in GitHub +2. Select "phpMyAdmin Module Tests" workflow +3. Click "Run workflow" +4. Choose "Specific version" from the dropdown +5. Enter the version number (e.g., "5.2.3") +6. Click "Run workflow" +7. Monitor the test results + +## Best Practices + +1. **Always test before merging**: The workflow runs on PRs to catch issues early +2. **Review test summaries**: Check PR comments for test results before merging +3. **Investigate failures**: Don't merge if tests fail without understanding why +4. **Keep versions updated**: Regularly update `releases.properties` with new phpMyAdmin versions +5. **Monitor artifact storage**: Old artifacts are automatically cleaned up after retention period +6. **Test locally first**: Before creating a PR, test the phpMyAdmin build locally +7. **Document changes**: Update this documentation when modifying the workflow +8. **Version consistency**: Ensure version numbers in filenames match `releases.properties` +9. **Include all dependencies**: Always run `composer install --no-dev` before packaging +10. **Verify archive structure**: Ensure the archive contains the correct directory structure + +## Version Naming Conventions + +phpMyAdmin versions in `releases.properties` should follow these patterns: + +- **Major.Minor.Patch**: `5.2.3`, `5.2.2`, `5.2.1` +- **Major.Minor**: `5.2`, `4.9` +- **Legacy versions**: `4.9.10` + +The workflow supports all version formats and will test them accordingly. + +## Workflow Outputs + +### Success Indicators + +When all tests pass, you'll see: +- āœ… Green checkmark on the PR +- "All tests passed" status in PR comment +- All phases marked with āœ… PASS +- Artifacts uploaded successfully + +### Failure Indicators + +When tests fail, you'll see: +- āŒ Red X on the PR +- "Some tests failed" status in PR comment +- Failed phases marked with āŒ FAIL +- Error messages in the summary +- Troubleshooting tips displayed + +## phpMyAdmin-Specific Considerations + +### Required Files and Directories + +phpMyAdmin requires the following structure: + +``` +phpmyadmin-X.Y.Z/ +ā”œā”€ā”€ index.php # Main entry point +ā”œā”€ā”€ config.sample.inc.php # Sample configuration +ā”œā”€ā”€ libraries/ # Core libraries +│ └── classes/ +│ └── Version.php # Version information +ā”œā”€ā”€ templates/ # Template files +ā”œā”€ā”€ themes/ # Theme files +│ ā”œā”€ā”€ pmahomme/ # Default theme +│ └── ... # Other themes +└── vendor/ # Composer dependencies + └── autoload.php # Composer autoloader +``` + +### Composer Dependencies + +phpMyAdmin uses Composer for dependency management. The workflow verifies: +- `vendor/` directory exists +- `vendor/autoload.php` exists +- Dependencies are properly installed + +**Important**: Always run `composer install --no-dev` before packaging to ensure all required dependencies are included without development dependencies. + +### Themes + +phpMyAdmin includes multiple themes. The workflow: +- Verifies the `themes/` directory exists +- Lists all available themes +- Ensures at least one theme is present + +### Configuration + +The workflow checks for `config.sample.inc.php` which contains: +- Database connection settings template +- phpMyAdmin configuration options +- Security settings + +## Related Documentation + +- [phpMyAdmin Official Documentation](https://docs.phpmyadmin.net/) +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Bearsampp Project](https://github.com/Bearsampp) +- [Module phpMyAdmin Repository](https://github.com/Bearsampp/module-phpmyadmin) + +## Changelog + +### Version History + +- **Initial Release**: Basic download and extraction testing with file/directory verification + +### Future Enhancements + +Potential improvements for future versions: + +1. **PHP Syntax Validation**: Add PHP linting to validate all PHP files +2. **Configuration Testing**: Test configuration file parsing +3. **Database Connection Testing**: Test database connectivity (with mock database) +4. **Theme Validation**: Verify theme files are complete and valid +5. **Security Checks**: Verify default security settings +6. **Performance Benchmarks**: Add basic performance metrics +7. **Localization Testing**: Verify language files are present + +## Contributing to Tests + +To contribute improvements to the testing workflow: + +1. Fork the repository +2. Create a feature branch +3. Modify `.github/workflows/phpmyadmin-test.yml` +4. Update this documentation +5. Test your changes with manual workflow dispatch +6. Submit a pull request with: + - Description of changes + - Rationale for improvements + - Test results showing the changes work + +## Support and Contact + +For questions or issues with the CI/CD workflow: + +- **GitHub Issues**: [Open an issue](https://github.com/Bearsampp/module-phpmyadmin/issues) +- **Discussions**: Use GitHub Discussions for questions +- **Pull Requests**: Submit improvements via PR + +When reporting issues, please include: +- Version number being tested +- Link to failed workflow run +- Error messages from logs +- Steps to reproduce (if applicable) + +## Packaging Guidelines + +When creating a new phpMyAdmin release for Bearsampp: + +1. **Download phpMyAdmin**: Get the official release from phpMyAdmin.net +2. **Install Dependencies**: Run `composer install --no-dev` +3. **Verify Structure**: Ensure all required files and directories are present +4. **Create Archive**: Package as `.7z` with naming convention `bearsampp-phpmyadmin-X.Y.Z-YYYY.MM.DD.7z` +5. **Upload to GitHub**: Create a release and upload the archive +6. **Update releases.properties**: Add the new version entry +7. **Create PR**: Submit PR to trigger automated testing +8. **Review Results**: Check CI/CD test results before merging + +## Testing Checklist + +Before merging a PR with new phpMyAdmin versions: + +- [ ] Archive downloads successfully +- [ ] Archive extracts without errors +- [ ] All required files are present +- [ ] All required directories are present +- [ ] PHP files contain valid syntax +- [ ] Configuration file is valid +- [ ] Composer dependencies are installed +- [ ] At least one theme is present +- [ ] Version can be detected +- [ ] All CI/CD tests pass +- [ ] Test artifacts are available for review diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..f045e00 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,36 @@ +# phpMyAdmin Module Documentation + +This directory contains documentation for the Bearsampp phpMyAdmin module. + +## Available Documentation + +### [CI/CD Testing](CI-CD-TESTING.md) + +Comprehensive guide to the automated testing workflow for phpMyAdmin builds: +- Workflow triggers and configuration +- Detailed test phase descriptions +- Test results and artifacts +- Troubleshooting guide +- Maintenance instructions + +## Quick Links + +- **Workflow File**: [`.github/workflows/phpmyadmin-test.yml`](../.github/workflows/phpmyadmin-test.yml) +- **Releases**: [`releases.properties`](../releases.properties) +- **Main Repository**: [Bearsampp phpMyAdmin Module](https://github.com/Bearsampp/module-phpmyadmin) + +## Contributing + +When adding new features or making changes to the phpMyAdmin module: + +1. Update relevant documentation in this folder +2. Ensure CI/CD tests pass on your pull request +3. Review test results in the automated PR comment +4. Update this README if adding new documentation files + +## Support + +For issues or questions: +- Open an issue on [GitHub](https://github.com/Bearsampp/module-phpmyadmin/issues) +- Check existing documentation for troubleshooting steps +- Review CI/CD test logs for build-related issues