From a935cc2470d8e59cca59a64ddabbebe948a17418 Mon Sep 17 00:00:00 2001 From: Sandro Date: Fri, 23 Oct 2026 23:28:55 +0200 Subject: [PATCH] new workflow --- .gitea/workflows/docker-test.yaml | 275 +++++++++++------------------- 1 file changed, 104 insertions(+), 171 deletions(-) diff --git a/.gitea/workflows/docker-test.yaml b/.gitea/workflows/docker-test.yaml index 4e4d2fe..c2c48f8 100644 --- a/.gitea/workflows/docker-test.yaml +++ b/.gitea/workflows/docker-test.yaml @@ -2,93 +2,109 @@ name: Docker Build, Test & Push on: push: - branches: - - main - tags: - - 'v*' - paths: - - 'dockerfile/**' - - 'docker-compose.example.yaml' - - '.example.env' - - '.gitea/workflows/**' - pull_request: - branches: + branches-ignore: - main + - default workflow_dispatch: +# ============================================================================== +# KONFIGURATION (Für andere Repositories einfach hier oben anpassen) +# ============================================================================== env: + # Registry & Image-Name (CUSTOM_IMAGE_NAME leer lassen = automatisch /) REGISTRY: git.dsit.me + CUSTOM_IMAGE_NAME: "" + + # Pfad zum Build-Kontext und Dockerfile + BUILD_CONTEXT: ./dockerfile + DOCKERFILE: ./dockerfile/Dockerfile + + # Name des temporären Test-Containers & Start-Timeout (in Sekunden) + CONTAINER_NAME: ci-test-container + STARTUP_TIMEOUT: 15 + + # Umgebungsvariablen für den Test-Container (leer lassen falls nicht benötigt) + CONTAINER_ENV: >- + -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 + + # Optionale Checks im Container (jeweils leer "" lassen zum Überspringen) + READINESS_CMD: "apache2ctl -t" + REQUIRED_PHP_EXTENSIONS: "mysqli gd imagick intl zip exif" + REQUIRED_APACHE_MODULES: "ssl_module rewrite_module" + TEST_HTTP_PORT: "80" + TEST_HTTPS_PORT: "443" + WEBROOT_DIR: "/var/www/html" jobs: build-test-push: - name: Build, Test & Push PHP 8.5 Apache Image + name: Build, Test & Push (${{ gitea.ref_name }}) runs-on: ubuntu-latest + if: gitea.ref_name != 'main' && gitea.ref_name != 'default' steps: - name: Checkout Repository uses: actions/checkout@v4 - - name: Set Image Metadata + - name: Prepare Image Tag from Branch id: meta run: | - IMAGE_NAME=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]') - SHORT_SHA=$(echo "${{ gitea.sha }}" | cut -c1-7) - echo "image=${REGISTRY}/${IMAGE_NAME}" >> "$GITEA_OUTPUT" - echo "sha_tag=${REGISTRY}/${IMAGE_NAME}:${SHORT_SHA}" >> "$GITEA_OUTPUT" - echo "latest_tag=${REGISTRY}/${IMAGE_NAME}:latest" >> "$GITEA_OUTPUT" + if [ -n "${CUSTOM_IMAGE_NAME}" ]; then + IMAGE_REPO=$(echo "${CUSTOM_IMAGE_NAME}" | tr '[:upper:]' '[:lower:]') + else + IMAGE_REPO=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]') + fi + + # Branch-Namen als Docker-Tag nutzen (Schrägstriche durch Bindestriche ersetzen) + BRANCH_TAG=$(echo "${{ gitea.ref_name }}" | sed 's/[^a-zA-Z0-9._-]/-/g') + FULL_TAG="${REGISTRY}/${IMAGE_REPO}:${BRANCH_TAG}" + + echo "Target Image Tag: ${FULL_TAG}" + echo "image_tag=${FULL_TAG}" >> "$GITEA_OUTPUT" - name: Build Docker Image run: | docker build \ - -t webhost-test:ci \ - -t "${{ steps.meta.outputs.sha_tag }}" \ - -t "${{ steps.meta.outputs.latest_tag }}" \ - ./dockerfile + -f "${DOCKERFILE}" \ + -t "${{ steps.meta.outputs.image_tag }}" \ + "${BUILD_CONTEXT}" - - name: Start Container with Test ENV + - name: Start Container & Wait for Readiness run: | - docker rm -f webhost-test 2>/dev/null || true + docker rm -f "${CONTAINER_NAME}" 2>/dev/null || true + # shellcheck disable=SC2086 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 + --name "${CONTAINER_NAME}" \ + ${CONTAINER_ENV} \ + "${{ steps.meta.outputs.image_tag }}" - 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." + echo "Waiting up to ${STARTUP_TIMEOUT}s for container to become ready..." + for i in $(seq 1 "${STARTUP_TIMEOUT}"); do + if [ "$(docker inspect -f '{{.State.Running}}' "${CONTAINER_NAME}" 2>/dev/null)" = "true" ]; then + if [ -z "${READINESS_CMD}" ] || docker exec "${CONTAINER_NAME}" sh -c "${READINESS_CMD}" >/dev/null 2>&1; then + echo "Container is running and ready." break fi fi - if [ "$i" -eq 15 ]; then - echo "Container failed to start in time!" - docker logs webhost-test + if [ "$i" -eq "${STARTUP_TIMEOUT}" ]; then + echo "Container failed readiness check!" + docker logs "${CONTAINER_NAME}" exit 1 fi sleep 1 done - - name: Verify PHP Version & Extensions + - name: Verify PHP Extensions + if: env.REQUIRED_PHP_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"]; + docker exec "${CONTAINER_NAME}" php -v + docker exec -e REQUIRED_EXTS="${REQUIRED_PHP_EXTENSIONS}" "${CONTAINER_NAME}" php -r ' + $required = preg_split("/\s+/", trim(getenv("REQUIRED_EXTS")), -1, PREG_SPLIT_NO_EMPTY); $missing = []; foreach ($required as $ext) { if (!extension_loaded($ext)) { @@ -99,140 +115,57 @@ jobs: fwrite(STDERR, "Missing PHP extensions: " . implode(", ", $missing) . PHP_EOL); exit(1); } - echo "All required extensions are loaded: " . implode(", ", $required) . PHP_EOL; + echo "Verified PHP extensions: " . 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 + - name: Verify Apache Modules + if: env.REQUIRED_APACHE_MODULES != '' 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." + MODULES=$(docker exec "${CONTAINER_NAME}" apache2ctl -M) + for mod in ${REQUIRED_APACHE_MODULES}; do + echo "$MODULES" | grep -q "$mod" || { echo "Missing Apache module: $mod"; exit 1; } + done + echo "Verified Apache modules: ${REQUIRED_APACHE_MODULES}" - 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 + - name: Verify HTTP / HTTPS Response + if: env.TEST_HTTP_PORT != '' || env.TEST_HTTPS_PORT != '' 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 + if [ -n "${WEBROOT_DIR}" ]; then + docker exec "${CONTAINER_NAME}" sh -c " + mkdir -p '${WEBROOT_DIR}' && + if [ ! -f '${WEBROOT_DIR}/index.php' ] && [ ! -f '${WEBROOT_DIR}/index.html' ]; then + echo 'OK' > '${WEBROOT_DIR}/index.html' + fi + " + fi - test -f /etc/aliases - grep -q "^default: noreply@example.com$" /etc/aliases + if [ -n "${TEST_HTTP_PORT}" ]; then + echo "Testing HTTP on port ${TEST_HTTP_PORT}..." + docker exec "${CONTAINER_NAME}" curl -fsS "http://127.0.0.1:${TEST_HTTP_PORT}/" >/dev/null + echo "HTTP check passed." + fi - 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' + if [ -n "${TEST_HTTPS_PORT}" ]; then + echo "Testing HTTPS on port ${TEST_HTTPS_PORT}..." + docker exec "${CONTAINER_NAME}" curl -fsSk "https://127.0.0.1:${TEST_HTTPS_PORT}/" >/dev/null + echo "HTTPS check passed." + fi - name: Login to Gitea Container Registry if: success() && gitea.event_name != 'pull_request' run: | - echo "${{ secrets.PACKAGE_TOKEN || secrets.GITEA_TOKEN || gitea.token }}" | \ + echo "${{ secrets.PACKAGE_TOKEN || gitea.token }}" | \ docker login "${REGISTRY}" -u "${{ gitea.actor }}" --password-stdin - - name: Push Docker Image to Gitea Registry + - name: Push Docker Image if: success() && gitea.event_name != 'pull_request' run: | - docker push "${{ steps.meta.outputs.sha_tag }}" - docker push "${{ steps.meta.outputs.latest_tag }}" + docker push "${{ steps.meta.outputs.image_tag }}" - if [ "${{ gitea.ref_type }}" = "tag" ]; then - TAG_IMAGE="${{ steps.meta.outputs.image }}:${{ gitea.ref_name }}" - docker tag webhost-test:ci "${TAG_IMAGE}" - docker push "${TAG_IMAGE}" - fi - - - name: Cleanup Test Container + - name: Cleanup if: always() run: | echo "--- Container Logs ---" - docker logs webhost-test || true - docker rm -f webhost-test || true + docker logs "${CONTAINER_NAME}" || true + docker rm -f "${CONTAINER_NAME}" || true docker logout "${REGISTRY}" 2>/dev/null || true