name: Docker Image Test on: push: branches: - main paths: - 'dockerfile/**' - 'docker-compose.example.yaml' - '.example.env' - '.gitea/workflows/**' pull_request: branches: - main workflow_dispatch: jobs: build-and-test: name: Build & Test PHP 8.5 Apache Image runs-on: ubuntu-latest steps: - name: Checkout Repository uses: actions/checkout@v4 - name: Build Docker Image run: | docker build -t webhost-test:ci ./dockerfile - name: Start Container with Test ENV run: | docker rm -f webhost-test 2>/dev/null || true docker run -d \ --name webhost-test \ -e SMTP_HOST=127.0.0.1 \ -e SMTP_PORT=2525 \ -e SMTP_USER=testuser@example.com \ -e SMTP_PASS=supersecret \ -e SMTP_FROM=noreply@example.com \ -e SMTP_TLS=off \ -e SMTP_STARTTLS=off \ webhost-test:ci echo "Waiting for Apache to start..." for i in $(seq 1 15); do if [ "$(docker inspect -f '{{.State.Running}}' webhost-test 2>/dev/null)" = "true" ]; then if docker exec webhost-test apache2ctl -t >/dev/null 2>&1; then echo "Container is running and Apache config is valid." break fi fi if [ "$i" -eq 15 ]; then echo "Container failed to start in time!" docker logs webhost-test exit 1 fi sleep 1 done - name: Verify PHP Version & Extensions run: | echo "--- Checking PHP Version (8.5.x) ---" docker exec webhost-test php -v docker exec webhost-test php -r ' if (version_compare(PHP_VERSION, "8.5.0-dev", "<")) { fwrite(STDERR, "Expected PHP 8.5+, got " . PHP_VERSION . PHP_EOL); exit(1); } ' echo "--- Checking Required PHP Extensions ---" docker exec webhost-test php -r ' $required = ["mysqli", "gd", "imagick", "intl", "zip", "exif", "Zend OPcache"]; $missing = []; foreach ($required as $ext) { if (!extension_loaded($ext)) { $missing[] = $ext; } } if (!empty($missing)) { fwrite(STDERR, "Missing PHP extensions: " . implode(", ", $missing) . PHP_EOL); exit(1); } echo "All required extensions are loaded: " . implode(", ", $required) . PHP_EOL; ' echo "--- Checking GD WebP & PNG Support ---" docker exec webhost-test php -r ' $gd = gd_info(); if (empty($gd["WebP Support"]) || empty($gd["PNG Support"])) { fwrite(STDERR, "GD is missing WebP or PNG support!" . PHP_EOL); print_r($gd); exit(1); } echo "GD WebP & PNG support verified." . PHP_EOL; ' echo "--- Checking OPcache Configuration ---" docker exec webhost-test php -r ' $checks = [ "opcache.enable" => "1", "opcache.validate_timestamps" => "0", "opcache.max_accelerated_files" => "10000", "opcache.memory_consumption" => "192", "opcache.max_wasted_percentage" => "10", "opcache.interned_strings_buffer" => "16", ]; foreach ($checks as $key => $expected) { $actual = (string) ini_get($key); if ($actual !== $expected) { fwrite(STDERR, "Config mismatch for $key: expected $expected, got $actual" . PHP_EOL); exit(1); } } echo "OPcache settings verified." . PHP_EOL; ' - name: Verify Apache Modules & SSL Certificate run: | echo "--- Checking Apache Modules (ssl, rewrite) ---" MODULES=$(docker exec webhost-test apache2ctl -M) echo "$MODULES" | grep -q "ssl_module" || { echo "ssl_module not enabled"; exit 1; } echo "$MODULES" | grep -q "rewrite_module" || { echo "rewrite_module not enabled"; exit 1; } echo "Apache modules ssl and rewrite are enabled." echo "--- Checking Self-Signed SSL Certificate ---" docker exec webhost-test test -s /etc/apache2/certs/apache.crt docker exec webhost-test test -s /etc/apache2/certs/apache.key docker exec webhost-test openssl x509 -in /etc/apache2/certs/apache.crt -noout -subject -dates - name: Verify msmtp Entrypoint & Configuration run: | echo "--- Checking /etc/msmtprc & /var/log/msmtp.log ---" docker exec webhost-test sh -c ' test -f /etc/msmtprc PERMS=$(stat -c "%a" /etc/msmtprc) OWNER=$(stat -c "%U:%G" /etc/msmtprc) if [ "$PERMS" != "600" ] || [ "$OWNER" != "www-data:www-data" ]; then echo "Unexpected /etc/msmtprc permissions ($PERMS) or owner ($OWNER)" exit 1 fi grep -q "^host 127.0.0.1$" /etc/msmtprc grep -q "^port 2525$" /etc/msmtprc grep -q "^from noreply@example.com$" /etc/msmtprc grep -q "^user testuser@example.com$" /etc/msmtprc grep -q "^password supersecret$" /etc/msmtprc test -f /etc/aliases grep -q "^default: noreply@example.com$" /etc/aliases test -f /var/log/msmtp.log LOG_OWNER=$(stat -c "%U:%G" /var/log/msmtp.log) if [ "$LOG_OWNER" != "www-data:www-data" ]; then echo "Unexpected /var/log/msmtp.log owner ($LOG_OWNER)" exit 1 fi echo "msmtp configuration and permissions verified." ' - name: Test HTTP, HTTPS & .htaccess Rewrite run: | docker exec webhost-test sh -c ' cat << "EOF" > /var/www/html/index.php "ok", "php" => PHP_VERSION, "https" => (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off"), "rewritten" => ($_GET["rewritten"] ?? "0") === "1" ]); EOF cat << "EOF" > /var/www/html/.htaccess RewriteEngine On RewriteRule ^rewrite-test$ index.php?rewritten=1 [L,QSA] EOF ' echo "--- Testing HTTP (Port 80) ---" HTTP_RESP=$(docker exec webhost-test curl -fsS http://127.0.0.1/index.php) echo "HTTP Response: $HTTP_RESP" echo "$HTTP_RESP" | grep -q '"status":"ok"' echo "--- Testing HTTPS (Port 443) ---" HTTPS_RESP=$(docker exec webhost-test curl -fsSk https://127.0.0.1/index.php) echo "HTTPS Response: $HTTPS_RESP" echo "$HTTPS_RESP" | grep -q '"status":"ok"' echo "$HTTPS_RESP" | grep -q '"https":true' echo "--- Testing .htaccess mod_rewrite ---" REWRITE_RESP=$(docker exec webhost-test curl -fsS http://127.0.0.1/rewrite-test) echo "Rewrite Response: $REWRITE_RESP" echo "$REWRITE_RESP" | grep -q '"rewritten":true' - name: Cleanup Container if: always() run: | echo "--- Container Logs ---" docker logs webhost-test || true docker rm -f webhost-test || true