chore: refactor release workflow for modular distro and upstream builds
This commit is contained in:
281
.github/workflows/release.yml
vendored
281
.github/workflows/release.yml
vendored
@@ -3,8 +3,12 @@ name: Build and Release Module
|
|||||||
"on":
|
"on":
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
nginx_versions:
|
distro_targets:
|
||||||
description: "Space-separated Nginx versions to build against"
|
description: "Space-separated distro images to build in, for example: ubuntu:24.04 debian:12 debian:13"
|
||||||
|
required: true
|
||||||
|
default: "ubuntu:24.04 debian:12 debian:13"
|
||||||
|
upstream_nginx_versions:
|
||||||
|
description: "Space-separated upstream nginx.org versions for generic tarball builds"
|
||||||
required: true
|
required: true
|
||||||
default: "1.22.1 1.24.0 1.26.3 1.28.0 1.30.0"
|
default: "1.22.1 1.24.0 1.26.3 1.28.0 1.30.0"
|
||||||
target_arches:
|
target_arches:
|
||||||
@@ -21,7 +25,7 @@ name: Build and Release Module
|
|||||||
- minor
|
- minor
|
||||||
- major
|
- major
|
||||||
push_image:
|
push_image:
|
||||||
description: "Push multi-platform Docker image to GHCR using the new tag"
|
description: "Push multi-platform demo Docker image to GHCR using the new tag"
|
||||||
type: boolean
|
type: boolean
|
||||||
required: true
|
required: true
|
||||||
default: true
|
default: true
|
||||||
@@ -31,9 +35,11 @@ permissions:
|
|||||||
packages: write
|
packages: write
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEFAULT_NGINX_VERSIONS: "1.22.1 1.24.0 1.26.3 1.28.0 1.30.0"
|
DEFAULT_DISTRO_TARGETS: "ubuntu:24.04 debian:12 debian:13"
|
||||||
|
DEFAULT_UPSTREAM_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"
|
DEFAULT_TARGET_ARCHES: "linux-x86_64 linux-arm64 linux-armv7"
|
||||||
MODULE_NAME: ngx_http_monitoring_module
|
MODULE_NAME: ngx_http_monitoring_module
|
||||||
|
DEB_PACKAGE_NAME: libnginx-mod-http-monitoring
|
||||||
RELEASE_BUILD_IMAGE: ubuntu:18.04
|
RELEASE_BUILD_IMAGE: ubuntu:18.04
|
||||||
RELEASE_LIBC_BASELINE: ubuntu-bionic-glibc-2.27
|
RELEASE_LIBC_BASELINE: ubuntu-bionic-glibc-2.27
|
||||||
NGINX_CONFIGURE_ARGS: >-
|
NGINX_CONFIGURE_ARGS: >-
|
||||||
@@ -46,9 +52,9 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Build module and publish release
|
name: Build distro modules and publish release
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 120
|
timeout-minutes: 240
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
@@ -186,17 +192,75 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build release packages
|
- name: Build distro release packages
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
INPUT_NGINX_VERSIONS: ${{ github.event.inputs.nginx_versions }}
|
INPUT_DISTRO_TARGETS: ${{ github.event.inputs.distro_targets }}
|
||||||
NORMALIZED_TARGET_ARCHES: ${{ steps.targets.outputs.target_arches }}
|
NORMALIZED_TARGET_ARCHES: ${{ steps.targets.outputs.target_arches }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
versions="${INPUT_NGINX_VERSIONS:-$DEFAULT_NGINX_VERSIONS}"
|
distro_targets="${INPUT_DISTRO_TARGETS:-$DEFAULT_DISTRO_TARGETS}"
|
||||||
mkdir -p "$GITHUB_WORKSPACE/dist" "$GITHUB_WORKSPACE/.release-work"
|
mkdir -p "$GITHUB_WORKSPACE/dist" "$GITHUB_WORKSPACE/.release-work"
|
||||||
|
|
||||||
|
if [[ -z "$distro_targets" ]]; then
|
||||||
|
echo "No distro_targets were selected" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for distro_image in $distro_targets; do
|
||||||
|
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 ${distro_image} ${target_arch}"
|
||||||
|
docker run --rm -i \
|
||||||
|
--platform "$docker_platform" \
|
||||||
|
-e DEB_PACKAGE_NAME \
|
||||||
|
-e DISTRO_IMAGE="$distro_image" \
|
||||||
|
-e DOCKER_PLATFORM="$docker_platform" \
|
||||||
|
-e GITHUB_REF \
|
||||||
|
-e GITHUB_SHA \
|
||||||
|
-e LATEST_TAG \
|
||||||
|
-e MODULE_NAME \
|
||||||
|
-e NEXT_TAG \
|
||||||
|
-e NEXT_VERSION \
|
||||||
|
-e TARGET_ARCH="$target_arch" \
|
||||||
|
-v "$GITHUB_WORKSPACE:/work" \
|
||||||
|
-w /work \
|
||||||
|
"$distro_image" \
|
||||||
|
bash /work/scripts/build-distro-release.sh
|
||||||
|
echo "::endgroup::"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Build upstream nginx.org release tarballs
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
INPUT_UPSTREAM_NGINX_VERSIONS: ${{ github.event.inputs.upstream_nginx_versions }}
|
||||||
|
NORMALIZED_TARGET_ARCHES: ${{ steps.targets.outputs.target_arches }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
upstream_versions="${INPUT_UPSTREAM_NGINX_VERSIONS:-$DEFAULT_UPSTREAM_NGINX_VERSIONS}"
|
||||||
|
if [[ -z "$upstream_versions" ]]; then
|
||||||
|
echo "No upstream_nginx_versions were selected" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
for target_arch in $NORMALIZED_TARGET_ARCHES; do
|
for target_arch in $NORMALIZED_TARGET_ARCHES; do
|
||||||
case "$target_arch" in
|
case "$target_arch" in
|
||||||
linux-x86_64)
|
linux-x86_64)
|
||||||
@@ -214,10 +278,11 @@ jobs:
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "::group::Build ${target_arch} release packages"
|
echo "::group::Build nginx.org ${target_arch} tarballs"
|
||||||
docker run --rm -i \
|
docker run --rm -i \
|
||||||
--platform "$docker_platform" \
|
--platform "$docker_platform" \
|
||||||
-e BUILD_NGINX_VERSIONS="$versions" \
|
-e BUILD_NGINX_VERSIONS="$upstream_versions" \
|
||||||
|
-e DIST_DIR=/work/dist \
|
||||||
-e DOCKER_PLATFORM="$docker_platform" \
|
-e DOCKER_PLATFORM="$docker_platform" \
|
||||||
-e GITHUB_REF \
|
-e GITHUB_REF \
|
||||||
-e GITHUB_SHA \
|
-e GITHUB_SHA \
|
||||||
@@ -232,149 +297,76 @@ jobs:
|
|||||||
-v "$GITHUB_WORKSPACE:/work" \
|
-v "$GITHUB_WORKSPACE:/work" \
|
||||||
-w /work \
|
-w /work \
|
||||||
"$RELEASE_BUILD_IMAGE" \
|
"$RELEASE_BUILD_IMAGE" \
|
||||||
bash -s <<'BUILD_SCRIPT'
|
bash /work/scripts/build-upstream-release.sh
|
||||||
|
echo "::endgroup::"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Generate release manifests and notes
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
cd "$GITHUB_WORKSPACE/dist"
|
||||||
|
|
||||||
apt-get update
|
shopt -s nullglob
|
||||||
apt-get install -y --no-install-recommends \
|
compatibility_files=( *.compatibility.json )
|
||||||
build-essential \
|
if [[ "${#compatibility_files[@]}" -eq 0 ]]; then
|
||||||
ca-certificates \
|
echo "No compatibility metadata files were generated" >&2
|
||||||
curl \
|
exit 1
|
||||||
file \
|
|
||||||
libpcre2-dev \
|
|
||||||
libssl-dev \
|
|
||||||
zlib1g-dev
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
target_workdir="/work/.release-work/${TARGET_ARCH}"
|
|
||||||
mkdir -p "$target_workdir" /work/dist
|
|
||||||
|
|
||||||
for nginx_version in $BUILD_NGINX_VERSIONS; do
|
|
||||||
echo "::group::Nginx ${nginx_version} (${TARGET_ARCH})"
|
|
||||||
|
|
||||||
archive="nginx-${nginx_version}.tar.gz"
|
|
||||||
archive_path="${target_workdir}/${archive}"
|
|
||||||
workdir="${target_workdir}/nginx-${nginx_version}"
|
|
||||||
|
|
||||||
if [[ ! -f "$archive_path" ]]; then
|
|
||||||
curl -fsSLo "$archive_path" \
|
|
||||||
"https://nginx.org/download/${archive}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$workdir"
|
jq -s \
|
||||||
tar -xzf "$archive_path" -C "$target_workdir"
|
--arg releaseTag "$NEXT_TAG" \
|
||||||
|
--arg generatedAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
'{
|
||||||
|
schema: 1,
|
||||||
|
release_tag: $releaseTag,
|
||||||
|
generated_at: $generatedAt,
|
||||||
|
artifacts: .
|
||||||
|
}' \
|
||||||
|
"${compatibility_files[@]}" > COMPATIBILITY-MATRIX.json
|
||||||
|
|
||||||
cd "$workdir"
|
find . -maxdepth 1 -type f \
|
||||||
./configure \
|
\( -name '*.deb' -o -name '*.tar.gz' -o -name '*.compatibility.json' -o -name 'COMPATIBILITY-MATRIX.json' \) \
|
||||||
--prefix=/usr/local/nginx \
|
-print0 \
|
||||||
--sbin-path=/usr/local/sbin/nginx \
|
| sort -z \
|
||||||
--modules-path=/usr/local/nginx/modules \
|
| xargs -0 sha256sum > SHA256SUMS.txt
|
||||||
--conf-path=/etc/nginx/nginx.conf \
|
|
||||||
--error-log-path=/var/log/nginx/error.log \
|
|
||||||
--http-log-path=/var/log/nginx/access.log \
|
|
||||||
--pid-path=/var/run/nginx.pid \
|
|
||||||
--lock-path=/var/run/nginx.lock \
|
|
||||||
--http-client-body-temp-path=/var/cache/nginx/client_temp \
|
|
||||||
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
|
|
||||||
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
|
|
||||||
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
|
|
||||||
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
|
|
||||||
$NGINX_CONFIGURE_ARGS \
|
|
||||||
--add-dynamic-module=/work
|
|
||||||
|
|
||||||
make -j"$(nproc)" modules
|
|
||||||
|
|
||||||
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 /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"
|
printf '# %s %s\n\n' "$MODULE_NAME" "$NEXT_TAG"
|
||||||
printf 'module_version=%s\n' "$NEXT_VERSION"
|
|
||||||
printf 'release_tag=%s\n' "$NEXT_TAG"
|
|
||||||
printf 'previous_tag=%s\n' "$LATEST_TAG"
|
|
||||||
printf 'nginx_version=%s\n' "$nginx_version"
|
|
||||||
printf 'target=%s\n' "$TARGET_ARCH"
|
|
||||||
printf 'docker_platform=%s\n' "$DOCKER_PLATFORM"
|
|
||||||
printf 'build_image=%s\n' "$RELEASE_BUILD_IMAGE"
|
|
||||||
printf 'libc_baseline=%s\n' "$RELEASE_LIBC_BASELINE"
|
|
||||||
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"
|
|
||||||
printf 'configure_args=%s\n' "$NGINX_CONFIGURE_ARGS"
|
|
||||||
printf 'built_at=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
||||||
} > "$package_dir/METADATA.txt"
|
|
||||||
|
|
||||||
{
|
|
||||||
printf '# %s for Nginx %s\n\n' "$MODULE_NAME" "$nginx_version"
|
|
||||||
printf 'Release: `%s`\n\n' "$NEXT_TAG"
|
|
||||||
printf 'Target: `%s` (`%s`)\n\n' "$TARGET_ARCH" "$DOCKER_PLATFORM"
|
|
||||||
printf 'Libc baseline: `%s`\n\n' "$RELEASE_LIBC_BASELINE"
|
|
||||||
printf 'This package contains a prebuilt Linux dynamic module:\n\n'
|
|
||||||
printf '```text\n'
|
|
||||||
printf 'modules/%s.so\n' "$MODULE_NAME"
|
|
||||||
printf '```\n\n'
|
|
||||||
printf 'Copy it into your Nginx modules directory and add this near the top of `nginx.conf`:\n\n'
|
|
||||||
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 Bionic 18.04 for %s. ' "$nginx_version" "$TARGET_ARCH"
|
|
||||||
printf 'For safest production use, run the same Nginx version, CPU architecture, and a Linux/glibc environment compatible with `%s`. ' "$RELEASE_LIBC_BASELINE"
|
|
||||||
printf 'If your Nginx package has a materially different module ABI, rebuild from source with this repository.\n'
|
|
||||||
} > "$package_dir/INSTALL.md"
|
|
||||||
|
|
||||||
(
|
|
||||||
cd "$package_dir"
|
|
||||||
sha256sum "modules/${MODULE_NAME}.so" > SHA256SUMS
|
|
||||||
file "modules/${MODULE_NAME}.so" > FILE.txt
|
|
||||||
)
|
|
||||||
|
|
||||||
tar -czf "/work/dist/$package.tar.gz" -C /work/dist "$package"
|
|
||||||
rm -rf "$package_dir"
|
|
||||||
|
|
||||||
echo "::endgroup::"
|
|
||||||
done
|
|
||||||
BUILD_SCRIPT
|
|
||||||
echo "::endgroup::"
|
|
||||||
done
|
|
||||||
|
|
||||||
(
|
|
||||||
cd "$GITHUB_WORKSPACE/dist"
|
|
||||||
sha256sum *.tar.gz > SHA256SUMS.txt
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
printf '# ngx_http_monitoring_module %s\n\n' "$NEXT_TAG"
|
|
||||||
printf 'Previous tag: `%s`\n\n' "$LATEST_TAG"
|
printf 'Previous tag: `%s`\n\n' "$LATEST_TAG"
|
||||||
printf 'Libc baseline: `%s`\n\n' "$RELEASE_LIBC_BASELINE"
|
printf 'This release includes two artifact tiers:\n\n'
|
||||||
printf 'Prebuilt Linux dynamic module packages are attached for targets: `%s`.\n\n' "$NORMALIZED_TARGET_ARCHES"
|
printf -- '- distro `.deb` packages built from Ubuntu/Debian Nginx source packages and pinned to the matching packaged Nginx revision\n'
|
||||||
printf 'Each tarball is built against the Nginx version and target architecture in its filename and includes:\n\n'
|
printf -- '- nginx.org upstream-version tarballs for users who build or run Nginx from upstream source versions\n\n'
|
||||||
printf -- '- `modules/%s.so`\n' "$MODULE_NAME"
|
printf 'Recommended production artifacts are the `.deb` packages. They depend on the exact distro `nginx-abi-*` virtual package when the distribution exposes one and on the exact Nginx binary package version used for the build. That strict pin prevents Nginx package revisions from silently reusing an unrebuilt module.\n\n'
|
||||||
printf -- '- `INSTALL.md`\n'
|
printf 'The nginx.org `.tar.gz` packages preserve upstream-version coverage but are not a safe substitute for distro packages on Ubuntu/Debian packaged Nginx.\n\n'
|
||||||
printf -- '- `METADATA.txt`\n'
|
printf '## Distro Package Matrix\n\n'
|
||||||
printf -- '- `SHA256SUMS`\n'
|
jq -r '
|
||||||
printf -- '- example configuration and API docs\n\n'
|
.artifacts[]
|
||||||
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'
|
| select(.build.method == "distro-source-package")
|
||||||
} > "$GITHUB_WORKSPACE/dist/RELEASE_NOTES.md"
|
| "- `\(.artifacts.deb_file)`: \(.target.os_id) \(.target.os_version) \(.target.architecture), "
|
||||||
|
+ "\(.nginx.binary_package) \(.nginx.binary_version), source \(.nginx.source_package) \(.nginx.source_version), "
|
||||||
|
+ "ABI `\(if .nginx.abi == "" then "package-version-pinned" else .nginx.abi end)`"
|
||||||
|
' COMPATIBILITY-MATRIX.json
|
||||||
|
printf '\n## nginx.org Tarballs\n\n'
|
||||||
|
jq -r '
|
||||||
|
.artifacts[]
|
||||||
|
| select(.build.method == "upstream-nginxorg-source")
|
||||||
|
| "- `\(.artifacts.tarball_file)`: nginx.org \(.nginx.source_version), \(.target.architecture), baseline `\(.target.libc_baseline)`"
|
||||||
|
' COMPATIBILITY-MATRIX.json
|
||||||
|
printf '\n## Validation\n\n'
|
||||||
|
printf 'Distro `.deb` artifacts are installed into their target distro containers and validated with packaged `nginx -t` plus live endpoint checks. nginx.org tarballs are validated with the Nginx binary built from the same upstream source during the tarball build.\n'
|
||||||
|
} > RELEASE_NOTES.md
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ngx-http-monitoring-module-${{ steps.version.outputs.next_tag }}-release-assets
|
name: ngx-http-monitoring-module-${{ steps.version.outputs.next_tag }}-release-assets
|
||||||
path: |
|
path: |
|
||||||
|
dist/*.deb
|
||||||
dist/*.tar.gz
|
dist/*.tar.gz
|
||||||
|
dist/*.compatibility.json
|
||||||
|
dist/COMPATIBILITY-MATRIX.json
|
||||||
dist/SHA256SUMS.txt
|
dist/SHA256SUMS.txt
|
||||||
dist/RELEASE_NOTES.md
|
dist/RELEASE_NOTES.md
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
@@ -393,7 +385,12 @@ jobs:
|
|||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
gh release create "$NEXT_TAG" dist/*.tar.gz dist/SHA256SUMS.txt \
|
gh release create "$NEXT_TAG" \
|
||||||
|
dist/*.deb \
|
||||||
|
dist/*.tar.gz \
|
||||||
|
dist/*.compatibility.json \
|
||||||
|
dist/COMPATIBILITY-MATRIX.json \
|
||||||
|
dist/SHA256SUMS.txt \
|
||||||
--title "$NEXT_TAG" \
|
--title "$NEXT_TAG" \
|
||||||
--notes-file dist/RELEASE_NOTES.md
|
--notes-file dist/RELEASE_NOTES.md
|
||||||
|
|
||||||
@@ -414,7 +411,7 @@ jobs:
|
|||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ github.token }}
|
password: ${{ github.token }}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push demo Docker image
|
||||||
if: github.event.inputs.push_image == 'true'
|
if: github.event.inputs.push_image == 'true'
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -423,8 +420,8 @@ jobs:
|
|||||||
platforms: ${{ steps.targets.outputs.docker_platforms }}
|
platforms: ${{ steps.targets.outputs.docker_platforms }}
|
||||||
push: true
|
push: true
|
||||||
build-args: |
|
build-args: |
|
||||||
BASE_IMAGE=ubuntu:18.04
|
BASE_IMAGE=debian:bookworm-slim
|
||||||
OPENSSL_RUNTIME_PACKAGE=libssl1.1
|
OPENSSL_RUNTIME_PACKAGE=libssl3
|
||||||
tags: |
|
tags: |
|
||||||
${{ steps.image.outputs.repo }}:${{ steps.version.outputs.next_tag }}
|
${{ steps.image.outputs.repo }}:${{ steps.version.outputs.next_tag }}
|
||||||
${{ steps.image.outputs.repo }}:latest
|
${{ steps.image.outputs.repo }}:latest
|
||||||
|
|||||||
63
.github/workflows/test.yml
vendored
63
.github/workflows/test.yml
vendored
@@ -265,3 +265,66 @@ jobs:
|
|||||||
.ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/logs/*.log
|
.ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/logs/*.log
|
||||||
.ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/nginx.conf
|
.ci-runtime/${{ matrix.target.name }}/nginx-${{ matrix.nginx-version }}/nginx.conf
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
|
distro-package-compat:
|
||||||
|
name: Distro package compatibility (${{ matrix.distro-image }})
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 90
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
distro-image:
|
||||||
|
- ubuntu:24.04
|
||||||
|
- debian:12
|
||||||
|
- debian:13
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build package and validate against distro nginx
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
DEB_PACKAGE_NAME: libnginx-mod-http-monitoring
|
||||||
|
DISTRO_IMAGE: ${{ matrix.distro-image }}
|
||||||
|
DOCKER_PLATFORM: linux/amd64
|
||||||
|
LATEST_TAG: none
|
||||||
|
MODULE_NAME: ngx_http_monitoring_module
|
||||||
|
NEXT_TAG: ci
|
||||||
|
NEXT_VERSION: 0.0.0
|
||||||
|
TARGET_ARCH: linux-x86_64
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p "$GITHUB_WORKSPACE/.ci-distro-dist" "$GITHUB_WORKSPACE/.ci-distro-work"
|
||||||
|
|
||||||
|
docker run --rm -i \
|
||||||
|
--platform "$DOCKER_PLATFORM" \
|
||||||
|
-e DEB_PACKAGE_NAME \
|
||||||
|
-e DISTRO_IMAGE \
|
||||||
|
-e DIST_DIR=/work/.ci-distro-dist \
|
||||||
|
-e DOCKER_PLATFORM \
|
||||||
|
-e GITHUB_REF \
|
||||||
|
-e GITHUB_SHA \
|
||||||
|
-e LATEST_TAG \
|
||||||
|
-e MODULE_NAME \
|
||||||
|
-e NEXT_TAG \
|
||||||
|
-e NEXT_VERSION \
|
||||||
|
-e TARGET_ARCH \
|
||||||
|
-e WORK_ROOT=/work/.ci-distro-work \
|
||||||
|
-v "$GITHUB_WORKSPACE:/work" \
|
||||||
|
-w /work \
|
||||||
|
"$DISTRO_IMAGE" \
|
||||||
|
bash /work/scripts/build-distro-release.sh
|
||||||
|
|
||||||
|
- name: Upload distro compatibility artifacts
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: distro-package-compat-${{ strategy.job-index }}
|
||||||
|
path: |
|
||||||
|
.ci-distro-dist/*.deb
|
||||||
|
.ci-distro-dist/*.tar.gz
|
||||||
|
.ci-distro-dist/*.compatibility.json
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|||||||
@@ -59,11 +59,11 @@ A reusable Codex skill for clients and agents is available at `skills/ngx-http-m
|
|||||||
|
|
||||||
## GitHub Releases
|
## 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, ARM64, and ARMv7 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 Ubuntu/Debian distro-specific module packages, keeps generic nginx.org source-version tarballs, validates the artifacts, pushes the tag, and publishes the release. Production installs on Ubuntu/Debian should prefer the generated `.deb` packages because they depend on the matching distro Nginx ABI and exact Nginx binary package revision. See `docs/RELEASES.md` for release asset format and compatibility notes.
|
||||||
|
|
||||||
## CI Tests
|
## CI Tests
|
||||||
|
|
||||||
`.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.
|
`.github/workflows/test.yml` runs on pushes and pull requests. It builds Nginx and the dynamic module against common upstream Nginx versions as a broad source sanity check, and also builds distro packages against Ubuntu/Debian packaged Nginx on amd64. Both paths run `nginx -t`, start Nginx, and check the dashboard, JSON API, health, Prometheus, and SSE routes.
|
||||||
|
|
||||||
## Load The Module
|
## Load The Module
|
||||||
|
|
||||||
|
|||||||
186
docs/RELEASES.md
186
docs/RELEASES.md
@@ -1,83 +1,165 @@
|
|||||||
# Release Builds
|
# Release Builds
|
||||||
|
|
||||||
The GitHub Actions workflow in `.github/workflows/release.yml` builds ready-to-use Linux dynamic module packages for x86_64 and ARM targets. Release binaries are built in Ubuntu Bionic 18.04 containers, giving the module artifacts a `ubuntu-bionic-glibc-2.27` libc baseline.
|
The release workflow in `.github/workflows/release.yml` builds two artifact
|
||||||
|
tiers:
|
||||||
|
|
||||||
## Manual Release Only
|
- production-oriented `.deb` packages against Ubuntu and Debian Nginx source
|
||||||
|
packages
|
||||||
|
- generic `.tar.gz` packages against upstream `nginx.org` source versions
|
||||||
|
|
||||||
The workflow runs only through GitHub Actions `workflow_dispatch`. It does not run on pushes, pull requests, or tag pushes.
|
## Why Distro Builds
|
||||||
|
|
||||||
Open the workflow in GitHub Actions and choose:
|
Nginx dynamic modules are ABI-sensitive. `--with-compat` relaxes some module
|
||||||
|
signature checks, but it does not make a module independent from the Nginx
|
||||||
|
source package, distro patchset, compiler flags, configure arguments, or module
|
||||||
|
ABI selected by a Debian or Ubuntu package maintainer.
|
||||||
|
|
||||||
- `nginx_versions`: space-separated versions, for example `1.24.0 1.26.3 1.28.0`
|
An upstream `nginx-1.24.0` build can load into an Ubuntu `nginx` package and
|
||||||
- `target_arches`: space-separated targets, default `linux-x86_64 linux-arm64 linux-armv7`
|
still behave incorrectly at runtime after a package rebuild such as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1.24.0-2ubuntu7.9 -> 1.24.0-2ubuntu7.10
|
||||||
|
```
|
||||||
|
|
||||||
|
The safer production rule is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
build from the distro source package that produced the nginx binary you run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Release
|
||||||
|
|
||||||
|
The workflow runs through GitHub Actions `workflow_dispatch`.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
|
||||||
|
- `distro_targets`: space-separated container images, default
|
||||||
|
`ubuntu:24.04 debian:12 debian:13`
|
||||||
|
- `upstream_nginx_versions`: space-separated upstream source versions, default
|
||||||
|
`1.22.1 1.24.0 1.26.3 1.28.0 1.30.0`
|
||||||
|
- `target_arches`: `linux-x86_64`, `linux-arm64`, and `linux-armv7`
|
||||||
- `version_bump`: `patch`, `minor`, or `major`
|
- `version_bump`: `patch`, `minor`, or `major`
|
||||||
- `push_image`: whether to push the multi-platform Docker image to GHCR
|
- `push_image`: push the demo 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.
|
The workflow fetches existing `vMAJOR.MINOR.PATCH` tags, computes the next tag,
|
||||||
|
builds all release artifacts, creates an annotated tag, pushes it, and publishes
|
||||||
|
the GitHub release.
|
||||||
|
|
||||||
Examples:
|
## Distro Build Strategy
|
||||||
|
|
||||||
|
For every distro and architecture, the workflow:
|
||||||
|
|
||||||
|
1. Starts the target distro container for the target CPU platform.
|
||||||
|
2. Enables `deb-src` repositories.
|
||||||
|
3. Installs the distro `nginx` package.
|
||||||
|
4. Downloads the exact matching `apt source nginx` package version.
|
||||||
|
5. Installs the Nginx source package build dependencies.
|
||||||
|
6. Replays the packaged `nginx -V` configure arguments, rewriting distro module
|
||||||
|
source paths into the downloaded source tree when needed.
|
||||||
|
7. Adds this repository as a dynamic module and builds with the distro Nginx
|
||||||
|
source package.
|
||||||
|
8. Builds a `.deb` package and a manual `.tar.gz` package.
|
||||||
|
9. Installs the `.deb` package in the same container.
|
||||||
|
10. Validates the installed module with packaged `nginx -t` and live endpoint
|
||||||
|
checks for `/monitor`, `/monitor/api`, `/monitor/health`,
|
||||||
|
`/monitor/metrics`, and `/monitor/live`.
|
||||||
|
|
||||||
|
## nginx.org Build Strategy
|
||||||
|
|
||||||
|
For every requested upstream Nginx version and architecture, the workflow:
|
||||||
|
|
||||||
|
1. Starts the baseline `ubuntu:18.04` build container for the target CPU
|
||||||
|
platform.
|
||||||
|
2. Downloads the requested `https://nginx.org/download/nginx-<version>.tar.gz`
|
||||||
|
source archive.
|
||||||
|
3. Configures Nginx with the repository's compatibility build flags and this
|
||||||
|
module as a dynamic module.
|
||||||
|
4. Builds the Nginx binary and module.
|
||||||
|
5. Validates the module with the just-built Nginx binary and live endpoint
|
||||||
|
checks for `/monitor`, `/monitor/api`, `/monitor/health`,
|
||||||
|
`/monitor/metrics`, and `/monitor/live`.
|
||||||
|
6. Publishes a tarball plus sidecar compatibility metadata.
|
||||||
|
|
||||||
|
These artifacts preserve upstream version coverage for users who run Nginx
|
||||||
|
built from nginx.org source. They are not the recommended artifact for Ubuntu or
|
||||||
|
Debian packaged Nginx.
|
||||||
|
|
||||||
|
## Release Assets
|
||||||
|
|
||||||
|
Recommended production asset:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
latest v1.2.3 + patch = v1.2.4
|
libnginx-mod-http-monitoring_<module-version>-1+<distro>.nginx<source-version>_<deb-arch>.deb
|
||||||
latest v1.2.3 + minor = v1.3.0
|
|
||||||
latest v1.2.3 + major = v2.0.0
|
|
||||||
no existing tag + patch = v0.0.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Built Nginx Versions
|
Manual fallback asset:
|
||||||
|
|
||||||
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
|
```text
|
||||||
ngx_http_monitoring_module-v1.0.0-nginx-1.28.0-linux-x86_64.tar.gz
|
ngx_http_monitoring_module-<tag>-<distro>-nginx-<source-version>-<deb-arch>.tar.gz
|
||||||
ngx_http_monitoring_module-v1.0.0-nginx-1.28.0-linux-arm64.tar.gz
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Each package contains:
|
Upstream nginx.org source asset:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ngx_http_monitoring_module-<tag>-nginxorg-<nginx-version>-<target-arch>.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
Metadata assets:
|
||||||
|
|
||||||
|
- `*.compatibility.json`: compatibility metadata for one artifact target
|
||||||
|
- `COMPATIBILITY-MATRIX.json`: combined release compatibility matrix
|
||||||
|
- `SHA256SUMS.txt`: checksums for release assets
|
||||||
|
|
||||||
|
Each tarball contains:
|
||||||
|
|
||||||
- `modules/ngx_http_monitoring_module.so`
|
- `modules/ngx_http_monitoring_module.so`
|
||||||
- `INSTALL.md`
|
- `INSTALL.md`
|
||||||
|
- `COMPATIBILITY.json`
|
||||||
- `METADATA.txt`
|
- `METADATA.txt`
|
||||||
|
- `NGINX-V.txt`
|
||||||
- `SHA256SUMS`
|
- `SHA256SUMS`
|
||||||
- example config
|
- example config and docs
|
||||||
- API/config/performance docs
|
|
||||||
|
## ABI Guard
|
||||||
|
|
||||||
|
The `.deb` package depends on the distro `nginx-abi-*` virtual package when the
|
||||||
|
distribution exposes it and always pins the exact Nginx binary package version
|
||||||
|
used for the build. If a later Nginx package update changes either the ABI or
|
||||||
|
the package revision, apt cannot silently keep the old module installed against
|
||||||
|
the new Nginx binary.
|
||||||
|
|
||||||
|
This is stricter than ABI-only packaging and can require rebuilding the module
|
||||||
|
for routine distro Nginx updates. That is intentional: it favors explicit
|
||||||
|
release artifacts over a module that loads and then fails at runtime.
|
||||||
|
|
||||||
|
## Tarball Warning
|
||||||
|
|
||||||
|
Tarballs are useful for inspection, non-dpkg deployments, upstream nginx.org
|
||||||
|
source builds, and emergency manual installs. They do not give apt a dependency
|
||||||
|
edge, so they cannot protect a host from an ABI-changing Nginx update.
|
||||||
|
|
||||||
|
Use a distro tarball only when all fields in `COMPATIBILITY.json` match the
|
||||||
|
target host:
|
||||||
|
|
||||||
|
- OS ID and version
|
||||||
|
- CPU architecture
|
||||||
|
- Nginx binary package and version
|
||||||
|
- Nginx source package and version
|
||||||
|
- Nginx ABI, when present
|
||||||
|
|
||||||
|
Use an nginx.org tarball only when your target Nginx binary was built from the
|
||||||
|
same upstream Nginx source version and materially compatible configure options.
|
||||||
|
For Ubuntu/Debian packaged Nginx, use the `.deb` artifacts instead.
|
||||||
|
|
||||||
## Docker Image
|
## Docker Image
|
||||||
|
|
||||||
When `push_image` is true, the workflow also builds and pushes:
|
When `push_image` is true, the workflow also builds a self-contained demo image:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
ghcr.io/<owner>/<repo>:<tag>
|
ghcr.io/<owner>/<repo>:<tag>
|
||||||
ghcr.io/<owner>/<repo>:latest
|
ghcr.io/<owner>/<repo>:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
The image is built with Docker Buildx for the same normalized target platforms requested by `target_arches`.
|
The image is not the recommended artifact for installing the module into
|
||||||
|
distribution-packaged Nginx. It is a runnable demo image with Nginx and the
|
||||||
The release image build passes:
|
module built together.
|
||||||
|
|
||||||
```text
|
|
||||||
BASE_IMAGE=ubuntu:18.04
|
|
||||||
OPENSSL_RUNTIME_PACKAGE=libssl1.1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Compatibility Warning
|
|
||||||
|
|
||||||
Nginx dynamic modules are ABI-sensitive. The release packages are built with `--with-compat` on Ubuntu Bionic 18.04 against the Nginx version and CPU architecture in the filename. Use the matching Nginx version, CPU architecture, and a Linux/glibc runtime compatible with `ubuntu-bionic-glibc-2.27`. Rebuild locally when using a vendor Nginx package with materially different module ABI or hardening options.
|
|
||||||
|
|||||||
537
scripts/build-distro-release.sh
Normal file
537
scripts/build-distro-release.sh
Normal file
@@ -0,0 +1,537 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MODULE_NAME="${MODULE_NAME:-ngx_http_monitoring_module}"
|
||||||
|
DEB_PACKAGE_NAME="${DEB_PACKAGE_NAME:-libnginx-mod-http-monitoring}"
|
||||||
|
NGINX_INSTALL_PACKAGE="${NGINX_INSTALL_PACKAGE:-nginx}"
|
||||||
|
NEXT_VERSION="${NEXT_VERSION:-0.0.0}"
|
||||||
|
NEXT_TAG="${NEXT_TAG:-v${NEXT_VERSION}}"
|
||||||
|
LATEST_TAG="${LATEST_TAG:-none}"
|
||||||
|
TARGET_ARCH="${TARGET_ARCH:-$(uname -m)}"
|
||||||
|
DOCKER_PLATFORM="${DOCKER_PLATFORM:-unknown}"
|
||||||
|
DISTRO_IMAGE="${DISTRO_IMAGE:-unknown}"
|
||||||
|
DIST_DIR="${DIST_DIR:-/work/dist}"
|
||||||
|
WORK_ROOT="${WORK_ROOT:-/work/.release-work}"
|
||||||
|
VALIDATION_PORT="${VALIDATION_PORT:-18080}"
|
||||||
|
GITHUB_REF="${GITHUB_REF:-unknown}"
|
||||||
|
GITHUB_SHA="${GITHUB_SHA:-unknown}"
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
slugify() {
|
||||||
|
tr '[:upper:]' '[:lower:]' \
|
||||||
|
| sed -E 's/[^a-z0-9.+~]+/./g; s/^[.]+//; s/[.]+$//'
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "error: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
apt_install() {
|
||||||
|
apt-get install -y --no-install-recommends "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
find_nginx_abi() {
|
||||||
|
local pkg
|
||||||
|
local abi
|
||||||
|
|
||||||
|
for pkg in "$@"; do
|
||||||
|
abi="$(
|
||||||
|
apt-cache show "$pkg" 2>/dev/null \
|
||||||
|
| awk -F': ' '
|
||||||
|
/^Provides:/ {
|
||||||
|
n = split($2, provides, ",")
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
gsub(/^[ \t]+|[ \t]+$/, "", provides[i])
|
||||||
|
if (provides[i] ~ /^nginx-abi-/) {
|
||||||
|
print provides[i]
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' \
|
||||||
|
| head -n 1 \
|
||||||
|
|| true
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ -n "$abi" ]]; then
|
||||||
|
printf '%s\n' "$abi"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_module() {
|
||||||
|
local module_path="$1"
|
||||||
|
local runtime_root="$2"
|
||||||
|
local config_path="$runtime_root/nginx.conf"
|
||||||
|
local base_url="http://127.0.0.1:${VALIDATION_PORT}"
|
||||||
|
local status
|
||||||
|
local dashboard
|
||||||
|
local sse_output
|
||||||
|
|
||||||
|
rm -rf "$runtime_root"
|
||||||
|
mkdir -p \
|
||||||
|
"$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' "$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' "$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'
|
||||||
|
printf ' monitor_shm_size 8m;\n'
|
||||||
|
printf ' monitor_collect_system on;\n'
|
||||||
|
printf ' monitor_collect_nginx on;\n'
|
||||||
|
printf ' monitor_collect_network on;\n'
|
||||||
|
printf ' monitor_access_log on;\n'
|
||||||
|
printf ' monitor_max_top_urls 100;\n\n'
|
||||||
|
printf ' server {\n'
|
||||||
|
printf ' listen 127.0.0.1:%s;\n' "$VALIDATION_PORT"
|
||||||
|
printf ' server_name localhost;\n\n'
|
||||||
|
printf ' location /monitor {\n'
|
||||||
|
printf ' monitor on;\n'
|
||||||
|
printf ' monitor_dashboard on;\n'
|
||||||
|
printf ' monitor_api on;\n'
|
||||||
|
printf ' monitor_sse on;\n'
|
||||||
|
printf ' monitor_allow all;\n'
|
||||||
|
printf ' monitor_basic_auth off;\n'
|
||||||
|
printf ' monitor_cors off;\n'
|
||||||
|
printf ' monitor_rate_limit 120;\n'
|
||||||
|
printf ' }\n\n'
|
||||||
|
printf ' location / {\n'
|
||||||
|
printf ' return 200 "ok\\n";\n'
|
||||||
|
printf ' }\n'
|
||||||
|
printf ' }\n'
|
||||||
|
printf '}\n'
|
||||||
|
} > "$config_path"
|
||||||
|
|
||||||
|
nginx -t -p "$runtime_root" -c "$config_path"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
nginx -p "$runtime_root" -c "$config_path" -s quit >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup RETURN
|
||||||
|
|
||||||
|
nginx -p "$runtime_root" -c "$config_path"
|
||||||
|
|
||||||
|
for attempt in $(seq 1 50); do
|
||||||
|
if curl -fsS "$base_url/" >/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$attempt" -eq 50 ]]; then
|
||||||
|
echo "Nginx did not become ready" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
|
||||||
|
curl -fsS "$base_url/" | grep -q '^ok'
|
||||||
|
|
||||||
|
status="$(curl -fsS -o "$runtime_root/dashboard.html" -w '%{http_code}' "$base_url/monitor")"
|
||||||
|
[[ "$status" == "200" ]] || fail "/monitor returned HTTP $status"
|
||||||
|
dashboard="$(cat "$runtime_root/dashboard.html")"
|
||||||
|
printf '%s' "$dashboard" | grep -q '<title>Nginx Monitor</title>'
|
||||||
|
printf '%s' "$dashboard" | grep -q '/monitor/api'
|
||||||
|
printf '%s' "$dashboard" | grep -q '/monitor/live'
|
||||||
|
|
||||||
|
curl -fsS "$base_url/monitor/api" \
|
||||||
|
| jq -e '.version == 1 and has("system") and has("nginx") and has("requests") and has("history")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/api/system" \
|
||||||
|
| jq -e '.version == 1 and .scope == "system" and has("system")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/api/nginx" \
|
||||||
|
| jq -e '.version == 1 and .scope == "nginx" and has("nginx")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/health" \
|
||||||
|
| jq -e '.version == 1 and .scope == "health" and .status == "ok"' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/metrics" \
|
||||||
|
| grep -q '^nginx_monitor_requests_total '
|
||||||
|
|
||||||
|
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: {'
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
trap - RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "$DIST_DIR" "$WORK_ROOT"
|
||||||
|
|
||||||
|
printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d
|
||||||
|
chmod +x /usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt_install ca-certificates curl gnupg
|
||||||
|
bash /work/scripts/enable-apt-source-repos.sh
|
||||||
|
apt-get update
|
||||||
|
apt_install \
|
||||||
|
bash \
|
||||||
|
binutils \
|
||||||
|
build-essential \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dpkg-dev \
|
||||||
|
file \
|
||||||
|
findutils \
|
||||||
|
jq \
|
||||||
|
libpcre2-dev \
|
||||||
|
libssl-dev \
|
||||||
|
python3 \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
"$NGINX_INSTALL_PACKAGE"
|
||||||
|
|
||||||
|
. /etc/os-release
|
||||||
|
distro_id="${ID:-unknown}"
|
||||||
|
distro_version="${VERSION_ID:-unknown}"
|
||||||
|
distro_codename="${VERSION_CODENAME:-${UBUNTU_CODENAME:-unknown}}"
|
||||||
|
distro_slug="$(printf '%s-%s-%s' "$distro_id" "$distro_version" "$distro_codename" | slugify)"
|
||||||
|
|
||||||
|
deb_arch="$(dpkg --print-architecture)"
|
||||||
|
nginx_bin="$(command -v nginx)"
|
||||||
|
nginx_binary_package="$(dpkg-query -S "$nginx_bin" | head -n 1 | cut -d: -f1)"
|
||||||
|
nginx_binary_version="$(dpkg-query -W -f='${Version}' "$nginx_binary_package")"
|
||||||
|
source_package="$(dpkg-query -W -f='${source:Package}' "$nginx_binary_package" 2>/dev/null || true)"
|
||||||
|
source_version="$(dpkg-query -W -f='${source:Version}' "$nginx_binary_package" 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [[ -z "$source_package" || "$source_package" == *'{'* ]]; then
|
||||||
|
source_package="$nginx_binary_package"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$source_version" || "$source_version" == *'{'* ]]; then
|
||||||
|
source_version="$nginx_binary_version"
|
||||||
|
fi
|
||||||
|
|
||||||
|
nginx_abi="$(find_nginx_abi "$nginx_binary_package" "$NGINX_INSTALL_PACKAGE" nginx-core nginx-full nginx-light nginx-extras nginx)"
|
||||||
|
|
||||||
|
echo "Distro: ${distro_id} ${distro_version} (${distro_codename}), arch ${deb_arch}"
|
||||||
|
echo "Nginx binary package: ${nginx_binary_package} ${nginx_binary_version}"
|
||||||
|
echo "Nginx source package: ${source_package} ${source_version}"
|
||||||
|
echo "Nginx ABI package: ${nginx_abi:-none found}"
|
||||||
|
|
||||||
|
src_root="$WORK_ROOT/${distro_slug}/${deb_arch}/source"
|
||||||
|
build_root="$WORK_ROOT/${distro_slug}/${deb_arch}/build"
|
||||||
|
rm -rf "$src_root" "$build_root"
|
||||||
|
mkdir -p "$src_root" "$build_root"
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$src_root"
|
||||||
|
apt-get source "${source_package}=${source_version}" \
|
||||||
|
|| apt-get source "$source_package"
|
||||||
|
)
|
||||||
|
|
||||||
|
dsc_path="$(find "$src_root" -maxdepth 1 -name '*.dsc' | head -n 1)"
|
||||||
|
[[ -n "$dsc_path" ]] || fail "apt-get source did not download a .dsc file"
|
||||||
|
|
||||||
|
dsc_version="$(awk '/^Version:/ { print $2; exit }' "$dsc_path")"
|
||||||
|
if [[ "$dsc_version" != "$source_version" ]]; then
|
||||||
|
fail "downloaded source version ${dsc_version}, expected ${source_version}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
nginx_src="$(find "$src_root" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
|
||||||
|
[[ -n "$nginx_src" ]] || fail "apt-get source did not unpack an nginx source directory"
|
||||||
|
|
||||||
|
apt-get build-dep -y --no-install-recommends "${source_package}=${source_version}" \
|
||||||
|
|| apt-get build-dep -y --no-install-recommends "$source_package"
|
||||||
|
|
||||||
|
nginx_build_info="$build_root/nginx-build-info.json"
|
||||||
|
python3 /work/scripts/nginx-build-info.py --nginx-src "$nginx_src" --json > "$nginx_build_info"
|
||||||
|
modules_path="$(python3 /work/scripts/nginx-build-info.py --modules-path)"
|
||||||
|
configure_line="$(python3 /work/scripts/nginx-build-info.py --nginx-src "$nginx_src" --configure-line)"
|
||||||
|
|
||||||
|
case "$modules_path" in
|
||||||
|
/*) ;;
|
||||||
|
*) modules_path="/${modules_path}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
source_version_slug="$(printf '%s' "$source_version" | slugify)"
|
||||||
|
deb_revision_slug="$(printf '%s%s.nginx%s' "$distro_id" "$distro_version" "$source_version" | slugify)"
|
||||||
|
deb_version="${NEXT_VERSION}-1+${deb_revision_slug}"
|
||||||
|
build_metadata="$(printf '%s.%s.%s' "$distro_slug" "$deb_arch" "$source_version_slug" | slugify)"
|
||||||
|
module_cflags="-DNGX_HTTP_MONITORING_MODULE_VERSION=\\\"${NEXT_VERSION}\\\" -DNGX_HTTP_MONITORING_BUILD_METADATA=\\\"${build_metadata}\\\""
|
||||||
|
|
||||||
|
cd "$nginx_src"
|
||||||
|
eval "./configure ${configure_line} --with-cc-opt=\"${module_cflags}\" --add-dynamic-module=/work"
|
||||||
|
|
||||||
|
build_jobs="$(nproc)"
|
||||||
|
if [[ "$TARGET_ARCH" != "linux-x86_64" && "$build_jobs" -gt 2 ]]; then
|
||||||
|
build_jobs=2
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -j"$build_jobs" modules
|
||||||
|
|
||||||
|
built_module="$nginx_src/objs/${MODULE_NAME}.so"
|
||||||
|
[[ -f "$built_module" ]] || fail "module was not built at ${built_module}"
|
||||||
|
|
||||||
|
artifact_base="${MODULE_NAME}-${NEXT_TAG}-${distro_slug}-nginx-${source_version_slug}-${deb_arch}"
|
||||||
|
deb_file="${DEB_PACKAGE_NAME}_${deb_version}_${deb_arch}.deb"
|
||||||
|
tarball_file="${artifact_base}.tar.gz"
|
||||||
|
package_root="$build_root/package-root"
|
||||||
|
doc_dir="$package_root/usr/share/doc/$DEB_PACKAGE_NAME"
|
||||||
|
module_install_dir="$package_root/${modules_path#/}"
|
||||||
|
modules_available_dir="$package_root/usr/share/nginx/modules-available"
|
||||||
|
metadata_dir="$doc_dir/metadata"
|
||||||
|
|
||||||
|
rm -rf "$package_root"
|
||||||
|
mkdir -p "$module_install_dir" "$modules_available_dir" "$metadata_dir" "$package_root/DEBIAN"
|
||||||
|
|
||||||
|
cp "$built_module" "$module_install_dir/${MODULE_NAME}.so"
|
||||||
|
strip --strip-unneeded "$module_install_dir/${MODULE_NAME}.so" || true
|
||||||
|
|
||||||
|
cat > "$modules_available_dir/mod-http-monitoring.conf" <<EOF
|
||||||
|
load_module ${modules_path}/${MODULE_NAME}.so;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cp /work/README.md "$doc_dir/README.md"
|
||||||
|
cp /work/LICENSE "$doc_dir/copyright"
|
||||||
|
cp /work/docs/API.md "$doc_dir/API.md"
|
||||||
|
cp /work/docs/CONFIGURATION.md "$doc_dir/CONFIGURATION.md"
|
||||||
|
cp /work/docs/PERFORMANCE.md "$doc_dir/PERFORMANCE.md"
|
||||||
|
cp /work/examples/monitoring-site.conf "$doc_dir/monitoring-site.conf.example"
|
||||||
|
|
||||||
|
cat > "$doc_dir/changelog.Debian" <<EOF
|
||||||
|
$DEB_PACKAGE_NAME (${deb_version}) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Build ${NEXT_TAG} against ${distro_id} ${distro_version} nginx source ${source_version}.
|
||||||
|
|
||||||
|
-- GitHub Actions <actions@github.com> $(date -Ru)
|
||||||
|
EOF
|
||||||
|
gzip -9n "$doc_dir/changelog.Debian"
|
||||||
|
|
||||||
|
module_sha256="$(sha256sum "$module_install_dir/${MODULE_NAME}.so" | awk '{ print $1 }')"
|
||||||
|
dsc_sha256="$(sha256sum "$dsc_path" | awk '{ print $1 }')"
|
||||||
|
nginx_v_text="$metadata_dir/nginx-V.txt"
|
||||||
|
nginx -V > "$nginx_v_text" 2>&1
|
||||||
|
|
||||||
|
compatibility_json="$metadata_dir/compatibility.json"
|
||||||
|
jq -n \
|
||||||
|
--slurpfile nginxBuild "$nginx_build_info" \
|
||||||
|
--arg schema "1" \
|
||||||
|
--arg module "$MODULE_NAME" \
|
||||||
|
--arg debPackage "$DEB_PACKAGE_NAME" \
|
||||||
|
--arg debVersion "$deb_version" \
|
||||||
|
--arg releaseTag "$NEXT_TAG" \
|
||||||
|
--arg releaseVersion "$NEXT_VERSION" \
|
||||||
|
--arg previousTag "$LATEST_TAG" \
|
||||||
|
--arg gitRef "$GITHUB_REF" \
|
||||||
|
--arg gitSha "$GITHUB_SHA" \
|
||||||
|
--arg distroImage "$DISTRO_IMAGE" \
|
||||||
|
--arg dockerPlatform "$DOCKER_PLATFORM" \
|
||||||
|
--arg targetArch "$TARGET_ARCH" \
|
||||||
|
--arg osId "$distro_id" \
|
||||||
|
--arg osVersion "$distro_version" \
|
||||||
|
--arg osCodename "$distro_codename" \
|
||||||
|
--arg debArch "$deb_arch" \
|
||||||
|
--arg nginxBinaryPackage "$nginx_binary_package" \
|
||||||
|
--arg nginxBinaryVersion "$nginx_binary_version" \
|
||||||
|
--arg nginxSourcePackage "$source_package" \
|
||||||
|
--arg nginxSourceVersion "$source_version" \
|
||||||
|
--arg nginxAbi "$nginx_abi" \
|
||||||
|
--arg modulesPath "$modules_path" \
|
||||||
|
--arg dscPath "$(basename "$dsc_path")" \
|
||||||
|
--arg dscSha256 "$dsc_sha256" \
|
||||||
|
--arg moduleSha256 "$module_sha256" \
|
||||||
|
--arg builtAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
--arg artifactBase "$artifact_base" \
|
||||||
|
--arg debFile "$deb_file" \
|
||||||
|
--arg tarballFile "$tarball_file" \
|
||||||
|
'{
|
||||||
|
schema: ($schema | tonumber),
|
||||||
|
module: $module,
|
||||||
|
release: {
|
||||||
|
tag: $releaseTag,
|
||||||
|
version: $releaseVersion,
|
||||||
|
previous_tag: $previousTag,
|
||||||
|
git_ref: $gitRef,
|
||||||
|
git_sha: $gitSha
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
os_id: $osId,
|
||||||
|
os_version: $osVersion,
|
||||||
|
os_codename: $osCodename,
|
||||||
|
architecture: $debArch,
|
||||||
|
requested_target: $targetArch,
|
||||||
|
docker_image: $distroImage,
|
||||||
|
docker_platform: $dockerPlatform
|
||||||
|
},
|
||||||
|
nginx: {
|
||||||
|
binary_package: $nginxBinaryPackage,
|
||||||
|
binary_version: $nginxBinaryVersion,
|
||||||
|
source_package: $nginxSourcePackage,
|
||||||
|
source_version: $nginxSourceVersion,
|
||||||
|
abi: $nginxAbi,
|
||||||
|
modules_path: $modulesPath,
|
||||||
|
build: $nginxBuild[0]
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
method: "distro-source-package",
|
||||||
|
dsc_file: $dscPath,
|
||||||
|
dsc_sha256: $dscSha256,
|
||||||
|
module_sha256: $moduleSha256,
|
||||||
|
built_at: $builtAt
|
||||||
|
},
|
||||||
|
artifacts: {
|
||||||
|
base_name: $artifactBase,
|
||||||
|
deb_package: $debPackage,
|
||||||
|
deb_version: $debVersion,
|
||||||
|
deb_file: $debFile,
|
||||||
|
tarball_file: $tarballFile,
|
||||||
|
compatibility_file: ($artifactBase + ".compatibility.json")
|
||||||
|
},
|
||||||
|
packaging: {
|
||||||
|
deb_depends: (
|
||||||
|
if $nginxAbi == "" then
|
||||||
|
[($nginxBinaryPackage + " (= " + $nginxBinaryVersion + ")"), "libc6"]
|
||||||
|
else
|
||||||
|
[$nginxAbi, ($nginxBinaryPackage + " (= " + $nginxBinaryVersion + ")"), "libc6"]
|
||||||
|
end
|
||||||
|
)
|
||||||
|
},
|
||||||
|
validation: {
|
||||||
|
packaged_nginx_config_test: false,
|
||||||
|
packaged_nginx_endpoint_smoke: false
|
||||||
|
}
|
||||||
|
}' > "$compatibility_json"
|
||||||
|
|
||||||
|
cat > "$doc_dir/INSTALL.md" <<EOF
|
||||||
|
# ${MODULE_NAME} for ${distro_id} ${distro_version} ${deb_arch}
|
||||||
|
|
||||||
|
This package was built from the ${source_package} source package version
|
||||||
|
${source_version} and validated against the packaged ${nginx_binary_package}
|
||||||
|
binary version ${nginx_binary_version}.
|
||||||
|
|
||||||
|
Recommended install:
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
sudo apt install ./$(printf '%s_%s_%s.deb' "$DEB_PACKAGE_NAME" "$deb_version" "$deb_arch")
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
The package installs the module at:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
${modules_path}/${MODULE_NAME}.so
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Load it near the top of nginx.conf:
|
||||||
|
|
||||||
|
\`\`\`nginx
|
||||||
|
load_module ${modules_path}/${MODULE_NAME}.so;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Compatibility guard:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
$(if [[ -n "$nginx_abi" ]]; then printf 'Depends: %s\nDepends: %s (= %s)\n' "$nginx_abi" "$nginx_binary_package" "$nginx_binary_version"; else printf 'Depends: %s (= %s)\n' "$nginx_binary_package" "$nginx_binary_version"; fi)
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
If a distro nginx update changes this ABI, apt will refuse to keep this module
|
||||||
|
installed with the new nginx package. Rebuild and publish a new package for the
|
||||||
|
new distro nginx package instead of reusing this binary.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
depends=""
|
||||||
|
if [[ -n "$nginx_abi" ]]; then
|
||||||
|
depends="$nginx_abi, $nginx_binary_package (= $nginx_binary_version), libc6"
|
||||||
|
else
|
||||||
|
depends="$nginx_binary_package (= $nginx_binary_version), libc6"
|
||||||
|
fi
|
||||||
|
|
||||||
|
installed_size="$(du -ks "$package_root" | awk '{ print $1 }')"
|
||||||
|
cat > "$package_root/DEBIAN/control" <<EOF
|
||||||
|
Package: $DEB_PACKAGE_NAME
|
||||||
|
Version: $deb_version
|
||||||
|
Section: httpd
|
||||||
|
Priority: optional
|
||||||
|
Architecture: $deb_arch
|
||||||
|
Maintainer: ngx_http_monitoring_module maintainers <noreply@github.com>
|
||||||
|
Depends: $depends
|
||||||
|
Installed-Size: $installed_size
|
||||||
|
Description: Nginx HTTP monitoring dynamic module
|
||||||
|
Distro-built dynamic module for live Nginx monitoring, JSON APIs,
|
||||||
|
Server-Sent Events, Prometheus metrics, and an embedded dashboard.
|
||||||
|
This package is built against the target distribution nginx source package
|
||||||
|
and depends on the matching nginx module ABI.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
deb_path="$DIST_DIR/$deb_file"
|
||||||
|
dpkg-deb --build --root-owner-group "$package_root" "$deb_path"
|
||||||
|
|
||||||
|
apt-get install -y --no-install-recommends "$deb_path"
|
||||||
|
validate_module "${modules_path}/${MODULE_NAME}.so" "$build_root/runtime"
|
||||||
|
|
||||||
|
jq \
|
||||||
|
--arg debFile "$deb_file" \
|
||||||
|
--arg validationTime "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
'.artifacts.deb_file = $debFile
|
||||||
|
| .validation.packaged_nginx_config_test = true
|
||||||
|
| .validation.packaged_nginx_endpoint_smoke = true
|
||||||
|
| .validation.validated_at = $validationTime' \
|
||||||
|
"$compatibility_json" > "$compatibility_json.tmp"
|
||||||
|
mv "$compatibility_json.tmp" "$compatibility_json"
|
||||||
|
dpkg-deb --build --root-owner-group "$package_root" "$deb_path"
|
||||||
|
|
||||||
|
tar_root="$build_root/tar"
|
||||||
|
tar_dir="$tar_root/$artifact_base"
|
||||||
|
rm -rf "$tar_root"
|
||||||
|
mkdir -p "$tar_dir/modules" "$tar_dir/docs" "$tar_dir/examples"
|
||||||
|
cp "${modules_path}/${MODULE_NAME}.so" "$tar_dir/modules/${MODULE_NAME}.so"
|
||||||
|
cp "$compatibility_json" "$tar_dir/COMPATIBILITY.json"
|
||||||
|
cp "$doc_dir/INSTALL.md" "$tar_dir/INSTALL.md"
|
||||||
|
cp "$doc_dir/README.md" "$tar_dir/README.md"
|
||||||
|
cp "$doc_dir/API.md" "$tar_dir/docs/API.md"
|
||||||
|
cp "$doc_dir/CONFIGURATION.md" "$tar_dir/docs/CONFIGURATION.md"
|
||||||
|
cp "$doc_dir/PERFORMANCE.md" "$tar_dir/docs/PERFORMANCE.md"
|
||||||
|
cp "$doc_dir/monitoring-site.conf.example" "$tar_dir/examples/monitoring-site.conf"
|
||||||
|
cp "$nginx_v_text" "$tar_dir/NGINX-V.txt"
|
||||||
|
|
||||||
|
{
|
||||||
|
printf 'module=%s\n' "$MODULE_NAME"
|
||||||
|
printf 'module_release=%s\n' "$NEXT_TAG"
|
||||||
|
printf 'module_version=%s\n' "$NEXT_VERSION"
|
||||||
|
printf 'module_build_metadata=%s\n' "$build_metadata"
|
||||||
|
printf 'distro=%s\n' "$distro_slug"
|
||||||
|
printf 'architecture=%s\n' "$deb_arch"
|
||||||
|
printf 'nginx_binary_package=%s\n' "$nginx_binary_package"
|
||||||
|
printf 'nginx_binary_version=%s\n' "$nginx_binary_version"
|
||||||
|
printf 'nginx_source_package=%s\n' "$source_package"
|
||||||
|
printf 'nginx_source_version=%s\n' "$source_version"
|
||||||
|
printf 'nginx_abi=%s\n' "$nginx_abi"
|
||||||
|
printf 'modules_path=%s\n' "$modules_path"
|
||||||
|
printf 'git_ref=%s\n' "$GITHUB_REF"
|
||||||
|
printf 'git_sha=%s\n' "$GITHUB_SHA"
|
||||||
|
printf 'built_at=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
} > "$tar_dir/METADATA.txt"
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$tar_dir"
|
||||||
|
sha256sum "modules/${MODULE_NAME}.so" COMPATIBILITY.json > SHA256SUMS
|
||||||
|
file "modules/${MODULE_NAME}.so" > FILE.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
tar -czf "$DIST_DIR/$tarball_file" -C "$tar_root" "$artifact_base"
|
||||||
|
|
||||||
|
cp "$compatibility_json" "$DIST_DIR/${artifact_base}.compatibility.json"
|
||||||
|
|
||||||
|
echo "Built $deb_path"
|
||||||
|
echo "Built $DIST_DIR/$tarball_file"
|
||||||
|
echo "Built $DIST_DIR/${artifact_base}.compatibility.json"
|
||||||
359
scripts/build-upstream-release.sh
Normal file
359
scripts/build-upstream-release.sh
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MODULE_NAME="${MODULE_NAME:-ngx_http_monitoring_module}"
|
||||||
|
BUILD_NGINX_VERSIONS="${BUILD_NGINX_VERSIONS:-}"
|
||||||
|
NEXT_VERSION="${NEXT_VERSION:-0.0.0}"
|
||||||
|
NEXT_TAG="${NEXT_TAG:-v${NEXT_VERSION}}"
|
||||||
|
LATEST_TAG="${LATEST_TAG:-none}"
|
||||||
|
TARGET_ARCH="${TARGET_ARCH:-$(uname -m)}"
|
||||||
|
DOCKER_PLATFORM="${DOCKER_PLATFORM:-unknown}"
|
||||||
|
RELEASE_BUILD_IMAGE="${RELEASE_BUILD_IMAGE:-unknown}"
|
||||||
|
RELEASE_LIBC_BASELINE="${RELEASE_LIBC_BASELINE:-unknown}"
|
||||||
|
NGINX_CONFIGURE_ARGS="${NGINX_CONFIGURE_ARGS:---with-compat --with-http_ssl_module --with-http_stub_status_module}"
|
||||||
|
DIST_DIR="${DIST_DIR:-/work/dist}"
|
||||||
|
WORK_ROOT="${WORK_ROOT:-/work/.release-work/upstream}"
|
||||||
|
VALIDATION_PORT="${VALIDATION_PORT:-18080}"
|
||||||
|
GITHUB_REF="${GITHUB_REF:-unknown}"
|
||||||
|
GITHUB_SHA="${GITHUB_SHA:-unknown}"
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "error: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
slugify() {
|
||||||
|
tr '[:upper:]' '[:lower:]' \
|
||||||
|
| sed -E 's/[^a-z0-9.+~]+/./g; s/^[.]+//; s/[.]+$//'
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_module() {
|
||||||
|
local nginx_bin="$1"
|
||||||
|
local module_path="$2"
|
||||||
|
local runtime_root="$3"
|
||||||
|
local config_path="$runtime_root/nginx.conf"
|
||||||
|
local base_url="http://127.0.0.1:${VALIDATION_PORT}"
|
||||||
|
local status
|
||||||
|
local dashboard
|
||||||
|
local sse_output
|
||||||
|
|
||||||
|
rm -rf "$runtime_root"
|
||||||
|
mkdir -p \
|
||||||
|
"$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' "$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' "$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'
|
||||||
|
printf ' monitor_shm_size 8m;\n'
|
||||||
|
printf ' monitor_collect_system on;\n'
|
||||||
|
printf ' monitor_collect_nginx on;\n'
|
||||||
|
printf ' monitor_collect_network on;\n'
|
||||||
|
printf ' monitor_access_log on;\n'
|
||||||
|
printf ' monitor_max_top_urls 100;\n\n'
|
||||||
|
printf ' server {\n'
|
||||||
|
printf ' listen 127.0.0.1:%s;\n' "$VALIDATION_PORT"
|
||||||
|
printf ' server_name localhost;\n\n'
|
||||||
|
printf ' location /monitor {\n'
|
||||||
|
printf ' monitor on;\n'
|
||||||
|
printf ' monitor_dashboard on;\n'
|
||||||
|
printf ' monitor_api on;\n'
|
||||||
|
printf ' monitor_sse on;\n'
|
||||||
|
printf ' monitor_allow all;\n'
|
||||||
|
printf ' monitor_basic_auth off;\n'
|
||||||
|
printf ' monitor_cors off;\n'
|
||||||
|
printf ' monitor_rate_limit 120;\n'
|
||||||
|
printf ' }\n\n'
|
||||||
|
printf ' location / {\n'
|
||||||
|
printf ' return 200 "ok\\n";\n'
|
||||||
|
printf ' }\n'
|
||||||
|
printf ' }\n'
|
||||||
|
printf '}\n'
|
||||||
|
} > "$config_path"
|
||||||
|
|
||||||
|
"$nginx_bin" -t -p "$runtime_root" -c "$config_path"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
"$nginx_bin" -p "$runtime_root" -c "$config_path" -s quit >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup RETURN
|
||||||
|
|
||||||
|
"$nginx_bin" -p "$runtime_root" -c "$config_path"
|
||||||
|
|
||||||
|
for attempt in $(seq 1 50); do
|
||||||
|
if curl -fsS "$base_url/" >/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$attempt" -eq 50 ]]; then
|
||||||
|
echo "Nginx did not become ready" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
|
||||||
|
curl -fsS "$base_url/" | grep -q '^ok'
|
||||||
|
|
||||||
|
status="$(curl -fsS -o "$runtime_root/dashboard.html" -w '%{http_code}' "$base_url/monitor")"
|
||||||
|
[[ "$status" == "200" ]] || fail "/monitor returned HTTP $status"
|
||||||
|
dashboard="$(cat "$runtime_root/dashboard.html")"
|
||||||
|
printf '%s' "$dashboard" | grep -q '<title>Nginx Monitor</title>'
|
||||||
|
printf '%s' "$dashboard" | grep -q '/monitor/api'
|
||||||
|
printf '%s' "$dashboard" | grep -q '/monitor/live'
|
||||||
|
|
||||||
|
curl -fsS "$base_url/monitor/api" \
|
||||||
|
| jq -e '.version == 1 and has("system") and has("nginx") and has("requests") and has("history")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/api/system" \
|
||||||
|
| jq -e '.version == 1 and .scope == "system" and has("system")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/api/nginx" \
|
||||||
|
| jq -e '.version == 1 and .scope == "nginx" and has("nginx")' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/health" \
|
||||||
|
| jq -e '.version == 1 and .scope == "health" and .status == "ok"' >/dev/null
|
||||||
|
curl -fsS "$base_url/monitor/metrics" \
|
||||||
|
| grep -q '^nginx_monitor_requests_total '
|
||||||
|
|
||||||
|
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: {'
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
trap - RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -n "$BUILD_NGINX_VERSIONS" ]] || fail "BUILD_NGINX_VERSIONS is required"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
binutils \
|
||||||
|
build-essential \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
file \
|
||||||
|
jq \
|
||||||
|
libpcre2-dev \
|
||||||
|
libssl-dev \
|
||||||
|
zlib1g-dev
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
mkdir -p "$DIST_DIR" "$WORK_ROOT"
|
||||||
|
|
||||||
|
for nginx_version in $BUILD_NGINX_VERSIONS; do
|
||||||
|
archive="nginx-${nginx_version}.tar.gz"
|
||||||
|
archive_path="${WORK_ROOT}/${archive}"
|
||||||
|
workdir="${WORK_ROOT}/nginx-${nginx_version}"
|
||||||
|
runtime_root="${WORK_ROOT}/runtime/nginx-${nginx_version}"
|
||||||
|
|
||||||
|
if [[ ! -f "$archive_path" ]]; then
|
||||||
|
curl -fsSLo "$archive_path" "https://nginx.org/download/${archive}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "$workdir"
|
||||||
|
tar -xzf "$archive_path" -C "$WORK_ROOT"
|
||||||
|
|
||||||
|
nginx_version_slug="$(printf '%s' "$nginx_version" | slugify)"
|
||||||
|
build_metadata="$(printf 'nginxorg.%s.%s.%s' "$nginx_version_slug" "$TARGET_ARCH" "$RELEASE_LIBC_BASELINE" | slugify)"
|
||||||
|
module_cflags="-DNGX_HTTP_MONITORING_MODULE_VERSION=\\\"${NEXT_VERSION}\\\" -DNGX_HTTP_MONITORING_BUILD_METADATA=\\\"${build_metadata}\\\""
|
||||||
|
|
||||||
|
cd "$workdir"
|
||||||
|
./configure \
|
||||||
|
--prefix=/usr/local/nginx \
|
||||||
|
--sbin-path=/usr/local/sbin/nginx \
|
||||||
|
--modules-path=/usr/local/nginx/modules \
|
||||||
|
--conf-path=/etc/nginx/nginx.conf \
|
||||||
|
--error-log-path=/var/log/nginx/error.log \
|
||||||
|
--http-log-path=/var/log/nginx/access.log \
|
||||||
|
--pid-path=/var/run/nginx.pid \
|
||||||
|
--lock-path=/var/run/nginx.lock \
|
||||||
|
--http-client-body-temp-path=/var/cache/nginx/client_temp \
|
||||||
|
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
|
||||||
|
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
|
||||||
|
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
|
||||||
|
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
|
||||||
|
--with-cc-opt="$module_cflags" \
|
||||||
|
$NGINX_CONFIGURE_ARGS \
|
||||||
|
--add-dynamic-module=/work
|
||||||
|
|
||||||
|
build_jobs="$(nproc)"
|
||||||
|
if [[ "$TARGET_ARCH" != "linux-x86_64" && "$build_jobs" -gt 2 ]]; then
|
||||||
|
build_jobs=2
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -j"$build_jobs"
|
||||||
|
make -j"$build_jobs" modules
|
||||||
|
|
||||||
|
module_path="$workdir/objs/${MODULE_NAME}.so"
|
||||||
|
nginx_bin="$workdir/objs/nginx"
|
||||||
|
[[ -x "$nginx_bin" ]] || fail "nginx binary was not built at ${nginx_bin}"
|
||||||
|
[[ -f "$module_path" ]] || fail "module was not built at ${module_path}"
|
||||||
|
|
||||||
|
strip --strip-unneeded "$module_path" || true
|
||||||
|
validate_module "$nginx_bin" "$module_path" "$runtime_root"
|
||||||
|
|
||||||
|
module_sha256="$(sha256sum "$module_path" | awk '{ print $1 }')"
|
||||||
|
archive_sha256="$(sha256sum "$archive_path" | awk '{ print $1 }')"
|
||||||
|
artifact_base="${MODULE_NAME}-${NEXT_TAG}-nginxorg-${nginx_version_slug}-${TARGET_ARCH}"
|
||||||
|
package_root="${WORK_ROOT}/packages/${artifact_base}"
|
||||||
|
compatibility_json="${package_root}/COMPATIBILITY.json"
|
||||||
|
|
||||||
|
rm -rf "$package_root"
|
||||||
|
mkdir -p "$package_root/modules" "$package_root/docs" "$package_root/examples"
|
||||||
|
|
||||||
|
cp "$module_path" "$package_root/modules/${MODULE_NAME}.so"
|
||||||
|
cp /work/examples/nginx.conf "$package_root/examples/nginx.conf"
|
||||||
|
cp /work/examples/monitoring-site.conf "$package_root/examples/monitoring-site.conf"
|
||||||
|
cp /work/README.md "$package_root/README.md"
|
||||||
|
cp /work/docs/API.md "$package_root/docs/API.md"
|
||||||
|
cp /work/docs/CONFIGURATION.md "$package_root/docs/CONFIGURATION.md"
|
||||||
|
cp /work/docs/PERFORMANCE.md "$package_root/docs/PERFORMANCE.md"
|
||||||
|
"$nginx_bin" -V > "$package_root/NGINX-V.txt" 2>&1
|
||||||
|
|
||||||
|
tarball_file="${artifact_base}.tar.gz"
|
||||||
|
sidecar_file="${artifact_base}.compatibility.json"
|
||||||
|
|
||||||
|
jq -n \
|
||||||
|
--arg schema "1" \
|
||||||
|
--arg module "$MODULE_NAME" \
|
||||||
|
--arg releaseTag "$NEXT_TAG" \
|
||||||
|
--arg releaseVersion "$NEXT_VERSION" \
|
||||||
|
--arg previousTag "$LATEST_TAG" \
|
||||||
|
--arg gitRef "$GITHUB_REF" \
|
||||||
|
--arg gitSha "$GITHUB_SHA" \
|
||||||
|
--arg buildImage "$RELEASE_BUILD_IMAGE" \
|
||||||
|
--arg libcBaseline "$RELEASE_LIBC_BASELINE" \
|
||||||
|
--arg dockerPlatform "$DOCKER_PLATFORM" \
|
||||||
|
--arg targetArch "$TARGET_ARCH" \
|
||||||
|
--arg nginxVersion "$nginx_version" \
|
||||||
|
--arg configureArgs "$NGINX_CONFIGURE_ARGS" \
|
||||||
|
--arg archive "$archive" \
|
||||||
|
--arg archiveSha256 "$archive_sha256" \
|
||||||
|
--arg moduleSha256 "$module_sha256" \
|
||||||
|
--arg builtAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
--arg artifactBase "$artifact_base" \
|
||||||
|
--arg tarballFile "$tarball_file" \
|
||||||
|
--arg sidecarFile "$sidecar_file" \
|
||||||
|
--arg validationTime "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
'{
|
||||||
|
schema: ($schema | tonumber),
|
||||||
|
module: $module,
|
||||||
|
release: {
|
||||||
|
tag: $releaseTag,
|
||||||
|
version: $releaseVersion,
|
||||||
|
previous_tag: $previousTag,
|
||||||
|
git_ref: $gitRef,
|
||||||
|
git_sha: $gitSha
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
os_id: "nginx.org-source",
|
||||||
|
os_version: $nginxVersion,
|
||||||
|
os_codename: "upstream",
|
||||||
|
architecture: $targetArch,
|
||||||
|
requested_target: $targetArch,
|
||||||
|
docker_image: $buildImage,
|
||||||
|
docker_platform: $dockerPlatform,
|
||||||
|
libc_baseline: $libcBaseline
|
||||||
|
},
|
||||||
|
nginx: {
|
||||||
|
binary_package: "nginx.org-source-build",
|
||||||
|
binary_version: $nginxVersion,
|
||||||
|
source_package: "nginx.org",
|
||||||
|
source_version: $nginxVersion,
|
||||||
|
abi: "",
|
||||||
|
modules_path: "/usr/local/nginx/modules",
|
||||||
|
build: {
|
||||||
|
version: ("nginx/" + $nginxVersion),
|
||||||
|
configure_args: ($configureArgs | split(" ")),
|
||||||
|
configure_line: $configureArgs
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
method: "upstream-nginxorg-source",
|
||||||
|
source_archive: $archive,
|
||||||
|
source_archive_sha256: $archiveSha256,
|
||||||
|
module_sha256: $moduleSha256,
|
||||||
|
built_at: $builtAt
|
||||||
|
},
|
||||||
|
artifacts: {
|
||||||
|
base_name: $artifactBase,
|
||||||
|
deb_package: "",
|
||||||
|
deb_version: "",
|
||||||
|
deb_file: "",
|
||||||
|
tarball_file: $tarballFile,
|
||||||
|
compatibility_file: $sidecarFile
|
||||||
|
},
|
||||||
|
packaging: {
|
||||||
|
deb_depends: []
|
||||||
|
},
|
||||||
|
validation: {
|
||||||
|
packaged_nginx_config_test: false,
|
||||||
|
packaged_nginx_endpoint_smoke: false,
|
||||||
|
built_nginx_config_test: true,
|
||||||
|
built_nginx_endpoint_smoke: true,
|
||||||
|
validated_at: $validationTime
|
||||||
|
}
|
||||||
|
}' > "$compatibility_json"
|
||||||
|
|
||||||
|
{
|
||||||
|
printf '# %s for nginx.org %s\n\n' "$MODULE_NAME" "$nginx_version"
|
||||||
|
printf 'Release: `%s`\n\n' "$NEXT_TAG"
|
||||||
|
printf 'Target: `%s` (`%s`)\n\n' "$TARGET_ARCH" "$DOCKER_PLATFORM"
|
||||||
|
printf 'Build baseline: `%s`\n\n' "$RELEASE_LIBC_BASELINE"
|
||||||
|
printf 'This tarball is built against upstream nginx.org source, not a Debian or Ubuntu source package.\n\n'
|
||||||
|
printf 'Use this artifact for Nginx binaries built from the same upstream source version and compatible configure options. For distribution-packaged Nginx, prefer the distro `.deb` release artifacts.\n\n'
|
||||||
|
printf 'Load it near the top of `nginx.conf`:\n\n'
|
||||||
|
printf '```nginx\n'
|
||||||
|
printf 'load_module modules/%s.so;\n' "$MODULE_NAME"
|
||||||
|
printf '```\n'
|
||||||
|
} > "$package_root/INSTALL.md"
|
||||||
|
|
||||||
|
{
|
||||||
|
printf 'module=%s\n' "$MODULE_NAME"
|
||||||
|
printf 'module_release=%s\n' "$NEXT_TAG"
|
||||||
|
printf 'module_version=%s\n' "$NEXT_VERSION"
|
||||||
|
printf 'module_build_metadata=%s\n' "$build_metadata"
|
||||||
|
printf 'nginx_source=nginx.org\n'
|
||||||
|
printf 'nginx_version=%s\n' "$nginx_version"
|
||||||
|
printf 'target=%s\n' "$TARGET_ARCH"
|
||||||
|
printf 'docker_platform=%s\n' "$DOCKER_PLATFORM"
|
||||||
|
printf 'build_image=%s\n' "$RELEASE_BUILD_IMAGE"
|
||||||
|
printf 'libc_baseline=%s\n' "$RELEASE_LIBC_BASELINE"
|
||||||
|
printf 'configure_args=%s\n' "$NGINX_CONFIGURE_ARGS"
|
||||||
|
printf 'git_ref=%s\n' "$GITHUB_REF"
|
||||||
|
printf 'git_sha=%s\n' "$GITHUB_SHA"
|
||||||
|
printf 'built_at=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
} > "$package_root/METADATA.txt"
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$package_root"
|
||||||
|
sha256sum "modules/${MODULE_NAME}.so" COMPATIBILITY.json > SHA256SUMS
|
||||||
|
file "modules/${MODULE_NAME}.so" > FILE.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
tar -czf "$DIST_DIR/$tarball_file" -C "$(dirname "$package_root")" "$(basename "$package_root")"
|
||||||
|
cp "$compatibility_json" "$DIST_DIR/$sidecar_file"
|
||||||
|
|
||||||
|
echo "Built $DIST_DIR/$tarball_file"
|
||||||
|
echo "Built $DIST_DIR/$sidecar_file"
|
||||||
|
done
|
||||||
53
scripts/enable-apt-source-repos.sh
Normal file
53
scripts/enable-apt-source-repos.sh
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
enable_deb822_sources() {
|
||||||
|
local file="$1"
|
||||||
|
local tmp
|
||||||
|
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
awk '
|
||||||
|
/^Types:/ {
|
||||||
|
if ($0 !~ /(^|[[:space:]])deb-src($|[[:space:]])/) {
|
||||||
|
print $0 " deb-src"
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' "$file" > "$tmp"
|
||||||
|
cat "$tmp" > "$file"
|
||||||
|
rm -f "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_legacy_sources() {
|
||||||
|
local file="$1"
|
||||||
|
local output="$2"
|
||||||
|
|
||||||
|
awk '
|
||||||
|
/^[[:space:]]*deb[[:space:]]/ {
|
||||||
|
line = $0
|
||||||
|
sub(/^[[:space:]]*deb[[:space:]]+/, "deb-src ", line)
|
||||||
|
print line
|
||||||
|
}
|
||||||
|
' "$file" > "$output"
|
||||||
|
}
|
||||||
|
|
||||||
|
found_sources=0
|
||||||
|
|
||||||
|
for sources_file in /etc/apt/sources.list.d/*.sources; do
|
||||||
|
if [[ -f "$sources_file" ]]; then
|
||||||
|
found_sources=1
|
||||||
|
enable_deb822_sources "$sources_file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -f /etc/apt/sources.list ]]; then
|
||||||
|
found_sources=1
|
||||||
|
enable_legacy_sources /etc/apt/sources.list \
|
||||||
|
/etc/apt/sources.list.d/codex-deb-src.list
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$found_sources" -eq 0 ]]; then
|
||||||
|
echo "No apt source list files were found under /etc/apt" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
124
scripts/nginx-build-info.py
Normal file
124
scripts/nginx-build-info.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def nginx_v_output(nginx_bin):
|
||||||
|
proc = subprocess.run(
|
||||||
|
[nginx_bin, "-V"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return proc.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def parse_nginx_v(output):
|
||||||
|
version = ""
|
||||||
|
configure_line = ""
|
||||||
|
|
||||||
|
for line in output.splitlines():
|
||||||
|
if line.startswith("nginx version:"):
|
||||||
|
version = line.split(":", 1)[1].strip()
|
||||||
|
elif line.startswith("configure arguments:"):
|
||||||
|
configure_line = line.split(":", 1)[1].strip()
|
||||||
|
|
||||||
|
if not configure_line:
|
||||||
|
raise RuntimeError("nginx -V did not include configure arguments")
|
||||||
|
|
||||||
|
return version, configure_line, shlex.split(configure_line)
|
||||||
|
|
||||||
|
|
||||||
|
def option_value(args, option):
|
||||||
|
prefix = option + "="
|
||||||
|
for arg in args:
|
||||||
|
if arg.startswith(prefix):
|
||||||
|
return arg[len(prefix) :]
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_module_path(arg, nginx_src):
|
||||||
|
for option in ("--add-module=", "--add-dynamic-module="):
|
||||||
|
if not arg.startswith(option):
|
||||||
|
continue
|
||||||
|
|
||||||
|
module_path = arg[len(option) :]
|
||||||
|
if os.path.exists(module_path):
|
||||||
|
return arg
|
||||||
|
|
||||||
|
marker = "/debian/modules/"
|
||||||
|
if marker in module_path:
|
||||||
|
suffix = module_path.split(marker, 1)[1]
|
||||||
|
candidate = os.path.join(nginx_src, "debian", "modules", suffix)
|
||||||
|
if os.path.exists(candidate):
|
||||||
|
return option + candidate
|
||||||
|
|
||||||
|
marker = "/debian/"
|
||||||
|
if marker in module_path:
|
||||||
|
suffix = module_path.split(marker, 1)[1]
|
||||||
|
candidate = os.path.join(nginx_src, "debian", suffix)
|
||||||
|
if os.path.exists(candidate):
|
||||||
|
return option + candidate
|
||||||
|
|
||||||
|
return arg
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_configure_args(args, nginx_src):
|
||||||
|
if not nginx_src:
|
||||||
|
return args
|
||||||
|
|
||||||
|
return [rewrite_module_path(arg, nginx_src) for arg in args]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--nginx-bin", default="nginx")
|
||||||
|
parser.add_argument("--nginx-src", default="")
|
||||||
|
parser.add_argument("--json", action="store_true")
|
||||||
|
parser.add_argument("--configure-line", action="store_true")
|
||||||
|
parser.add_argument("--modules-path", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
output = nginx_v_output(args.nginx_bin)
|
||||||
|
version, configure_line, configure_args = parse_nginx_v(output)
|
||||||
|
rewritten_args = rewrite_configure_args(configure_args, args.nginx_src)
|
||||||
|
|
||||||
|
modules_path = option_value(configure_args, "--modules-path")
|
||||||
|
if not modules_path:
|
||||||
|
prefix = option_value(configure_args, "--prefix") or "/usr/share/nginx"
|
||||||
|
modules_path = os.path.join(prefix, "modules")
|
||||||
|
|
||||||
|
if args.configure_line:
|
||||||
|
print(shlex.join(rewritten_args))
|
||||||
|
return
|
||||||
|
|
||||||
|
if args.modules_path:
|
||||||
|
print(modules_path)
|
||||||
|
return
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"version": version,
|
||||||
|
"configure_line": configure_line,
|
||||||
|
"configure_args": configure_args,
|
||||||
|
"rewritten_configure_args": rewritten_args,
|
||||||
|
"modules_path": modules_path,
|
||||||
|
},
|
||||||
|
sys.stdout,
|
||||||
|
indent=2,
|
||||||
|
sort_keys=True,
|
||||||
|
)
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
parser.error("choose one of --json, --configure-line, or --modules-path")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -9,7 +9,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define NGX_HTTP_MONITORING_VERSION 1
|
#define NGX_HTTP_MONITORING_VERSION 1
|
||||||
#define NGX_HTTP_MONITORING_MODULE_VERSION "1.0.0"
|
|
||||||
|
#ifndef NGX_HTTP_MONITORING_MODULE_VERSION
|
||||||
|
#define NGX_HTTP_MONITORING_MODULE_VERSION "0.0.0-dev"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NGX_HTTP_MONITORING_BUILD_METADATA
|
||||||
|
#define NGX_HTTP_MONITORING_BUILD_METADATA "source"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NGX_HTTP_MONITORING_DEFAULT_SHM_SIZE (8 * 1024 * 1024)
|
#define NGX_HTTP_MONITORING_DEFAULT_SHM_SIZE (8 * 1024 * 1024)
|
||||||
#define NGX_HTTP_MONITORING_MIN_INTERVAL 100
|
#define NGX_HTTP_MONITORING_MIN_INTERVAL 100
|
||||||
|
|||||||
@@ -411,10 +411,11 @@ ngx_http_monitoring_json_header(ngx_http_monitoring_json_writer_t *jw,
|
|||||||
tp = ngx_timeofday();
|
tp = ngx_timeofday();
|
||||||
|
|
||||||
ngx_http_monitoring_json_printf(jw,
|
ngx_http_monitoring_json_printf(jw,
|
||||||
"{\"version\":%d,\"module\":\"%s\",\"timestamp\":%T,"
|
"{\"version\":%d,\"module\":\"%s\",\"build\":\"%s\","
|
||||||
"\"msec\":%M,\"scope\":\"%s\",\"pid\":%P",
|
"\"timestamp\":%T,\"msec\":%M,\"scope\":\"%s\",\"pid\":%P",
|
||||||
NGX_HTTP_MONITORING_VERSION,
|
NGX_HTTP_MONITORING_VERSION,
|
||||||
NGX_HTTP_MONITORING_MODULE_VERSION,
|
NGX_HTTP_MONITORING_MODULE_VERSION,
|
||||||
|
NGX_HTTP_MONITORING_BUILD_METADATA,
|
||||||
tp->sec, tp->msec, scope, ngx_pid);
|
tp->sec, tp->msec, scope, ngx_pid);
|
||||||
|
|
||||||
(void) r;
|
(void) r;
|
||||||
|
|||||||
Reference in New Issue
Block a user