From b7d9de441220bbf3d4dba23e8353f5ce3078ebe6 Mon Sep 17 00:00:00 2001 From: William Correa Date: Wed, 3 Jun 2026 23:35:20 -0300 Subject: [PATCH 1/3] feat(hyperf): add OTEL collector variants and unify hyperf-otel Restructures hyperf/ to follow the {image}/{version} pattern used by aws-cli, node, quasar, vue and merges the standalone hyperf-otel image into hyperf/8.3 as a multi-stage variant. Targets: - hyperf -> devitools/hyperf:8.3 (lean, ~97MB, ENTRYPOINT=php) - hyperf-otel -> devitools/hyperf:8.3- (~463MB, ENTRYPOINT=supervisord) Collectors live in hyperf/8.3/otel/collectors/*.yaml. New variants can be added by dropping a yaml file. Two ship in this PR: - debug (vendor-neutral, logs spans to stderr) - google (googlecloud exporter, replaces previous gcloud-specific default) hyperf/latest is a symlink to 8.3. Adds .github/workflows/build-images.yml: detects changed {image}/{version} folders on push to main, follows latest symlinks, and publishes one tag per (version, target) combo to Docker Hub via DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets. --- .github/workflows/build-images.yml | 165 +++++++++++++++++++ .github/workflows/validate.yml | 93 +++++++++++ hyperf/{ => 8.3}/.scripts/setup-dev.sh | 0 hyperf/{ => 8.3}/.scripts/setup.sh | 0 hyperf/{ => 8.3}/Dockerfile | 30 +++- hyperf/{ => 8.3}/README-pt-BR.md | 0 hyperf/{ => 8.3}/README.md | 0 hyperf/8.3/otel/collectors/debug.yaml | 22 +++ hyperf/8.3/otel/collectors/google.yaml | 22 +++ hyperf/8.3/otel/entrypoint.sh | 96 +++++++++++ hyperf/8.3/otel/supervisord.conf | 28 ++++ hyperf/{ => 8.3}/rootfs/apk/repositories | 0 hyperf/{ => 8.3}/rootfs/etc/php/php-fpm.conf | 0 hyperf/{ => 8.3}/rootfs/etc/php/php.ini | 0 hyperf/8.3/variants.yaml | 14 ++ hyperf/latest | 1 + 16 files changed, 464 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/build-images.yml create mode 100644 .github/workflows/validate.yml rename hyperf/{ => 8.3}/.scripts/setup-dev.sh (100%) rename hyperf/{ => 8.3}/.scripts/setup.sh (100%) rename hyperf/{ => 8.3}/Dockerfile (65%) rename hyperf/{ => 8.3}/README-pt-BR.md (100%) rename hyperf/{ => 8.3}/README.md (100%) create mode 100644 hyperf/8.3/otel/collectors/debug.yaml create mode 100644 hyperf/8.3/otel/collectors/google.yaml create mode 100755 hyperf/8.3/otel/entrypoint.sh create mode 100644 hyperf/8.3/otel/supervisord.conf rename hyperf/{ => 8.3}/rootfs/apk/repositories (100%) rename hyperf/{ => 8.3}/rootfs/etc/php/php-fpm.conf (100%) rename hyperf/{ => 8.3}/rootfs/etc/php/php.ini (100%) create mode 100644 hyperf/8.3/variants.yaml create mode 120000 hyperf/latest diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml new file mode 100644 index 0000000..82abb14 --- /dev/null +++ b/.github/workflows/build-images.yml @@ -0,0 +1,165 @@ +name: Build and push images + +on: + push: + branches: + - main + paths: + - '*/*/Dockerfile' + - '*/*/variants.yaml' + - '*/*/rootfs/**' + - '*/*/.scripts/**' + - '*/*/otel/**' + - '*/latest' + workflow_dispatch: + inputs: + target: + description: 'Image/version to build (e.g. hyperf/8.3 or hyperf/latest). Leave empty to detect.' + required: false + +jobs: + detect: + runs-on: ubuntu-latest + outputs: + builds: ${{ steps.list.outputs.builds }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get changed files + id: changed + if: github.event_name == 'push' + uses: tj-actions/changed-files@v44 + + - name: Build matrix + id: list + shell: bash + run: | + set -euo pipefail + + declare -a versions=() + + collect_version() { + local v="$1" + [ -z "$v" ] && return + local depth + depth=$(awk -F/ '{print NF}' <<< "$v") + if [ "$depth" != "2" ]; then return; fi + local resolved="$v" + if [ -L "$v" ]; then + local link_target + link_target=$(readlink "$v") + resolved="${v%/*}/${link_target}" + fi + if [ ! -f "${resolved}/Dockerfile" ]; then return; fi + for existing in "${versions[@]+"${versions[@]}"}"; do + if [ "$existing" = "$v" ]; then return; fi + done + versions+=("$v") + } + + if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.target }}" ]; then + collect_version "${{ inputs.target }}" + else + declare -a changed_dirs=() + for f in ${{ steps.changed.outputs.all_changed_files || '' }}; do + dir=$(awk -F/ 'NF>=2 {print $1"/"$2}' <<< "$f") + [ -z "$dir" ] && continue + for existing in "${changed_dirs[@]+"${changed_dirs[@]}"}"; do + if [ "$existing" = "$dir" ]; then dir=""; break; fi + done + [ -n "$dir" ] && changed_dirs+=("$dir") + done + + for v in "${changed_dirs[@]+"${changed_dirs[@]}"}"; do + collect_version "$v" + done + + for symlink in */latest; do + [ -L "$symlink" ] || continue + target=$(readlink "$symlink") + parent="${symlink%/*}" + resolved="${parent}/${target}" + for changed in "${changed_dirs[@]+"${changed_dirs[@]}"}"; do + if [ "$changed" = "$resolved" ]; then + collect_version "$symlink" + break + fi + done + done + fi + + declare -a builds=() + for v in "${versions[@]+"${versions[@]}"}"; do + image="${v%%/*}" + version="${v##*/}" + ctx="$v" + if [ -L "$ctx" ]; then + link_target=$(readlink "$ctx") + ctx="${ctx%/*}/${link_target}" + fi + + manifest="${ctx}/variants.yaml" + if [ -f "$manifest" ]; then + if ! yq eval 'all_c(.target != null and .target != "" and has("suffix"))' "$manifest" | grep -qx true; then + echo "::error file=${manifest}::each entry must declare 'target' (non-empty) and 'suffix' (key required, value may be empty)" + exit 1 + fi + entries=$(yq eval -o=json "$manifest") + else + entries='[{"target":"'"$image"'","suffix":""}]' + fi + + while IFS= read -r line; do + [ -z "$line" ] && continue + builds+=("$line") + done < <(jq -c --arg img "$image" --arg ver "$version" --arg ctx "$ctx" ' + .[] | { + image: $img, + tag: ($ver + (if (.suffix // "") == "" then "" else "-" + .suffix end)), + context: $ctx, + target: .target, + build_args: ((.args // {}) | to_entries | map(.key + "=" + (.value | tostring)) | join("\n")) + } + ' <<< "$entries") + done + + if [ ${#builds[@]} -eq 0 ]; then + echo "builds=[]" >> "$GITHUB_OUTPUT" + else + joined=$(IFS=,; echo "${builds[*]}") + echo "builds=[${joined}]" >> "$GITHUB_OUTPUT" + fi + + build: + needs: detect + if: needs.detect.outputs.builds != '[]' + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build: ${{ fromJson(needs.detect.outputs.builds) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./${{ matrix.build.context }} + target: ${{ matrix.build.target }} + build-args: ${{ matrix.build.build_args }} + platforms: linux/amd64 + push: true + tags: devitools/${{ matrix.build.image }}:${{ matrix.build.tag }} + cache-from: type=gha,scope=${{ matrix.build.image }}-${{ matrix.build.tag }} + cache-to: type=gha,mode=max,scope=${{ matrix.build.image }}-${{ matrix.build.tag }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..25d8209 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,93 @@ +name: Validate variants.yaml + +on: + pull_request: + branches: + - main + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get changed variants.yaml files + id: changed + uses: tj-actions/changed-files@v44 + with: + files: '*/*/variants.yaml' + + - name: Validate each manifest + if: steps.changed.outputs.any_changed == 'true' + shell: bash + run: | + set -uo pipefail + errors=0 + + for manifest in ${{ steps.changed.outputs.all_changed_files }}; do + echo "::group::${manifest}" + dir="$(dirname "$manifest")" + dockerfile="${dir}/Dockerfile" + + if ! yq eval '.' "$manifest" > /dev/null 2>&1; then + echo "::error file=${manifest}::invalid YAML syntax" + errors=$((errors+1)) + echo "::endgroup::" + continue + fi + + kind=$(yq eval 'type' "$manifest") + if [ "$kind" != "!!seq" ]; then + echo "::error file=${manifest}::root must be a YAML list (got ${kind})" + errors=$((errors+1)) + echo "::endgroup::" + continue + fi + + entries=$(yq eval -o=json "$manifest") + + bad=$(jq -c '[.[] | select((.target | type) != "string" or .target == "" or (has("suffix") | not))]' <<< "$entries") + if [ "$(jq 'length' <<< "$bad")" != "0" ]; then + echo "::error file=${manifest}::entries missing required 'target' (non-empty string) or 'suffix' key:" + jq -r '.[] | " - " + (. | tostring)' <<< "$bad" + errors=$((errors+1)) + fi + + bad_args=$(jq -c '[.[] | select(has("args") and (.args | type) != "object")]' <<< "$entries") + if [ "$(jq 'length' <<< "$bad_args")" != "0" ]; then + echo "::error file=${manifest}::'args' must be a mapping when present:" + jq -r '.[] | " - " + (. | tostring)' <<< "$bad_args" + errors=$((errors+1)) + fi + + if [ ! -f "$dockerfile" ]; then + echo "::error file=${manifest}::sibling Dockerfile not found at ${dockerfile}" + errors=$((errors+1)) + else + for target in $(jq -r '.[].target' <<< "$entries" | sort -u); do + if ! grep -qE "^FROM[[:space:]]+.*[[:space:]]+AS[[:space:]]+${target}([[:space:]]|$)" "$dockerfile"; then + echo "::error file=${manifest}::target '${target}' is not declared as a stage in ${dockerfile} (expected: FROM AS ${target})" + errors=$((errors+1)) + fi + done + fi + + duplicates=$(jq -r ' + [.[] | (if (.suffix // "") == "" then "" else .suffix end)] | + group_by(.) | map(select(length > 1)) | map(.[0]) | .[] + ' <<< "$entries" | sort -u) + if [ -n "$duplicates" ]; then + echo "::error file=${manifest}::duplicate suffix(es) detected (would produce colliding tags):" + echo "$duplicates" | sed 's/^/ - /' + errors=$((errors+1)) + fi + + echo "::endgroup::" + done + + if [ $errors -gt 0 ]; then + echo "Found ${errors} error(s) across the changed manifests." + exit 1 + fi + echo "All changed variants.yaml are valid." diff --git a/hyperf/.scripts/setup-dev.sh b/hyperf/8.3/.scripts/setup-dev.sh similarity index 100% rename from hyperf/.scripts/setup-dev.sh rename to hyperf/8.3/.scripts/setup-dev.sh diff --git a/hyperf/.scripts/setup.sh b/hyperf/8.3/.scripts/setup.sh similarity index 100% rename from hyperf/.scripts/setup.sh rename to hyperf/8.3/.scripts/setup.sh diff --git a/hyperf/Dockerfile b/hyperf/8.3/Dockerfile similarity index 65% rename from hyperf/Dockerfile rename to hyperf/8.3/Dockerfile index f9011c2..ec1e343 100644 --- a/hyperf/Dockerfile +++ b/hyperf/8.3/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.20 +FROM alpine:3.20 AS hyperf ARG CONTEXT ARG TIMEZONE @@ -57,18 +57,34 @@ COPY --from=composer/composer:2.8.5-bin /composer /usr/local/bin/composer COPY .scripts /devitools/.scripts -# update RUN set -ex \ - # ---------- apply settings -------\ && bash /devitools/.scripts/setup.sh "$TIMEZONE" \ && bash /devitools/.scripts/setup-dev.sh "$APP_TARGET" \ - # ---------- clear works ----------\ && rm -rf /var/cache/apk/* /tmp/* /usr/share/man WORKDIR /opt/www - EXPOSE 9501 +ENTRYPOINT ["php", "/opt/www/bin/hyperf.php"] +CMD ["start"] + +# --- Variant: with OTEL Collector + pgbouncer + supervisor --- +FROM hyperf AS hyperf-otel + +ARG COLLECTOR=debug +ARG OTEL_COLLECTOR_VERSION=0.121.0 + +RUN apk add --no-cache --upgrade expat \ + && apk add --no-cache supervisor wget pgbouncer \ + && wget -q "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_COLLECTOR_VERSION}/otelcol-contrib_${OTEL_COLLECTOR_VERSION}_linux_amd64.tar.gz" -O /tmp/otelcol.tar.gz \ + && tar -xzf /tmp/otelcol.tar.gz -C /usr/local/bin otelcol-contrib \ + && rm /tmp/otelcol.tar.gz \ + && chmod +x /usr/local/bin/otelcol-contrib \ + && mkdir -p /etc/pgbouncer /var/log/pgbouncer /var/run/pgbouncer /etc/supervisor.d /var/run/supervisor -ENTRYPOINT [ "php", "/opt/www/bin/hyperf.php" ] +COPY otel/collectors/${COLLECTOR}.yaml /etc/otel-collector-config.yaml +COPY otel/supervisord.conf /etc/supervisord.conf +COPY otel/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh -CMD [ "start" ] +ENTRYPOINT ["/entrypoint.sh"] +CMD [] diff --git a/hyperf/README-pt-BR.md b/hyperf/8.3/README-pt-BR.md similarity index 100% rename from hyperf/README-pt-BR.md rename to hyperf/8.3/README-pt-BR.md diff --git a/hyperf/README.md b/hyperf/8.3/README.md similarity index 100% rename from hyperf/README.md rename to hyperf/8.3/README.md diff --git a/hyperf/8.3/otel/collectors/debug.yaml b/hyperf/8.3/otel/collectors/debug.yaml new file mode 100644 index 0000000..4dc8718 --- /dev/null +++ b/hyperf/8.3/otel/collectors/debug.yaml @@ -0,0 +1,22 @@ +receivers: + zipkin: + endpoint: "0.0.0.0:9411" + +processors: + batch: + send_batch_size: 200 + timeout: 5s + memory_limiter: + check_interval: 1s + limit_mib: 256 + +exporters: + debug: + verbosity: normal + +service: + pipelines: + traces: + receivers: [zipkin] + processors: [memory_limiter, batch] + exporters: [debug] diff --git a/hyperf/8.3/otel/collectors/google.yaml b/hyperf/8.3/otel/collectors/google.yaml new file mode 100644 index 0000000..663fae1 --- /dev/null +++ b/hyperf/8.3/otel/collectors/google.yaml @@ -0,0 +1,22 @@ +receivers: + zipkin: + endpoint: "0.0.0.0:9411" + +processors: + batch: + send_batch_size: 200 + timeout: 5s + memory_limiter: + check_interval: 1s + limit_mib: 256 + +exporters: + googlecloud: + project: ${GOOGLE_CLOUD_PROJECT} + +service: + pipelines: + traces: + receivers: [zipkin] + processors: [memory_limiter, batch] + exporters: [googlecloud] diff --git a/hyperf/8.3/otel/entrypoint.sh b/hyperf/8.3/otel/entrypoint.sh new file mode 100755 index 0000000..0d48cef --- /dev/null +++ b/hyperf/8.3/otel/entrypoint.sh @@ -0,0 +1,96 @@ +#!/bin/sh +set -e + +if [ "$PGBOUNCER_ENABLED" != "true" ]; then + exec supervisord -c /etc/supervisord.conf +fi + +PGBOUNCER_DATABASES="${PGBOUNCER_DATABASES:-default}" + +DEFAULT_POOL_SIZE="${PGBOUNCER_DEFAULT_POOL_SIZE:-5}" +MIN_POOL_SIZE="${PGBOUNCER_MIN_POOL_SIZE:-1}" +RESERVE_POOL_SIZE="${PGBOUNCER_RESERVE_POOL_SIZE:-2}" +MAX_CLIENT_CONN="${PGBOUNCER_MAX_CLIENT_CONN:-1000}" +MAX_PREPARED_STATEMENTS="${PGBOUNCER_MAX_PREPARED_STATEMENTS:-100}" +SERVER_IDLE_TIMEOUT="${PGBOUNCER_SERVER_IDLE_TIMEOUT:-300}" +SERVER_LIFETIME="${PGBOUNCER_SERVER_LIFETIME:-3600}" + +resolve_prefix() { + if [ "$1" = "default" ]; then + echo "POSTGRES_DB" + else + echo "POSTGRES_DB_$(echo "$1" | tr '[:lower:]' '[:upper:]')" + fi +} + +echo "[databases]" > /etc/pgbouncer/pgbouncer.ini + +OLD_IFS="$IFS" +IFS=',' +for alias in $PGBOUNCER_DATABASES; do + IFS="$OLD_IFS" + alias=$(echo "$alias" | tr -d ' ') + if [ -n "$alias" ]; then + prefix=$(resolve_prefix "$alias") + host=$(eval "printf '%s' \"\${${prefix}_HOST:-}\"") + port=$(eval "printf '%s' \"\${${prefix}_PORT:-5432}\"") + name=$(eval "printf '%s' \"\${${prefix}_NAME:-}\"") + user=$(eval "printf '%s' \"\${${prefix}_USERNAME:-}\"") + pass=$(eval "printf '%s' \"\${${prefix}_PASSWORD:-}\"") + + echo "pgb_${alias} = host=${host} port=${port} dbname=${name} user=${user} password=${pass}" >> /etc/pgbouncer/pgbouncer.ini + fi + IFS=',' +done +IFS="$OLD_IFS" + +cat >> /etc/pgbouncer/pgbouncer.ini < /etc/supervisor.d/pgbouncer.ini < Date: Thu, 4 Jun 2026 00:17:12 -0300 Subject: [PATCH 2/3] fix: address coderabbit review findings - workflows: declare explicit contents:read permissions and pass GitHub-context values through env: instead of inline ${{ }} expansion (mitigates template injection risk) - workflow_dispatch: require target input (avoids empty matrix on manual runs without input) - hyperf/8.3/Dockerfile: verify otelcol-contrib tarball sha256 against the published opentelemetry-collector-releases checksums - hyperf/8.3/otel/entrypoint.sh: whitelist PGBOUNCER_DATABASES alias chars before eval, and fail fast when a required POSTGRES_DB_* var is empty for an alias --- .github/workflows/build-images.yml | 21 ++++++++++++++++----- .github/workflows/validate.yml | 11 ++++++++++- hyperf/8.3/Dockerfile | 11 ++++++++--- hyperf/8.3/otel/entrypoint.sh | 16 ++++++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml index 82abb14..e9aeec4 100644 --- a/.github/workflows/build-images.yml +++ b/.github/workflows/build-images.yml @@ -14,8 +14,11 @@ on: workflow_dispatch: inputs: target: - description: 'Image/version to build (e.g. hyperf/8.3 or hyperf/latest). Leave empty to detect.' - required: false + description: 'Image/version to build (e.g. hyperf/8.3 or hyperf/latest).' + required: true + +permissions: + contents: read jobs: detect: @@ -34,6 +37,10 @@ jobs: - name: Build matrix id: list shell: bash + env: + EVENT_NAME: ${{ github.event_name }} + INPUT_TARGET: ${{ inputs.target }} + CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }} run: | set -euo pipefail @@ -42,6 +49,10 @@ jobs: collect_version() { local v="$1" [ -z "$v" ] && return + case "$v" in + [A-Za-z0-9_./-]*) ;; + *) echo "::warning::ignoring suspicious path '$v'"; return ;; + esac local depth depth=$(awk -F/ '{print NF}' <<< "$v") if [ "$depth" != "2" ]; then return; fi @@ -58,11 +69,11 @@ jobs: versions+=("$v") } - if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.target }}" ]; then - collect_version "${{ inputs.target }}" + if [ "$EVENT_NAME" = "workflow_dispatch" ]; then + collect_version "$INPUT_TARGET" else declare -a changed_dirs=() - for f in ${{ steps.changed.outputs.all_changed_files || '' }}; do + for f in $CHANGED_FILES; do dir=$(awk -F/ 'NF>=2 {print $1"/"$2}' <<< "$f") [ -z "$dir" ] && continue for existing in "${changed_dirs[@]+"${changed_dirs[@]}"}"; do diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 25d8209..da6b786 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -5,6 +5,9 @@ on: branches: - main +permissions: + contents: read + jobs: validate: runs-on: ubuntu-latest @@ -21,11 +24,17 @@ jobs: - name: Validate each manifest if: steps.changed.outputs.any_changed == 'true' shell: bash + env: + CHANGED_MANIFESTS: ${{ steps.changed.outputs.all_changed_files }} run: | set -uo pipefail errors=0 - for manifest in ${{ steps.changed.outputs.all_changed_files }}; do + for manifest in $CHANGED_MANIFESTS; do + case "$manifest" in + [A-Za-z0-9_./-]*) ;; + *) echo "::warning::skipping suspicious path '$manifest'"; continue ;; + esac echo "::group::${manifest}" dir="$(dirname "$manifest")" dockerfile="${dir}/Dockerfile" diff --git a/hyperf/8.3/Dockerfile b/hyperf/8.3/Dockerfile index ec1e343..9626fdb 100644 --- a/hyperf/8.3/Dockerfile +++ b/hyperf/8.3/Dockerfile @@ -75,9 +75,14 @@ ARG OTEL_COLLECTOR_VERSION=0.121.0 RUN apk add --no-cache --upgrade expat \ && apk add --no-cache supervisor wget pgbouncer \ - && wget -q "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_COLLECTOR_VERSION}/otelcol-contrib_${OTEL_COLLECTOR_VERSION}_linux_amd64.tar.gz" -O /tmp/otelcol.tar.gz \ - && tar -xzf /tmp/otelcol.tar.gz -C /usr/local/bin otelcol-contrib \ - && rm /tmp/otelcol.tar.gz \ + && OTEL_BASE_URL="https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_COLLECTOR_VERSION}" \ + && OTEL_ASSET="otelcol-contrib_${OTEL_COLLECTOR_VERSION}_linux_amd64.tar.gz" \ + && cd /tmp \ + && wget -q "${OTEL_BASE_URL}/${OTEL_ASSET}" -O "${OTEL_ASSET}" \ + && wget -q "${OTEL_BASE_URL}/opentelemetry-collector-releases_otelcol-contrib_checksums.txt" -O checksums.txt \ + && grep " ${OTEL_ASSET}$" checksums.txt | sha256sum -c - \ + && tar -xzf "${OTEL_ASSET}" -C /usr/local/bin otelcol-contrib \ + && rm "${OTEL_ASSET}" checksums.txt \ && chmod +x /usr/local/bin/otelcol-contrib \ && mkdir -p /etc/pgbouncer /var/log/pgbouncer /var/run/pgbouncer /etc/supervisor.d /var/run/supervisor diff --git a/hyperf/8.3/otel/entrypoint.sh b/hyperf/8.3/otel/entrypoint.sh index 0d48cef..57d6b3c 100755 --- a/hyperf/8.3/otel/entrypoint.sh +++ b/hyperf/8.3/otel/entrypoint.sh @@ -15,6 +15,15 @@ MAX_PREPARED_STATEMENTS="${PGBOUNCER_MAX_PREPARED_STATEMENTS:-100}" SERVER_IDLE_TIMEOUT="${PGBOUNCER_SERVER_IDLE_TIMEOUT:-300}" SERVER_LIFETIME="${PGBOUNCER_SERVER_LIFETIME:-3600}" +validate_alias() { + case "$1" in + *[!A-Za-z0-9_]*|"") + echo "entrypoint: invalid PGBOUNCER_DATABASES alias '$1' (allowed: [A-Za-z0-9_])" >&2 + exit 1 + ;; + esac +} + resolve_prefix() { if [ "$1" = "default" ]; then echo "POSTGRES_DB" @@ -31,6 +40,7 @@ for alias in $PGBOUNCER_DATABASES; do IFS="$OLD_IFS" alias=$(echo "$alias" | tr -d ' ') if [ -n "$alias" ]; then + validate_alias "$alias" prefix=$(resolve_prefix "$alias") host=$(eval "printf '%s' \"\${${prefix}_HOST:-}\"") port=$(eval "printf '%s' \"\${${prefix}_PORT:-5432}\"") @@ -38,6 +48,11 @@ for alias in $PGBOUNCER_DATABASES; do user=$(eval "printf '%s' \"\${${prefix}_USERNAME:-}\"") pass=$(eval "printf '%s' \"\${${prefix}_PASSWORD:-}\"") + [ -z "$host" ] && { echo "entrypoint: ${prefix}_HOST is required for alias '${alias}'" >&2; exit 1; } + [ -z "$name" ] && { echo "entrypoint: ${prefix}_NAME is required for alias '${alias}'" >&2; exit 1; } + [ -z "$user" ] && { echo "entrypoint: ${prefix}_USERNAME is required for alias '${alias}'" >&2; exit 1; } + [ -z "$pass" ] && { echo "entrypoint: ${prefix}_PASSWORD is required for alias '${alias}'" >&2; exit 1; } + echo "pgb_${alias} = host=${host} port=${port} dbname=${name} user=${user} password=${pass}" >> /etc/pgbouncer/pgbouncer.ini fi IFS=',' @@ -82,6 +97,7 @@ for alias in $PGBOUNCER_DATABASES; do IFS="$OLD_IFS" alias=$(echo "$alias" | tr -d ' ') if [ -n "$alias" ]; then + validate_alias "$alias" prefix=$(resolve_prefix "$alias") eval "export ${prefix}_HOST=127.0.0.1" eval "export ${prefix}_PORT=6432" From 81aea137846b3f473b33f4795fe89471db69a1bd Mon Sep 17 00:00:00 2001 From: William Correa Date: Thu, 18 Jun 2026 09:52:12 -0300 Subject: [PATCH 3/3] refactor: split new hyperf work into php-hyperf image Keep legacy hyperf/ untouched so devitools/hyperf is not overwritten. New multi-variant work (otel, debug, google, dev) lives under php-hyperf/8.3 and publishes to devitools/php-hyperf. --- .github/workflows/build-images.yml | 2 +- hyperf/{8.3 => }/.scripts/setup-dev.sh | 0 hyperf/{8.3 => }/.scripts/setup.sh | 0 hyperf/Dockerfile | 74 ++++++++ hyperf/{8.3 => }/README-pt-BR.md | 0 hyperf/{8.3 => }/README.md | 0 hyperf/{8.3 => }/rootfs/apk/repositories | 0 hyperf/{8.3 => }/rootfs/etc/php/php-fpm.conf | 0 hyperf/{8.3 => }/rootfs/etc/php/php.ini | 0 php-hyperf/8.3/.scripts/setup-dev.sh | 44 +++++ php-hyperf/8.3/.scripts/setup.sh | 18 ++ {hyperf => php-hyperf}/8.3/Dockerfile | 0 php-hyperf/8.3/README-pt-BR.md | 79 +++++++++ php-hyperf/8.3/README.md | 158 ++++++++++++++++++ .../8.3/otel/collectors/debug.yaml | 0 .../8.3/otel/collectors/google.yaml | 0 {hyperf => php-hyperf}/8.3/otel/entrypoint.sh | 0 .../8.3/otel/supervisord.conf | 0 php-hyperf/8.3/rootfs/apk/repositories | 2 + php-hyperf/8.3/rootfs/etc/php/php-fpm.conf | 2 + php-hyperf/8.3/rootfs/etc/php/php.ini | 11 ++ {hyperf => php-hyperf}/8.3/variants.yaml | 0 {hyperf => php-hyperf}/latest | 0 23 files changed, 389 insertions(+), 1 deletion(-) rename hyperf/{8.3 => }/.scripts/setup-dev.sh (100%) rename hyperf/{8.3 => }/.scripts/setup.sh (100%) create mode 100644 hyperf/Dockerfile rename hyperf/{8.3 => }/README-pt-BR.md (100%) rename hyperf/{8.3 => }/README.md (100%) rename hyperf/{8.3 => }/rootfs/apk/repositories (100%) rename hyperf/{8.3 => }/rootfs/etc/php/php-fpm.conf (100%) rename hyperf/{8.3 => }/rootfs/etc/php/php.ini (100%) create mode 100755 php-hyperf/8.3/.scripts/setup-dev.sh create mode 100755 php-hyperf/8.3/.scripts/setup.sh rename {hyperf => php-hyperf}/8.3/Dockerfile (100%) create mode 100644 php-hyperf/8.3/README-pt-BR.md create mode 100644 php-hyperf/8.3/README.md rename {hyperf => php-hyperf}/8.3/otel/collectors/debug.yaml (100%) rename {hyperf => php-hyperf}/8.3/otel/collectors/google.yaml (100%) rename {hyperf => php-hyperf}/8.3/otel/entrypoint.sh (100%) rename {hyperf => php-hyperf}/8.3/otel/supervisord.conf (100%) create mode 100644 php-hyperf/8.3/rootfs/apk/repositories create mode 100644 php-hyperf/8.3/rootfs/etc/php/php-fpm.conf create mode 100644 php-hyperf/8.3/rootfs/etc/php/php.ini rename {hyperf => php-hyperf}/8.3/variants.yaml (100%) rename {hyperf => php-hyperf}/latest (100%) diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml index e9aeec4..e1374ec 100644 --- a/.github/workflows/build-images.yml +++ b/.github/workflows/build-images.yml @@ -14,7 +14,7 @@ on: workflow_dispatch: inputs: target: - description: 'Image/version to build (e.g. hyperf/8.3 or hyperf/latest).' + description: 'Image/version to build (e.g. php-hyperf/8.3 or php-hyperf/latest).' required: true permissions: diff --git a/hyperf/8.3/.scripts/setup-dev.sh b/hyperf/.scripts/setup-dev.sh similarity index 100% rename from hyperf/8.3/.scripts/setup-dev.sh rename to hyperf/.scripts/setup-dev.sh diff --git a/hyperf/8.3/.scripts/setup.sh b/hyperf/.scripts/setup.sh similarity index 100% rename from hyperf/8.3/.scripts/setup.sh rename to hyperf/.scripts/setup.sh diff --git a/hyperf/Dockerfile b/hyperf/Dockerfile new file mode 100644 index 0000000..f9011c2 --- /dev/null +++ b/hyperf/Dockerfile @@ -0,0 +1,74 @@ +FROM alpine:3.20 + +ARG CONTEXT +ARG TIMEZONE +ARG APP_TARGET="liv" + +ENV TIMEZONE=${TIMEZONE:-"UTC"} \ + STDOUT_LOG_LEVEL=alert,critical,emergency,error,warning \ + SCAN_CACHEABLE=(true) + +COPY ${CONTEXT:-""}/rootfs / + +RUN apk update && \ + apk upgrade --available && \ + apk add --no-cache bash curl git unzip && \ + mkdir -p /opt/www + +SHELL ["/bin/ash", "-o", "pipefail", "-c"] + +RUN apk add --no-cache \ + php83-bcmath=8.3.15-r0 \ + php83-ctype=8.3.15-r0 \ + php83-curl=8.3.15-r0 \ + php83-dom=8.3.15-r0 \ + php83-fileinfo=8.3.15-r0 \ + php83-fpm=8.3.15-r0 \ + php83-gd=8.3.15-r0 \ + php83-iconv=8.3.15-r0 \ + php83-intl=8.3.15-r0 \ + php83-mbstring=8.3.15-r0 \ + php83-opcache=8.3.15-r0 \ + php83-openssl=8.3.15-r0 \ + php83-pcntl=8.3.15-r0 \ + php83-pdo=8.3.15-r0 \ + php83-pdo_mysql=8.3.15-r0 \ + php83-pecl-decimal=1.5.0-r1 \ + php83-pecl-ds=1.5.0-r0 \ + php83-pecl-mcrypt=1.0.7-r0 \ + php83-pecl-mongodb=1.19.1-r0 \ + php83-pecl-rdkafka=6.0.5-r0 \ + php83-pecl-redis=6.1.0-r0 \ + php83-pecl-swoole=5.1.6-r0 \ + php83-phar=8.3.15-r0 \ + php83-posix=8.3.15-r0 \ + php83-simplexml=8.3.15-r0 \ + php83-sodium=8.3.15-r0 \ + php83-tokenizer=8.3.15-r0 \ + php83-xml=8.3.15-r0 \ + php83-xmlreader=8.3.15-r0 \ + php83-xmlwriter=8.3.15-r0 \ + php83-zip=8.3.15-r0 \ + && ln -sf /usr/bin/php83 /usr/bin/php \ + && mv /etc/php/php.ini /etc/php83/conf.d/zzz_1_php.ini \ + && mv /etc/php/php-fpm.conf /etc/php83/php-fpm.d/zphp.conf + +COPY --from=composer/composer:2.8.5-bin /composer /usr/local/bin/composer + +COPY .scripts /devitools/.scripts + +# update +RUN set -ex \ + # ---------- apply settings -------\ + && bash /devitools/.scripts/setup.sh "$TIMEZONE" \ + && bash /devitools/.scripts/setup-dev.sh "$APP_TARGET" \ + # ---------- clear works ----------\ + && rm -rf /var/cache/apk/* /tmp/* /usr/share/man + +WORKDIR /opt/www + +EXPOSE 9501 + +ENTRYPOINT [ "php", "/opt/www/bin/hyperf.php" ] + +CMD [ "start" ] diff --git a/hyperf/8.3/README-pt-BR.md b/hyperf/README-pt-BR.md similarity index 100% rename from hyperf/8.3/README-pt-BR.md rename to hyperf/README-pt-BR.md diff --git a/hyperf/8.3/README.md b/hyperf/README.md similarity index 100% rename from hyperf/8.3/README.md rename to hyperf/README.md diff --git a/hyperf/8.3/rootfs/apk/repositories b/hyperf/rootfs/apk/repositories similarity index 100% rename from hyperf/8.3/rootfs/apk/repositories rename to hyperf/rootfs/apk/repositories diff --git a/hyperf/8.3/rootfs/etc/php/php-fpm.conf b/hyperf/rootfs/etc/php/php-fpm.conf similarity index 100% rename from hyperf/8.3/rootfs/etc/php/php-fpm.conf rename to hyperf/rootfs/etc/php/php-fpm.conf diff --git a/hyperf/8.3/rootfs/etc/php/php.ini b/hyperf/rootfs/etc/php/php.ini similarity index 100% rename from hyperf/8.3/rootfs/etc/php/php.ini rename to hyperf/rootfs/etc/php/php.ini diff --git a/php-hyperf/8.3/.scripts/setup-dev.sh b/php-hyperf/8.3/.scripts/setup-dev.sh new file mode 100755 index 0000000..1e1beb3 --- /dev/null +++ b/php-hyperf/8.3/.scripts/setup-dev.sh @@ -0,0 +1,44 @@ +set -e + +SONAR_SCANNER_VERSION=6.2.1.4610 + +if [ "$1" = "dev" ]; then + if ! command -v apk &> /dev/null; then + echo "Error: 'apk' not found. Make sure you are running this script in an Alpine Linux environment." >&2 + exit 1 + fi + + if ! command -v composer &> /dev/null; then + echo "Error: 'composer' not found. Make sure it is installed and accessible in the system PATH." >&2 + exit 1 + fi + + echo "[$1] Installing PHP extensions and dependencies" + + apk add --no-cache \ + libstdc++ \ + ca-certificates \ + libc6-compat \ + openjdk17-jre \ + php83-pecl-xdebug \ + php83-pecl-pcov + + { + echo "opcache.enable=0" + echo "opcache.interned_strings_buffer=72" + echo "xdebug.mode=develop,debug,coverage" + echo "xdebug.idekey=PHPSTORM" + } >> /etc/php83/conf.d/zzz_2_php.ini + + mkdir -p /opt + curl -fSL https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip \ + -o /opt/sonar-scanner.zip + + unzip -qq /opt/sonar-scanner.zip -d /opt + mv /opt/sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64 /sonar-scanner + rm /opt/sonar-scanner.zip + + ln -s /sonar-scanner/bin/sonar-scanner /bin/sonar-scanner + + sed -i 's/use_embedded_jre=true/use_embedded_jre=false/g' /sonar-scanner/bin/sonar-scanner +fi diff --git a/php-hyperf/8.3/.scripts/setup.sh b/php-hyperf/8.3/.scripts/setup.sh new file mode 100755 index 0000000..b99313a --- /dev/null +++ b/php-hyperf/8.3/.scripts/setup.sh @@ -0,0 +1,18 @@ +set -e + +TIMEZONE=${1:-UTC} + +git config --global --add safe.directory /opt/www +git config --global init.defaultBranch main + +# - config PHP +{ + echo "upload_max_filesize=128M" + echo "post_max_size=128M" + echo "memory_limit=1G" + echo "date.timezone=${TIMEZONE}" +} | tee /etc/php83/conf.d/zzz_0_php.ini + +# - config timezone +ln -sf "/usr/share/zoneinfo/${TIMEZONE}" /etc/localtime +echo "${TIMEZONE}" > /etc/timezone diff --git a/hyperf/8.3/Dockerfile b/php-hyperf/8.3/Dockerfile similarity index 100% rename from hyperf/8.3/Dockerfile rename to php-hyperf/8.3/Dockerfile diff --git a/php-hyperf/8.3/README-pt-BR.md b/php-hyperf/8.3/README-pt-BR.md new file mode 100644 index 0000000..d37d40c --- /dev/null +++ b/php-hyperf/8.3/README-pt-BR.md @@ -0,0 +1,79 @@ +# Devitools Hyperf Docker Image + +## Introdução +Esta imagem Docker foi criada para fornecer um ambiente otimizado para aplicações **Hyperf** em **PHP 8.3**, suportando tanto ambientes de desenvolvimento quanto de produção. + +Ela inclui configurações específicas para **Xdebug**, **Sonar Scanner**, ajustes de performance no PHP e suporte a análise estática de código. + +--- + +## 📦 Conteúdo da Imagem +A imagem contém: +- **PHP 8.3** com extensões essenciais +- **Composer** para gerenciamento de dependências +- **Xdebug** e **PCOV** para depuração e cobertura de código +- **Sonar Scanner** para análise de qualidade de código +- **Configuração de timezone** ajustável +- **Suporte a análise de código via SonarQube** + +--- + +## 🛠️ Configuração e Instalação +A configuração da imagem é realizada através dos scripts: + +### `setup.sh` +- Ajusta configurações do PHP, incluindo **limite de memória**, **upload_max_filesize**, e **timezone**. +- Configura o timezone do sistema. + +### `setup-dev.sh` +- Instala dependências para desenvolvimento, incluindo **Xdebug** e **Sonar Scanner**. +- Configura `xdebug.ini` para integração com **PHPStorm**. +- Desativa **JRE embutido** no Sonar Scanner para evitar conflitos. + +--- + +## 📌 Como Construir a Imagem +A imagem pode ser construída de duas formas: **para desenvolvimento** e **para produção**. + +### 🔹 **Imagem de Desenvolvimento** +Inclui **Xdebug**, **PCOV** e **Sonar Scanner** para depuração e análise de código. + +```sh +docker build --platform="linux/amd64" --build-arg APP_TARGET=dev -t devitools/php-hyperf:8.3-dev . +``` + +### 🔹 **Imagem de Produção** +Removendo ferramentas de desenvolvimento para otimizar o ambiente de execução. + +```sh +docker build --platform="linux/amd64" -t devitools/php-hyperf:8.3 . +``` + +--- + +## 🚀 Diferenças entre as Versões + +| Versão | Recursos Incluídos | +|-----------------------|------------------| +| `devitools/php-hyperf:8.3-dev` | PHP 8.3 + Xdebug + PCOV + Sonar Scanner | +| `devitools/php-hyperf:8.3` | PHP 8.3 otimizado para produção | + +--- + +## 🛠 Uso +Para rodar um container baseado na imagem: + +```sh +docker run --rm -it devitools/php-hyperf:8.3-dev php -v +``` + +Para iniciar um projeto Hyperf com a imagem: + +```sh +docker run --rm -it -v $(pwd):/opt/www devitools/php-hyperf:8.3-dev composer create-project hyperf/hyperf-skeleton . +``` + +--- + +## 📌 Conclusão +Esta imagem proporciona um ambiente completo para desenvolvimento e execução de aplicações Hyperf, garantindo produtividade e qualidade no código. diff --git a/php-hyperf/8.3/README.md b/php-hyperf/8.3/README.md new file mode 100644 index 0000000..15c9f1c --- /dev/null +++ b/php-hyperf/8.3/README.md @@ -0,0 +1,158 @@ +# Devitools Hyperf + +Optimized image for running Hyperf applications with PostgreSQL and Swoole support. + +## Introduction + +This Docker image is designed to provide an optimized environment for **Hyperf** applications running **PHP 8.3**, +supporting both development and production environments. + +It includes specific configurations for **Xdebug**, **Sonar Scanner**, PHP performance tuning, and static code analysis +support. + +## 🛠️ How to Use + +### Run a Container Directly + +```sh +docker run --rm --name hyperf -d -v "$(pwd):/opt/www" -p "8080:9501" --platform linux/amd64 devitools/php-hyperf:8.3-dev +``` + +### Example `Dockerfile` Ready for Production + +```dockerfile +FROM devitools/php-hyperf:8.3 + +COPY . /opt/www + +RUN composer install --prefer-dist --no-dev --optimize-autoloader +``` + +## 🚀 Example `docker-compose.yml` Ready for dev + +```yaml +services: + app: + image: devitools/php-hyperf:8.3-dev + container_name: template_name-app + command: [ "server:watch" ] + volumes: + - ./:/opt/www + ports: + - "9501:9501" + environment: + - SCAN_CACHEABLE=false + - STDOUT_LOG_LEVEL=alert,critical,emergency,error,warning,notice,info + restart: on-failure +``` + +## 📌 Environment Variables + +- `SCAN_CACHEABLE`: Controls Hyperf’s scan cache. +- `STDOUT_LOG_LEVEL`: Sets the log levels sent to `stdout`. + +## 🏗️ Just Run, no Build + +```sh +docker-compose up -d +``` + +## 📂 Related Repositories + +- **Dockerfile Repository** (Source code for this image): + 🔗 [github.com/devitools/dockerfile](https://github.com/devitools/dockerfile) + +- **Example Project** (Hyperf with this image): + 🔗 [github.com/phpcomrapadura/hyperf-com-rapadura](https://github.com/phpcomrapadura/hyperf-com-rapadura) + +--- + +## 📦 Image Contents + +The image includes: + +- **PHP 8.3** with essential extensions +- **Composer** for dependency management +- **Xdebug** and **PCOV** for debugging and code coverage +- **Sonar Scanner** for code quality analysis +- **Adjustable timezone configuration** +- **Support for static code analysis via SonarQube** + +--- + +## 🛠️ Configuration and Installation + +The image configuration is handled through the following scripts: + +### `setup.sh` + +- Adjusts PHP settings, including **memory limit**, **upload_max_filesize**, and **timezone**. +- Configures the system timezone. + +### `setup-dev.sh` + +- Installs development dependencies, including **Xdebug** and **Sonar Scanner**. +- Configures `xdebug.ini` for **PHPStorm** integration. +- Disables **embedded JRE** in Sonar Scanner to avoid conflicts. + +--- + +## 📌 How to Build the Image + +The image can be built in two ways: **for development** and **for production**. + +### 🔹 **Development Image** + +Includes **Xdebug**, **PCOV**, and **Sonar Scanner** for debugging and code analysis. + +```sh +docker build --platform="linux/amd64" --build-arg APP_TARGET=dev -t devitools/php-hyperf:8.3-dev . +``` + +### 🔹 **Production Image** + +Removes development tools to optimize the runtime environment. + +```sh +docker build --platform="linux/amd64" -t devitools/php-hyperf:8.3 . +``` + +## ✨ How to publish the new image + +After building the image, you can push it to Docker Hub: + +```sh +docker push devitools/php-hyperf:8.3-dev +``` + +--- + +## 🚀 Differences Between Versions + +| Version | Included Features | +|----------------------------|-----------------------------------------| +| `devitools/php-hyperf:8.3-dev` | PHP 8.3 + Xdebug + PCOV + Sonar Scanner | +| `devitools/php-hyperf:8.3` | PHP 8.3 optimized for production | + +--- + +## 🛠 Usage + +To run a container based on the image: + +```sh +docker run --rm -it devitools/php-hyperf:8.3-dev php -v +``` + +To start a Hyperf project with the image: + +```sh +docker run --rm -it -v $(pwd):/opt/www devitools/php-hyperf:8.3-dev composer create-project hyperf/hyperf-skeleton . +``` + +--- + +## 📌 Conclusion + +This image provides a complete environment for developing and running Hyperf applications, ensuring productivity and +code quality. diff --git a/hyperf/8.3/otel/collectors/debug.yaml b/php-hyperf/8.3/otel/collectors/debug.yaml similarity index 100% rename from hyperf/8.3/otel/collectors/debug.yaml rename to php-hyperf/8.3/otel/collectors/debug.yaml diff --git a/hyperf/8.3/otel/collectors/google.yaml b/php-hyperf/8.3/otel/collectors/google.yaml similarity index 100% rename from hyperf/8.3/otel/collectors/google.yaml rename to php-hyperf/8.3/otel/collectors/google.yaml diff --git a/hyperf/8.3/otel/entrypoint.sh b/php-hyperf/8.3/otel/entrypoint.sh similarity index 100% rename from hyperf/8.3/otel/entrypoint.sh rename to php-hyperf/8.3/otel/entrypoint.sh diff --git a/hyperf/8.3/otel/supervisord.conf b/php-hyperf/8.3/otel/supervisord.conf similarity index 100% rename from hyperf/8.3/otel/supervisord.conf rename to php-hyperf/8.3/otel/supervisord.conf diff --git a/php-hyperf/8.3/rootfs/apk/repositories b/php-hyperf/8.3/rootfs/apk/repositories new file mode 100644 index 0000000..91b969a --- /dev/null +++ b/php-hyperf/8.3/rootfs/apk/repositories @@ -0,0 +1,2 @@ +https://dl-cdn.alpinelinux.org/alpine/v3.20/main +https://dl-cdn.alpinelinux.org/alpine/v3.20/community diff --git a/php-hyperf/8.3/rootfs/etc/php/php-fpm.conf b/php-hyperf/8.3/rootfs/etc/php/php-fpm.conf new file mode 100644 index 0000000..db92dbe --- /dev/null +++ b/php-hyperf/8.3/rootfs/etc/php/php-fpm.conf @@ -0,0 +1,2 @@ +[www] +listen = 9000 diff --git a/php-hyperf/8.3/rootfs/etc/php/php.ini b/php-hyperf/8.3/rootfs/etc/php/php.ini new file mode 100644 index 0000000..2b9a62d --- /dev/null +++ b/php-hyperf/8.3/rootfs/etc/php/php.ini @@ -0,0 +1,11 @@ +disable_functions=phpinfo + +[opcache] +opcache.enable=1 +opcache.enable_cli=1 +opcache.validate_timestamps=0 +opcache.use_cwd=0 +opcache.log_verbosity_level=2 + +[swoole] +swoole.use_shortname=Off diff --git a/hyperf/8.3/variants.yaml b/php-hyperf/8.3/variants.yaml similarity index 100% rename from hyperf/8.3/variants.yaml rename to php-hyperf/8.3/variants.yaml diff --git a/hyperf/latest b/php-hyperf/latest similarity index 100% rename from hyperf/latest rename to php-hyperf/latest