diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 651a104..d1b8187 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,11 @@ name: Build and Release Module nginx_versions: description: "Space-separated Nginx versions to build against" required: true - default: "1.22.1 1.24.0 1.26.3 1.28.0" + default: "1.22.1 1.24.0 1.26.3 1.28.0 1.30.0" + target_arches: + description: "Space-separated targets: linux-x86_64 linux-arm64 linux-armv7" + required: true + default: "linux-x86_64 linux-arm64 linux-armv7" version_bump: description: "Semantic version part to increment from the latest v* tag" required: true @@ -17,7 +21,7 @@ name: Build and Release Module - minor - major push_image: - description: "Push Docker image to GHCR using the new tag" + description: "Push multi-platform Docker image to GHCR using the new tag" type: boolean required: true default: true @@ -27,8 +31,10 @@ permissions: packages: write env: - DEFAULT_NGINX_VERSIONS: "1.22.1 1.24.0 1.26.3 1.28.0" + DEFAULT_NGINX_VERSIONS: "1.22.1 1.24.0 1.26.3 1.28.0 1.30.0" + DEFAULT_TARGET_ARCHES: "linux-x86_64 linux-arm64 linux-armv7" MODULE_NAME: ngx_http_monitoring_module + RELEASE_BUILD_IMAGE: ubuntu:22.04 NGINX_CONFIGURE_ARGS: >- --with-compat --with-http_ssl_module @@ -41,6 +47,7 @@ jobs: release: name: Build module and publish release runs-on: ubuntu-22.04 + timeout-minutes: 120 steps: - name: Check out repository @@ -112,11 +119,124 @@ jobs: echo "Latest tag: $latest_tag" echo "Next tag: $next_tag" - - name: Install build dependencies + - name: Normalize target architectures + id: targets + shell: bash + env: + INPUT_TARGET_ARCHES: ${{ github.event.inputs.target_arches }} run: | set -euo pipefail - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ + + raw_targets="${INPUT_TARGET_ARCHES:-$DEFAULT_TARGET_ARCHES}" + normalized_targets="" + docker_platforms="" + + add_target() { + local target_arch="$1" + local docker_platform="$2" + + case " $normalized_targets " in + *" $target_arch "*) + return + ;; + esac + + normalized_targets="${normalized_targets}${normalized_targets:+ }${target_arch}" + docker_platforms="${docker_platforms}${docker_platforms:+,}${docker_platform}" + } + + for raw_target in $raw_targets; do + case "$raw_target" in + linux-x86_64|x86_64|amd64|linux-amd64) + add_target "linux-x86_64" "linux/amd64" + ;; + linux-arm64|linux-aarch64|arm64|aarch64) + add_target "linux-arm64" "linux/arm64" + ;; + linux-armv7|linux-armhf|armv7|armhf) + add_target "linux-armv7" "linux/arm/v7" + ;; + *) + echo "Unsupported target_arches entry: $raw_target" >&2 + echo "Supported entries: linux-x86_64 linux-arm64 linux-armv7" >&2 + exit 1 + ;; + esac + done + + if [[ -z "$normalized_targets" ]]; then + echo "No release target architectures were selected" >&2 + exit 1 + fi + + { + printf 'target_arches=%s\n' "$normalized_targets" + printf 'docker_platforms=%s\n' "$docker_platforms" + } >> "$GITHUB_OUTPUT" + + echo "Release targets: $normalized_targets" + echo "Docker platforms: $docker_platforms" + + - name: Set up QEMU for ARM builds + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64,arm + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build release packages + shell: bash + env: + INPUT_NGINX_VERSIONS: ${{ github.event.inputs.nginx_versions }} + NORMALIZED_TARGET_ARCHES: ${{ steps.targets.outputs.target_arches }} + run: | + set -euo pipefail + + versions="${INPUT_NGINX_VERSIONS:-$DEFAULT_NGINX_VERSIONS}" + mkdir -p "$GITHUB_WORKSPACE/dist" "$GITHUB_WORKSPACE/.release-work" + + for target_arch in $NORMALIZED_TARGET_ARCHES; do + case "$target_arch" in + linux-x86_64) + docker_platform="linux/amd64" + ;; + linux-arm64) + docker_platform="linux/arm64" + ;; + linux-armv7) + docker_platform="linux/arm/v7" + ;; + *) + echo "Unexpected normalized target: $target_arch" >&2 + exit 1 + ;; + esac + + echo "::group::Build ${target_arch} release packages" + docker run --rm \ + --platform "$docker_platform" \ + -e BUILD_NGINX_VERSIONS="$versions" \ + -e DOCKER_PLATFORM="$docker_platform" \ + -e GITHUB_REF \ + -e GITHUB_SHA \ + -e LATEST_TAG \ + -e MODULE_NAME \ + -e NEXT_TAG \ + -e NEXT_VERSION \ + -e NGINX_CONFIGURE_ARGS \ + -e RELEASE_BUILD_IMAGE \ + -e TARGET_ARCH="$target_arch" \ + -v "$GITHUB_WORKSPACE:/work" \ + -w /work \ + "$RELEASE_BUILD_IMAGE" \ + bash -s <<'BUILD_SCRIPT' + set -euo pipefail + + export DEBIAN_FRONTEND=noninteractive + + apt-get update + apt-get install -y --no-install-recommends \ build-essential \ ca-certificates \ curl \ @@ -124,25 +244,25 @@ jobs: libpcre2-dev \ libssl-dev \ zlib1g-dev + rm -rf /var/lib/apt/lists/* - - name: Build release packages - shell: bash - env: - INPUT_NGINX_VERSIONS: ${{ github.event.inputs.nginx_versions }} - run: | - set -euo pipefail + target_workdir="/work/.release-work/${TARGET_ARCH}" + mkdir -p "$target_workdir" /work/dist - versions="${INPUT_NGINX_VERSIONS:-$DEFAULT_NGINX_VERSIONS}" - mkdir -p "$GITHUB_WORKSPACE/dist" "$GITHUB_WORKSPACE/.release-work" + for nginx_version in $BUILD_NGINX_VERSIONS; do + echo "::group::Nginx ${nginx_version} (${TARGET_ARCH})" - for nginx_version in $versions; do - workdir="$GITHUB_WORKSPACE/.release-work/nginx-$nginx_version" - archive="nginx-$nginx_version.tar.gz" + archive="nginx-${nginx_version}.tar.gz" + archive_path="${target_workdir}/${archive}" + workdir="${target_workdir}/nginx-${nginx_version}" - curl -fsSLo "$GITHUB_WORKSPACE/.release-work/$archive" \ - "https://nginx.org/download/$archive" - tar -xzf "$GITHUB_WORKSPACE/.release-work/$archive" \ - -C "$GITHUB_WORKSPACE/.release-work" + if [[ ! -f "$archive_path" ]]; then + curl -fsSLo "$archive_path" \ + "https://nginx.org/download/${archive}" + fi + + rm -rf "$workdir" + tar -xzf "$archive_path" -C "$target_workdir" cd "$workdir" ./configure \ @@ -160,22 +280,22 @@ jobs: --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ $NGINX_CONFIGURE_ARGS \ - --add-dynamic-module="$GITHUB_WORKSPACE" + --add-dynamic-module=/work make -j"$(nproc)" modules - package="${MODULE_NAME}-${NEXT_VERSION}-${NEXT_TAG}-nginx-${nginx_version}-linux-x86_64" - package_dir="$GITHUB_WORKSPACE/dist/$package" + package="${MODULE_NAME}-${NEXT_TAG}-nginx-${nginx_version}-${TARGET_ARCH}" + package_dir="/work/dist/$package" mkdir -p "$package_dir/modules" "$package_dir/examples" "$package_dir/docs" cp "objs/${MODULE_NAME}.so" "$package_dir/modules/${MODULE_NAME}.so" strip --strip-unneeded "$package_dir/modules/${MODULE_NAME}.so" || true - cp "$GITHUB_WORKSPACE/examples/nginx.conf" "$package_dir/examples/nginx.conf" - cp "$GITHUB_WORKSPACE/examples/monitoring-site.conf" "$package_dir/examples/monitoring-site.conf" - cp "$GITHUB_WORKSPACE/README.md" "$package_dir/README.md" - cp "$GITHUB_WORKSPACE/docs/API.md" "$package_dir/docs/API.md" - cp "$GITHUB_WORKSPACE/docs/CONFIGURATION.md" "$package_dir/docs/CONFIGURATION.md" - cp "$GITHUB_WORKSPACE/docs/PERFORMANCE.md" "$package_dir/docs/PERFORMANCE.md" + cp /work/examples/nginx.conf "$package_dir/examples/nginx.conf" + cp /work/examples/monitoring-site.conf "$package_dir/examples/monitoring-site.conf" + cp /work/README.md "$package_dir/README.md" + cp /work/docs/API.md "$package_dir/docs/API.md" + cp /work/docs/CONFIGURATION.md "$package_dir/docs/CONFIGURATION.md" + cp /work/docs/PERFORMANCE.md "$package_dir/docs/PERFORMANCE.md" { printf 'module=%s\n' "$MODULE_NAME" @@ -183,7 +303,10 @@ jobs: printf 'release_tag=%s\n' "$NEXT_TAG" printf 'previous_tag=%s\n' "$LATEST_TAG" printf 'nginx_version=%s\n' "$nginx_version" - printf 'target=linux-x86_64\n' + printf 'target=%s\n' "$TARGET_ARCH" + printf 'docker_platform=%s\n' "$DOCKER_PLATFORM" + printf 'build_image=%s\n' "$RELEASE_BUILD_IMAGE" + printf 'build_machine=%s\n' "$(uname -m)" printf 'runner=ubuntu-22.04\n' printf 'git_ref=%s\n' "$GITHUB_REF" printf 'git_sha=%s\n' "$GITHUB_SHA" @@ -194,7 +317,8 @@ jobs: { printf '# %s for Nginx %s\n\n' "$MODULE_NAME" "$nginx_version" printf 'Release: `%s`\n\n' "$NEXT_TAG" - printf 'This package contains a prebuilt Linux x86_64 dynamic module:\n\n' + printf 'Target: `%s` (`%s`)\n\n' "$TARGET_ARCH" "$DOCKER_PLATFORM" + printf 'This package contains a prebuilt Linux dynamic module:\n\n' printf '```text\n' printf 'modules/%s.so\n' "$MODULE_NAME" printf '```\n\n' @@ -202,8 +326,8 @@ jobs: printf '```nginx\n' printf 'load_module modules/%s.so;\n' "$MODULE_NAME" printf '```\n\n' - printf 'This binary is built with `--with-compat` against Nginx %s on Ubuntu 22.04. ' "$nginx_version" - printf 'For safest production use, run the same Nginx version and a compatible Linux/glibc environment. ' + printf 'This binary is built with `--with-compat` against Nginx %s on Ubuntu 22.04 for %s. ' "$nginx_version" "$TARGET_ARCH" + printf 'For safest production use, run the same Nginx version, CPU architecture, and a compatible Linux/glibc environment. ' printf 'If your Nginx package has a materially different module ABI, rebuild from source with this repository.\n' } > "$package_dir/INSTALL.md" @@ -213,9 +337,13 @@ jobs: file "modules/${MODULE_NAME}.so" > FILE.txt ) - tar -czf "$GITHUB_WORKSPACE/dist/$package.tar.gz" \ - -C "$GITHUB_WORKSPACE/dist" "$package" + tar -czf "/work/dist/$package.tar.gz" -C /work/dist "$package" rm -rf "$package_dir" + + echo "::endgroup::" + done + BUILD_SCRIPT + echo "::endgroup::" done ( @@ -226,14 +354,14 @@ jobs: { printf '# ngx_http_monitoring_module %s\n\n' "$NEXT_TAG" printf 'Previous tag: `%s`\n\n' "$LATEST_TAG" - printf 'Prebuilt Linux x86_64 dynamic module packages are attached.\n\n' - printf 'Each tarball is built against the Nginx version in its filename and includes:\n\n' + printf 'Prebuilt Linux dynamic module packages are attached for targets: `%s`.\n\n' "$NORMALIZED_TARGET_ARCHES" + printf 'Each tarball is built against the Nginx version and target architecture in its filename and includes:\n\n' printf -- '- `modules/%s.so`\n' "$MODULE_NAME" printf -- '- `INSTALL.md`\n' printf -- '- `METADATA.txt`\n' printf -- '- `SHA256SUMS`\n' printf -- '- example configuration and API docs\n\n' - printf 'Nginx dynamic modules are ABI-sensitive. Use the package matching your Nginx version and rebuild locally if your Nginx distribution uses incompatible build options.\n' + printf 'Nginx dynamic modules are ABI-sensitive. Use the package matching your Nginx version and CPU architecture, and rebuild locally if your Nginx distribution uses incompatible build options.\n' } > "$GITHUB_WORKSPACE/dist/RELEASE_NOTES.md" - name: Upload build artifacts @@ -264,21 +392,31 @@ jobs: --title "$NEXT_TAG" \ --notes-file dist/RELEASE_NOTES.md - - name: Build and push Docker image + - name: Compute Docker image name if: github.event.inputs.push_image == 'true' - env: - GH_TOKEN: ${{ github.token }} + id: image shell: bash run: | set -euo pipefail image_repo="$(echo "ghcr.io/${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]')" + printf 'repo=%s\n' "$image_repo" >> "$GITHUB_OUTPUT" - docker build \ - -f dockerized/Dockerfile \ - -t "$image_repo:$NEXT_TAG" \ - -t "$image_repo:latest" \ - . + - name: Log in to GHCR + if: github.event.inputs.push_image == 'true' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} - echo "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin - docker push "$image_repo:$NEXT_TAG" - docker push "$image_repo:latest" + - name: Build and push Docker image + if: github.event.inputs.push_image == 'true' + uses: docker/build-push-action@v6 + with: + context: . + file: dockerized/Dockerfile + platforms: ${{ steps.targets.outputs.docker_platforms }} + push: true + tags: | + ${{ steps.image.outputs.repo }}:${{ steps.version.outputs.next_tag }} + ${{ steps.image.outputs.repo }}:latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d84daa..642c343 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,7 @@ permissions: contents: read env: + TEST_BUILD_IMAGE: ubuntu:22.04 NGINX_CONFIGURE_ARGS: >- --with-compat --with-http_ssl_module @@ -23,9 +24,9 @@ env: jobs: build-and-configure: - name: Nginx ${{ matrix.nginx-version }} + name: Nginx ${{ matrix.nginx-version }} (${{ matrix.target.name }}) runs-on: ubuntu-22.04 - timeout-minutes: 30 + timeout-minutes: 90 strategy: fail-fast: false @@ -35,16 +36,48 @@ jobs: - "1.24.0" - "1.26.3" - "1.28.0" + - "1.30.0" + target: + - name: linux-x86_64 + platform: linux/amd64 + - name: linux-arm64 + platform: linux/arm64 + - name: linux-armv7 + platform: linux/arm/v7 steps: - name: Check out repository uses: actions/checkout@v4 - - name: Install build dependencies + - name: Set up QEMU for ARM tests + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64,arm + + - name: Build, configure, and test routes + shell: bash + env: + NGINX_VERSION: ${{ matrix.nginx-version }} + TARGET_ARCH: ${{ matrix.target.name }} + DOCKER_PLATFORM: ${{ matrix.target.platform }} run: | set -euo pipefail - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ + + docker run --rm \ + --platform "$DOCKER_PLATFORM" \ + -e NGINX_VERSION \ + -e TARGET_ARCH \ + -e NGINX_CONFIGURE_ARGS \ + -v "$GITHUB_WORKSPACE:/work" \ + -w /work \ + "$TEST_BUILD_IMAGE" \ + bash -s <<'CI_SCRIPT' + set -euo pipefail + + export DEBIAN_FRONTEND=noninteractive + + apt-get update + apt-get install -y --no-install-recommends \ build-essential \ ca-certificates \ curl \ @@ -53,26 +86,32 @@ jobs: libpcre2-dev \ libssl-dev \ zlib1g-dev + rm -rf /var/lib/apt/lists/* - - name: Download Nginx source - shell: bash - env: - NGINX_VERSION: ${{ matrix.nginx-version }} - run: | - set -euo pipefail - mkdir -p "$GITHUB_WORKSPACE/.ci-nginx" - curl -fsSLo "$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}.tar.gz" \ - "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" - tar -xzf "$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}.tar.gz" \ - -C "$GITHUB_WORKSPACE/.ci-nginx" + build_jobs="$(nproc)" + if [[ "$TARGET_ARCH" != "linux-x86_64" && "$build_jobs" -gt 2 ]]; then + build_jobs=2 + fi - - name: Configure Nginx with module - shell: bash - env: - NGINX_VERSION: ${{ matrix.nginx-version }} - run: | - set -euo pipefail - cd "$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}" + nginx_root="/work/.ci-nginx/${TARGET_ARCH}" + runtime_root="/work/.ci-runtime/${TARGET_ARCH}/nginx-${NGINX_VERSION}" + archive="nginx-${NGINX_VERSION}.tar.gz" + archive_path="${nginx_root}/${archive}" + nginx_src="${nginx_root}/nginx-${NGINX_VERSION}" + module_path="${nginx_src}/objs/ngx_http_monitoring_module.so" + config_path="${runtime_root}/nginx.conf" + base_url="http://127.0.0.1:18080" + + mkdir -p "$nginx_root" + if [[ ! -f "$archive_path" ]]; then + curl -fsSLo "$archive_path" \ + "https://nginx.org/download/${archive}" + fi + + rm -rf "$nginx_src" "$runtime_root" + tar -xzf "$archive_path" -C "$nginx_root" + + cd "$nginx_src" ./configure \ --prefix=/usr/local/nginx \ --sbin-path=/usr/local/sbin/nginx \ @@ -88,58 +127,39 @@ jobs: --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ $NGINX_CONFIGURE_ARGS \ - --add-dynamic-module="$GITHUB_WORKSPACE" + --add-dynamic-module=/work - - name: Build Nginx binary and dynamic module - shell: bash - env: - NGINX_VERSION: ${{ matrix.nginx-version }} - run: | - set -euo pipefail - cd "$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}" - make -j"$(nproc)" - make -j"$(nproc)" modules + make -j"$build_jobs" + make -j"$build_jobs" modules test -x objs/nginx - test -f objs/ngx_http_monitoring_module.so + test -f "$module_path" file objs/nginx - file objs/ngx_http_monitoring_module.so - - - name: Validate generated Nginx configuration - shell: bash - env: - NGINX_VERSION: ${{ matrix.nginx-version }} - run: | - set -euo pipefail - - nginx_src="$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}" - run_root="$GITHUB_WORKSPACE/.ci-runtime/nginx-${NGINX_VERSION}" - module_path="$nginx_src/objs/ngx_http_monitoring_module.so" - config_path="$run_root/nginx.conf" + file "$module_path" mkdir -p \ - "$run_root/logs" \ - "$run_root/temp/client_body" \ - "$run_root/temp/proxy" \ - "$run_root/temp/fastcgi" \ - "$run_root/temp/uwsgi" \ - "$run_root/temp/scgi" + "$runtime_root/logs" \ + "$runtime_root/temp/client_body" \ + "$runtime_root/temp/proxy" \ + "$runtime_root/temp/fastcgi" \ + "$runtime_root/temp/uwsgi" \ + "$runtime_root/temp/scgi" { printf 'load_module %s;\n\n' "$module_path" printf 'worker_processes 1;\n' - printf 'error_log %s/logs/error.log info;\n' "$run_root" - printf 'pid %s/logs/nginx.pid;\n\n' "$run_root" + printf 'error_log %s/logs/error.log info;\n' "$runtime_root" + printf 'pid %s/logs/nginx.pid;\n\n' "$runtime_root" printf 'events {\n' printf ' worker_connections 1024;\n' printf '}\n\n' printf 'http {\n' printf ' access_log off;\n' printf ' default_type application/octet-stream;\n' - printf ' client_body_temp_path %s/temp/client_body;\n' "$run_root" - printf ' proxy_temp_path %s/temp/proxy;\n' "$run_root" - printf ' fastcgi_temp_path %s/temp/fastcgi;\n' "$run_root" - printf ' uwsgi_temp_path %s/temp/uwsgi;\n' "$run_root" - printf ' scgi_temp_path %s/temp/scgi;\n\n' "$run_root" + printf ' client_body_temp_path %s/temp/client_body;\n' "$runtime_root" + printf ' proxy_temp_path %s/temp/proxy;\n' "$runtime_root" + printf ' fastcgi_temp_path %s/temp/fastcgi;\n' "$runtime_root" + printf ' uwsgi_temp_path %s/temp/uwsgi;\n' "$runtime_root" + printf ' scgi_temp_path %s/temp/scgi;\n\n' "$runtime_root" printf ' monitor_refresh_interval 1s;\n' printf ' monitor_history 1m;\n' printf ' monitor_resolution 1s;\n' @@ -169,22 +189,14 @@ jobs: printf '}\n' } > "$config_path" - "$nginx_src/objs/nginx" -t -p "$run_root" -c "$config_path" + "$nginx_src/objs/nginx" -t -p "$runtime_root" -c "$config_path" - - name: Run Nginx and test monitoring routes - shell: bash - env: - NGINX_VERSION: ${{ matrix.nginx-version }} - run: | - set -euo pipefail + cleanup() { + "$nginx_src/objs/nginx" -p "$runtime_root" -c "$config_path" -s quit || true + } + trap cleanup EXIT - nginx_src="$GITHUB_WORKSPACE/.ci-nginx/nginx-${NGINX_VERSION}" - run_root="$GITHUB_WORKSPACE/.ci-runtime/nginx-${NGINX_VERSION}" - config_path="$run_root/nginx.conf" - base_url="http://127.0.0.1:18080" - - "$nginx_src/objs/nginx" -p "$run_root" -c "$config_path" - trap '"$nginx_src/objs/nginx" -p "$run_root" -c "$config_path" -s quit || true' EXIT + "$nginx_src/objs/nginx" -p "$runtime_root" -c "$config_path" for attempt in $(seq 1 50); do if curl -fsS "$base_url/" >/dev/null; then @@ -242,13 +254,14 @@ jobs: sse_output="$(timeout 5s curl -fsS -N "$base_url/monitor/live" || true)" printf '%s' "$sse_output" | grep -q '^event: metrics' printf '%s' "$sse_output" | grep -q '^data: {' + CI_SCRIPT - name: Upload failed nginx logs if: failure() uses: actions/upload-artifact@v4 with: - name: nginx-${{ matrix.nginx-version }}-test-logs + name: nginx-${{ matrix.nginx-version }}-${{ matrix.target.name }}-test-logs path: | - .ci-runtime/nginx-${{ matrix.nginx-version }}/logs/*.log - .ci-runtime/nginx-${{ matrix.nginx-version }}/nginx.conf + .ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/logs/*.log + .ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/nginx.conf if-no-files-found: ignore diff --git a/README.md b/README.md index 00ce6f7..e85092e 100644 --- a/README.md +++ b/README.md @@ -57,11 +57,11 @@ A reusable Codex skill for clients and agents is available at `skills/ngx-http-m ## GitHub Releases -The repository includes a manual GitHub Actions workflow at `.github/workflows/release.yml` that computes the next `vMAJOR.MINOR.PATCH` tag, builds Linux x86_64 dynamic module tarballs, pushes the tag, and publishes the release. See `docs/RELEASES.md` for release asset format and compatibility notes. +The repository includes a manual GitHub Actions workflow at `.github/workflows/release.yml` that computes the next `vMAJOR.MINOR.PATCH` tag, builds Linux x86_64, ARM64, and ARMv7 dynamic module tarballs, pushes the tag, and publishes the release. See `docs/RELEASES.md` for release asset format and compatibility notes. ## CI Tests -`.github/workflows/test.yml` runs on pushes and pull requests. It builds Nginx and the dynamic module against common Nginx versions, runs `nginx -t`, starts the built server, and checks the dashboard, JSON API, health, Prometheus, and SSE routes. +`.github/workflows/test.yml` runs on pushes and pull requests. It builds Nginx and the dynamic module against common Nginx versions on x86_64, ARM64, and ARMv7, runs `nginx -t`, starts the built server, and checks the dashboard, JSON API, health, Prometheus, and SSE routes. ## Load The Module diff --git a/docs/RELEASES.md b/docs/RELEASES.md index 6533f4a..be1cd30 100644 --- a/docs/RELEASES.md +++ b/docs/RELEASES.md @@ -1,6 +1,6 @@ # Release Builds -The GitHub Actions workflow in `.github/workflows/release.yml` builds ready-to-use Linux x86_64 dynamic module packages. +The GitHub Actions workflow in `.github/workflows/release.yml` builds ready-to-use Linux dynamic module packages for x86_64 and ARM targets. ## Manual Release Only @@ -9,8 +9,9 @@ The workflow runs only through GitHub Actions `workflow_dispatch`. It does not r Open the workflow in GitHub Actions and choose: - `nginx_versions`: space-separated versions, for example `1.24.0 1.26.3 1.28.0` +- `target_arches`: space-separated targets, default `linux-x86_64 linux-arm64 linux-armv7` - `version_bump`: `patch`, `minor`, or `major` -- `push_image`: whether to push the Docker image to GHCR +- `push_image`: whether to push the multi-platform Docker image to GHCR The workflow fetches existing `vMAJOR.MINOR.PATCH` tags, computes the next semantic version, creates an annotated tag, pushes it, and publishes the GitHub release. @@ -27,14 +28,27 @@ no existing tag + patch = v0.0.1 By default, the workflow builds packages for: +- Nginx 1.22.1 - Nginx 1.24.0 - Nginx 1.26.3 - Nginx 1.28.0 +- Nginx 1.30.0 + +## Built CPU Targets + +By default, the workflow builds module packages for: + +- `linux-x86_64` +- `linux-arm64` +- `linux-armv7` + +Aliases such as `amd64`, `arm64`, `aarch64`, `armv7`, and `armhf` are normalized by the workflow. Each release asset is named like: ```text -ngx_http_monitoring_module-1.0.0-v1.0.0-nginx-1.28.0-linux-x86_64.tar.gz +ngx_http_monitoring_module-v1.0.0-nginx-1.28.0-linux-x86_64.tar.gz +ngx_http_monitoring_module-v1.0.0-nginx-1.28.0-linux-arm64.tar.gz ``` Each package contains: @@ -55,6 +69,8 @@ ghcr.io//: ghcr.io//:latest ``` +The image is built with Docker Buildx for the same normalized target platforms requested by `target_arches`. + ## Compatibility Warning -Nginx dynamic modules are ABI-sensitive. The release packages are built with `--with-compat` on Ubuntu 22.04 against the Nginx version in the filename. Use the matching Nginx version and a compatible Linux/glibc runtime. Rebuild locally when using a vendor Nginx package with materially different module ABI or hardening options. +Nginx dynamic modules are ABI-sensitive. The release packages are built with `--with-compat` on Ubuntu 22.04 against the Nginx version and CPU architecture in the filename. Use the matching Nginx version, CPU architecture, and a compatible Linux/glibc runtime. Rebuild locally when using a vendor Nginx package with materially different module ABI or hardening options.