diff --git a/.github/test-env/module-acme.sh b/.github/test-env/module-acme.sh new file mode 100755 index 00000000..ad6be6c0 --- /dev/null +++ b/.github/test-env/module-acme.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +PEBBLE=$(find "$GITHUB_WORKSPACE" -path "*/nginx-acme-*/build/get-pebble.pl" -type f 2>/dev/null | head -1) +[ -n "$PEBBLE" ] && echo "TEST_NGINX_PEBBLE_BINARY=$(perl "$PEBBLE")" >> "$GITHUB_ENV" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee3e6bd3..93c5ecf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: for target in $(make list-all-modules | cut -d ' ' -f 1); do targets="$targets module-$target"; done - echo targets="base $targets" >> $GITHUB_ENV + echo targets="$targets" >> $GITHUB_ENV - name: set-matrix id: set-matrix @@ -38,8 +38,58 @@ jobs: jq -nRr '"matrix-" + $os +"=" + ( { include: [ $ARGS.positional[] | {target: . } ] } | tojson)' --arg os $os --args ${targets/ module-geoip/} >> $GITHUB_OUTPUT done - alpine: + alpine-base: + runs-on: ubuntu-24.04 + container: alpine:3.24 + defaults: + run: + shell: sh -e {0} needs: generate-matrix + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Setup Alpine Linux + run: | + apk add \ + abuild \ + build-base \ + coreutils \ + curl \ + findutils \ + git \ + make \ + xz + printf "#!/bin/sh\\nSETFATTR=true /usr/bin/abuild -F \"\$@\"\\n" > /usr/local/bin/abuild + chmod +x /usr/local/bin/abuild + + - name: Create build depends for base + working-directory: alpine + run: | + make abuild-base + + - name: Install build depends for base + working-directory: alpine + run: | + apk add $(. ./abuild-base/APKBUILD; echo $makedepends;) + + - name: Build base + working-directory: alpine + run: | + make base + + - name: Upload nginx binary + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: nginx-binary-alpine + path: alpine/base/nginx + + - name: List what has been built + if: ${{ !cancelled() }} + run: | + find ~/packages/alpine -type f | xargs ls -ld + + alpine: + needs: [generate-matrix, alpine-base] runs-on: ubuntu-24.04 container: alpine:3.24 defaults: @@ -63,12 +113,26 @@ jobs: findutils \ git \ make \ + perl \ + perl-io-socket-ssl \ + perl-io-socket-inet6 \ + perl-utils \ + perl-cryptx \ + perl-dev \ + perl-fcgi \ + perl-parse-recdescent \ + perl-protocol-websocket \ rustup \ - xz + xz \ + krb5-server \ + krb5 \ + krb5-dev \ + perl-gssapi printf "#!/bin/sh\\nSETFATTR=true /usr/bin/abuild -F \"\$@\"\\n" > /usr/local/bin/abuild chmod +x /usr/local/bin/abuild - name: Install Rust toolchain + if: matrix.target == 'module-acme' uses: actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606 #v1 with: toolchain: 1.86.0 @@ -88,14 +152,74 @@ jobs: run: | make ${{ matrix.target }} + - name: Download nginx binary + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: nginx-binary-alpine + path: alpine/base + + - name: Setup test environment for ${{ matrix.target }} + run: | + SETUP="$GITHUB_WORKSPACE/.github/test-env/${{ matrix.target }}.sh" + if [ -f "$SETUP" ]; then bash "$SETUP"; fi + + - name: Test ${{ matrix.target }} + env: + TEST_NGINX_BINARY: "${{ github.workspace }}/alpine/base/nginx" + TEST_NGINX_GLOBALS: "user root;" + working-directory: alpine + run: | + MODULE=${{ matrix.target }} + MODULE=${MODULE#module-} + chmod +x "$TEST_NGINX_BINARY" + make test TEST_MODULES=${MODULE} + - name: List what has been built if: ${{ !cancelled() }} run: | find ~/packages/alpine -type f | xargs ls -ld - ubuntu: + ubuntu-base: runs-on: ubuntu-24.04 needs: generate-matrix + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Setup Ubuntu + run: | + sudo apt-get update + sudo apt-get install -y --no-install-suggests --no-install-recommends \ + curl \ + devscripts \ + equivs \ + git \ + libxml2-utils \ + lsb-release \ + xsltproc + + - name: Build base + working-directory: debian + run: | + NGINX_VERSION=$(make --eval 'nv:; @echo $(BASE_VERSION)' nv) + make rules-base + sudo mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" \ + debuild-base/nginx-${NGINX_VERSION}/debian/control + make base + + - name: Upload nginx binary + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: nginx-binary-ubuntu + path: debian/base/nginx + + - name: List what has been built + if: ${{ !cancelled() }} + run: | + find .. -mindepth 1 -maxdepth 1 -name "*.deb" | xargs ls -ld + + ubuntu: + runs-on: ubuntu-24.04 + needs: [generate-matrix, ubuntu-base] strategy: fail-fast: false matrix: ${{fromJson(needs.generate-matrix.outputs.matrix-ubuntu)}} @@ -111,11 +235,19 @@ jobs: devscripts \ equivs \ git \ + libio-socket-ssl-perl \ + libio-socket-inet6-perl \ libxml2-utils \ lsb-release \ - xsltproc + xsltproc \ + krb5-kdc \ + krb5-admin-server \ + krb5-user \ + libkrb5-dev \ + libgssapi-perl - name: Install Rust toolchain + if: matrix.target == 'module-acme' uses: actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606 #v1 with: toolchain: 1.86.0 @@ -129,15 +261,79 @@ jobs: debuild-${{ matrix.target }}/nginx-${NGINX_VERSION}/debian/control make ${{ matrix.target }} + - name: Download nginx binary + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: nginx-binary-ubuntu + path: debian/base + + - name: Setup test environment for ${{ matrix.target }} + run: | + SETUP="$GITHUB_WORKSPACE/.github/test-env/${{ matrix.target }}.sh" + if [ -f "$SETUP" ]; then bash "$SETUP"; fi + + - name: Test ${{ matrix.target }} + env: + TEST_NGINX_BINARY: "${{ github.workspace }}/debian/base/nginx" + working-directory: debian + run: | + MODULE=${{ matrix.target }} + MODULE=${MODULE#module-} + chmod +x "$TEST_NGINX_BINARY" + make test TEST_MODULES=${MODULE} + - name: List what has been built if: ${{ !cancelled() }} run: | find .. -mindepth 1 -maxdepth 1 -name "*.deb" | xargs ls -ld - redhat: - needs: generate-matrix + redhat-base: runs-on: ubuntu-24.04 + needs: generate-matrix container: almalinux:9 + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Setup AlmaLinux + run: | + dnf makecache + dnf install -y \ + g++ \ + gcc \ + git \ + epel-release \ + libxslt \ + make \ + rpm-build \ + which \ + xz \ + 'dnf-command(config-manager)' + dnf config-manager --set-enabled crb + + - name: Build base + working-directory: rpm/SPECS + run: | + make nginx.spec + dnf -y builddep ./nginx.spec + make base + + - name: Upload nginx binary + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: nginx-binary-redhat + path: rpm/SPECS/base/nginx + + - name: List what has been built + if: ${{ !cancelled() }} + run: | + find rpm/RPMS -type f | xargs ls -ld + + redhat: + needs: [generate-matrix, redhat-base] + runs-on: ubuntu-24.04 + container: + image: almalinux:9 + options: --init strategy: fail-fast: false matrix: ${{fromJson(needs.generate-matrix.outputs.matrix-redhat )}} @@ -148,20 +344,33 @@ jobs: - name: Setup AlmaLinux run: | dnf makecache + dnf install -y epel-release 'dnf-command(config-manager)' + dnf config-manager --set-enabled crb dnf install -y \ g++ \ gcc \ git \ - epel-release \ libxslt \ make \ + perl \ + perl-Digest-MD5 \ + perl-ExtUtils-Embed \ + perl-IO-Compress \ + perl-IO-Socket-INET6 \ + perl-IO-Socket-SSL \ + perl-JSON \ + perl-JSON-PP \ + perl-Test-Simple \ rpm-build \ which \ xz \ - 'dnf-command(config-manager)' - dnf config-manager --set-enabled crb + krb5-server \ + krb5-workstation \ + krb5-devel \ + perl-GSSAPI - name: Install Rust toolchain + if: matrix.target == 'module-acme' uses: actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606 #v1 with: toolchain: 1.86.0 @@ -169,18 +378,32 @@ jobs: - name: Create and install build depends for ${{ matrix.target }} and build it working-directory: rpm/SPECS run: | - case ${{ matrix.target }} in - base) - spec="nginx.spec" - ;; - *) - spec="nginx-${{ matrix.target }}.spec" - ;; - esac - make $spec - dnf -y builddep ./${spec} + make nginx-${{ matrix.target }}.spec + dnf -y builddep ./nginx-${{ matrix.target }}.spec make ${{ matrix.target }} + - name: Download nginx binary + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: nginx-binary-redhat + path: rpm/SPECS/base + + - name: Setup test environment for ${{ matrix.target }} + run: | + SETUP="$GITHUB_WORKSPACE/.github/test-env/${{ matrix.target }}.sh" + if [ -f "$SETUP" ]; then bash "$SETUP"; fi + + - name: Test ${{ matrix.target }} + env: + TEST_NGINX_BINARY: "${{ github.workspace }}/rpm/SPECS/base/nginx" + TEST_NGINX_GLOBALS: "user root;" + working-directory: rpm/SPECS + run: | + MODULE=${{ matrix.target }} + MODULE=${MODULE#module-} + chmod +x "$TEST_NGINX_BINARY" + make test TEST_MODULES=${MODULE} + - name: List what has been built if: ${{ !cancelled() }} run: | diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..0b77d1f6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,990 @@ +# AGENTS.md — pkg-oss + +This file provides guidance for AI agents working in this repository. It covers +the project structure, build system, conventions, and step-by-step workflows for +the most common minor-change tasks. + +--- + +## Table of Contents + +1. [Project Overview](#1-project-overview) +2. [Repository Layout](#2-repository-layout) +3. [Branches](#3-branches) +4. [Build System — Four Makefile Layers](#4-build-system--four-makefile-layers) +5. [Platform Build Quick Reference](#5-platform-build-quick-reference) +6. [Template System — The `.in` Convention](#6-template-system--the-in-convention) +7. [Contrib Source Management](#7-contrib-source-management) +8. [Module Makefile Variable Reference](#8-module-makefile-variable-reference) +9. [Adding a New Module](#9-adding-a-new-module) +10. [Updating a Module or Dependency Version](#10-updating-a-module-or-dependency-version) +11. [Testing](#11-testing) +12. [CI Testing Architecture](#12-ci-testing-architecture) +13. [Platform Compatibility and Skip Files](#13-platform-compatibility-and-skip-files) +14. [OSS vs Plus Dual-mode](#14-oss-vs-plus-dual-mode) +15. [Changelog and Documentation](#15-changelog-and-documentation) +16. [build_module.sh — Packaging 3rd-party Modules](#16-build_modulesh--packaging-3rd-party-modules) +17. [Supply-chain and Attestation](#17-supply-chain-and-attestation) +18. [Commit and PR Conventions](#18-commit-and-pr-conventions) +19. [Key Gotchas](#19-key-gotchas) + +--- + +## 1. Project Overview + +`pkg-oss` is the official NGINX Open Source packaging repository. It is the +single source of truth for producing installable binary packages of NGINX and +its dynamic modules across all supported Linux distributions. + +**What it produces:** +- `.apk` packages for Alpine Linux +- `.deb` packages for Debian and Ubuntu +- `.rpm` packages for RHEL, CentOS, Fedora, Amazon Linux, and SLES + +**What it does NOT contain:** compiled application source code. The entire repo +is build infrastructure — GNU Make, POSIX shell, XML, and XSLT. + +**Supported targets:** +- NGINX OSS (open source) — default +- NGINX Plus (commercial) — via `BASE_TARGET=plus` + +**Currently pinned versions** (in `contrib/src/nginx/version` and +`contrib/src/njs/version`): +- NGINX `1.31.3` (mainline) +- NGINX Plus `37.0.0` +- NJS `1.0.0` + +**Module categories:** + +| Category | Modules | +|---|---| +| Bundled/base | `acme`, `geoip`, `image-filter`, `njs`, `otel`, `perl`, `xslt` | +| External/3rd-party | `auth-spnego`, `brotli`, `encrypted-session`, `fips-check`, `geoip2`, `headers-more`, `lua`, `ndk`, `passenger`, `rtmp`, `set-misc`, `subs-filter` | + +--- + +## 2. Repository Layout + +``` +pkg-oss/ +├── Makefile # Release management (version bumps, tagging) +├── build_module.sh # Standalone helper to package 3rd-party modules +├── .github/ +│ ├── workflows/ci.yml # CI pipeline +│ └── test-env/ # Per-module test environment setup scripts +│ └── module-.sh # Sourced by CI before the module's test step +├── alpine/ # Alpine Linux (.apk) packaging +│ ├── Makefile # Platform build driver +│ ├── Makefile.module-* # Per-module variable definitions +│ ├── alpine/ # APKBUILD templates (.in files), init scripts, nginx.conf +│ └── alpine-plus/ # NGINX Plus APKBUILD template +├── debian/ # Debian/Ubuntu (.deb) packaging +│ ├── Makefile # Platform build driver +│ ├── Makefile.module-* # Per-module variable definitions +│ ├── debian/ # Debian packaging templates (.in files), service files +│ └── debian-plus/ # NGINX Plus control template +├── rpm/ +│ ├── SPECS/ # RPM (.rpm) packaging +│ │ ├── Makefile # Platform build driver +│ │ ├── Makefile.module-* # Per-module variable definitions +│ │ ├── nginx.spec.in # Base NGINX spec template +│ │ ├── nginx-module.spec.in # OSS module spec template +│ │ └── nginx-plus-module.spec.in # Plus module spec template +│ └── SOURCES/ # Static files embedded in RPMs (nginx.conf, systemd units, etc.) +├── contrib/ # Upstream source dependency management +│ ├── Makefile # Download/verify/unpack orchestrator +│ ├── attestation.mak # Supply-chain attestation helpers +│ ├── src// # Per-dependency: version, SHA512SUMS, Makefile +│ └── tarballs/ # Downloaded archives land here (git-ignored) +└── docs/ # XML changelogs and XSLT transformation tooling + ├── *.xml # Canonical changelog per package + ├── *.copyright # Copyright text embedded into packages + ├── changes.dtd # DTD for the XML changelog format + ├── changes.xslt / .xsls # XSLT stylesheet for changelog generation + └── Makefile # Drives xsltproc transformations +``` + +--- + +## 3. Branches + +| Branch | Purpose | +|---|---| +| `master` | Current mainline packages (`FLAVOR=mainline`) | +| `stable-*` | Stable release packages (`FLAVOR=stable`) | + +The root `Makefile` auto-detects the flavor from the branch name: any branch +containing the word `stable` sets `FLAVOR=stable`; everything else is `mainline`. +Do not manually override this. + +--- + +## 4. Build System — Four Makefile Layers + +### Layer 1 — Root `Makefile` (release management) + +Handles version bumps, SHA512 appending, changelog injection, and Git tagging. +Agents performing minor changes (module updates, dep bumps) generally do not +need to invoke the root `Makefile` directly. The relevant targets are: + +| Target | Purpose | +|---|---| +| `make release` | Bump `NGINX_VERSION`, update SHA512SUMS, inject changelog entries | +| `make release-njs` | Same workflow for the NJS module | +| `make revert / commit / tag` | Git workflow helpers | + +### Layer 2 — `contrib/Makefile` (source acquisition) + +Downloads, checksums, and unpacks all upstream source tarballs. Sources are +fetched from `https://packages.nginx.org/contrib` with fallback to the original +upstream URL. + +| Target | Purpose | +|---|---| +| `make fetch` | Download and verify checksums for all packages | +| `make install` | Download, verify, and unpack all packages | +| `make list` | Print all known package names | +| `make clean` | Remove downloaded tarballs and unpacked trees | + +Run these from the `contrib/` directory. + +**Verbose output:** `tar` and `unzip` are quiet by default during unpack. Set +`V=1` to restore full output: + +```sh +V=1 make install +``` + +### Layer 3 — Platform Makefiles (package builds) + +One each in `alpine/`, `debian/`, `rpm/SPECS/`. All three follow the same +structure and expose the same targets. Run from the respective directory. + +### Layer 4 — `docs/Makefile` (changelog pipeline) + +Transforms `docs/*.xml` source via `xsltproc` into `.rpm-changelog` and +`.deb-changelog` files that are embedded into packages during builds. + +| Target | Purpose | +|---|---| +| `make changes` | Generate all changelog files | +| `make changelogs` | Alias for `make changes` | + +Run from the `docs/` directory. + +--- + +## 5. Platform Build Quick Reference + +The following targets work identically in `alpine/`, `debian/`, and +`rpm/SPECS/`: + +```sh +# Build the NGINX base package +make base + +# Build a specific module package +make module- + +# Build base + all bundled base modules +make all + +# Build all modules including external +make all-modules + +# Run the full test suite: core nginx-tests plus the suite of every built module +make test + +# Same, against the nginx-debug binary and the debug .so files +make test-debug + +# Narrow a run down to specific modules or files +make test TEST_MODULES=. # core suite only +make test TEST_MODULES= # a single module suite +make test TEST_MODULES=/some.t # a single test file + +# Check that built .so files have no embedded RPATHs +make check-modules + +# Check/generate platform compatibility skip files +make check-compat- + +# List all modules known to the platform Makefile +make list-all-modules +``` + +**NGINX Plus mode** — prefix any target with `BASE_TARGET=plus`: + +```sh +BASE_TARGET=plus make module-njs +``` + +--- + +## 6. Template System — The `.in` Convention + +> **Never edit generated files.** All final packaging files (APKBUILD, +> `debian/control`, `debian/rules`, `.spec`) are produced by `sed` substitution +> from `.in` templates. Edits to generated files are silently overwritten on the +> next build. + +Templates use double-percent delimited tokens: + +``` +%%VERSION%% %%CODENAME%% %%MODULE_CONFIGURE_ARGS%% %%PACKAGE_VENDOR%% +``` + +Template locations: + +| Platform | Templates | +|---|---| +| Alpine | `alpine/alpine/APKBUILD-base.in`, `alpine/alpine/APKBUILD-module.in` | +| Debian | `debian/debian/*.control.in`, `debian/debian/*.rules.in`, `debian/debian/*.postinst.in` | +| RPM | `rpm/SPECS/nginx.spec.in`, `rpm/SPECS/nginx-module.spec.in`, `rpm/SPECS/nginx-plus-module.spec.in` | + +If a packaging change is needed (e.g. adding a new `BuildRequires`, changing a +`Replaces:` tag), edit the `.in` template, not any generated file. + +--- + +## 7. Contrib Source Management + +Every upstream dependency has its own subdirectory under `contrib/src/`: + +``` +contrib/src// +├── version # Defines DEP_VERSION := x.y.z (and optionally DEP_GITHASH) +├── SHA512SUMS # One "hash filename" line per historical tarball (append-only) +└── Makefile # Download and unpack rules +``` + +The `SHA512SUMS` file is **append-only** — keep all historical entries so that +older pkg-oss checkouts can still verify their tarballs. Never delete existing +lines. + +### Adding a new dependency + +1. Create `contrib/src//` with the three files above. +2. Add a `PKGS += ` line and a download target in the new `Makefile`. +3. Compute the SHA512: `sha512sum ` and add the line to `SHA512SUMS`. +4. Verify: `make fetch` from `contrib/` (downloads and checks the checksum). + +### Updating a dependency version + +1. Edit `contrib/src//version` — update `DEP_VERSION`. +2. Compute the new tarball SHA512 and **append** it to `contrib/src//SHA512SUMS`. +3. Run `make fetch` from `contrib/` to download and verify. +4. Update `MODULE_VERSION_` and `MODULE_SOURCES_` in all three platform + `Makefile.module-` files (see [§8](#8-module-makefile-variable-reference)). + +### Git-sourced dependencies + +Some deps (e.g. `ngx_brotli`, `luajit2`) are fetched from Git refs rather than +tarballs. Their `Makefile` uses the `download_git` helper, which creates a +reproducible `.tar.xz` archive and records the commit hash in a `.githash` +sidecar file. When updating these, provide the new Git ref and update `version` +with the new commit hash as `DEP_GITHASH`. + +--- + +## 8. Module Makefile Variable Reference + +Each `Makefile.module-` file defines a set of namespaced Make variables. +The `` suffix below stands for the module nickname (e.g. `njs`, `brotli`). + +### Common variables (all three platforms) + +| Variable | Required | Description | +|---|---|---| +| `MODULES += ` | yes | Registers the module with the platform Makefile | +| `MODULE_SUMMARY_` | yes | One-line human description (used in package metadata) | +| `MODULE_VERSION_` | yes | Module version string, usually `$(DEP_VERSION)` | +| `MODULE_RELEASE_` | yes | Package release number; reset to `1` on each new upstream version | +| `MODULE_SOURCES_` | yes | Space-separated list of source tarball filenames from `contrib/tarballs/` | +| `MODULE_CONFARGS_` | yes | `--add-dynamic-module=` argument(s) passed to nginx `./configure` | +| `MODULE_CONTRIB_DEPS_` | if needed | Space-separated contrib dep names; their `version` files are auto-included | +| `MODULE_VERSION_PREFIX_` | yes | Set to `$(MODULE_TARGET_PREFIX)` for standard version epoch | +| `MODULE_PATCHES_` | if needed | Space-separated list of patch file paths to apply to sources | +| `MODULE_CC_OPT_` | if needed | Extra `-I` / compiler flags for the module build | +| `MODULE_LD_OPT_` | if needed | Extra `-L` / linker flags for the module build | +| `MODULE_CC_OPT_DEBUG_` | if needed | Same as above but for the `nginx-debug` build | +| `MODULE_LD_OPT_DEBUG_` | if needed | Same as above but for the `nginx-debug` build | +| `MODULE_PREBUILD_` | if needed | `define … endef` shell block run before nginx configure (e.g. build a dependency library) | +| `MODULE_PREINSTALL_` | if needed | `define … endef` shell block run before package install step (e.g. install extra binaries/docs) | +| `MODULE_POST_` | yes | `define … endef` block that prints the post-install banner (`load_module` instructions) | + +### Platform-specific variables + +**Alpine only:** + +| Variable | Description | +|---|---| +| `MODULE_BUILD_DEPENDS_` | Space-separated list of Alpine `apk` packages required at build time | +| `MODULE_ADD_CONTROL_TAGS_` | Extra APKBUILD tags (e.g. `replaces="nginx-mod-http-js"`) | + +**Debian only:** + +| Variable | Description | +|---|---| +| `MODULE_BUILD_DEPENDS_` | Comma-prefixed list of Debian packages required at build time (e.g. `,libedit-dev,libxml2-dev`) | +| `MODULE_ADD_CONTROL_TAGS_` | Extra `debian/control` stanza entries | + +**RPM only:** + +| Variable | Description | +|---|---| +| `MODULE_DEFINITIONS_` | `define … endef` block for raw spec preamble content (typically `BuildRequires:` lines with conditional RPM macros) | +| `MODULE_FILES_` | `define … endef` block listing additional files for the spec `%files` section (e.g. `%{_bindir}/njs`) | + +### Example — minimal module Makefile + +```make +MODULES+= mymodule + +MODULE_SUMMARY_mymodule= mymodule dynamic module + +MODULE_CONTRIB_DEPS_mymodule= mymodule-src + +include $(foreach dep,$(MODULE_CONTRIB_DEPS_mymodule),$(CONTRIB)/src/$(dep)/version) + +MODULE_VERSION_mymodule= $(MYMODULE_SRC_VERSION) +MODULE_RELEASE_mymodule= 1 + +MODULE_SOURCES_mymodule= mymodule-src-$(MYMODULE_SRC_VERSION).tar.gz + +MODULE_CONFARGS_mymodule= --add-dynamic-module=$(MODSRC_PREFIX)mymodule-src-$(MYMODULE_SRC_VERSION) + +MODULE_VERSION_PREFIX_mymodule=$(MODULE_TARGET_PREFIX) + +define MODULE_POST_mymodule +cat </version # e.g. MYMODULE_VERSION := 1.2.3 +contrib/src//SHA512SUMS # sha512sum output for the tarball +contrib/src//Makefile # download/unpack rules +``` + +Run `make fetch` from `contrib/` to verify the checksum. + +### Step 2 — Create `Makefile.module-` in all three platform directories + +The file must be created in all three locations: +- `alpine/Makefile.module-` +- `debian/Makefile.module-` +- `rpm/SPECS/Makefile.module-` + +The variable set is largely identical across platforms; see +[§8](#8-module-makefile-variable-reference) for platform differences. + +### Step 3 — Add changelog and copyright stubs + +Create two files in `docs/`: + +**`docs/nginx-module-.xml`:** +```xml + + + + + + + + + +initial release of nginx-module- + + + + + + +``` + +**`docs/nginx-module-.copyright`:** +``` +Copyright and license text for nginx-module-. +``` + +### Step 4 — Verify the build + +```sh +# From the target platform directory, e.g.: +cd debian +make module- +``` + +--- + +## 10. Updating a Module or Dependency Version + +### Updating a contrib dependency + +1. Edit `contrib/src//version` — change `DEP_VERSION`. +2. Obtain the new tarball SHA512: + ```sh + sha512sum + ``` +3. **Append** the new line to `contrib/src//SHA512SUMS`. Do not remove + existing lines. +4. Verify: `make fetch` from `contrib/`. + +### Updating module version in all platform Makefiles + +For each of `alpine/Makefile.module-`, `debian/Makefile.module-`, +`rpm/SPECS/Makefile.module-`: + +1. Update `MODULE_VERSION_` (or the contrib version variable it references). +2. Update `MODULE_SOURCES_` filenames to match the new version. +3. If this is a new upstream release (not just a packaging fix), reset + `MODULE_RELEASE_` back to `1`. Increment `MODULE_RELEASE_` only for + packaging-only changes that do not change the upstream version. + +### Updating the changelog + +Append a new `` block to `docs/nginx-module-.xml`: + +```xml + + + + +upgraded to version X.Y.Z + + + + +``` + +Always append; never edit or remove existing `` blocks. + +--- + +## 11. Testing + +Tests use the official [nginx-tests](https://github.com/nginx/nginx-tests) Perl TAP +suite, run via `prove`. The test suite source is cloned via +`contrib/src/nginx-tests`. + +Third-party modules whose upstream suite is written for OpenResty's +`Test::Nginx::Socket` DSL are not used directly. Instead they are converted to +the nginx-tests framework and live in a separate repository, +[pkg-oss-tests](https://github.com/nginx/pkg-oss-tests), cloned via +`contrib/src/pkg-oss-tests` with one `/t/` directory per module. That +repo has its own `AGENTS.md` describing the conversion rules. Nothing from +OpenResty is required at runtime — the converted suites use nginx-tests' +own `lib/Test/Nginx.pm`. + +Both checkouts are fetched and copied into the platform directory by a single +shared rule, so `nginx-tests/` and `pkg-oss-tests/` are local working copies: + +```make +nginx-tests pkg-oss-tests: + @{ \ + if [ ! -d "$(CONTRIB)/tarballs/$@" ]; then \ + cd $(CONTRIB) && make .sum-$@ ; \ + fi ; \ + cp -rP $(CONTRIB)/tarballs/$@ $@ ; \ + } +``` + +### Test targets + +Run from the platform directory (`alpine/`, `debian/`, or `rpm/SPECS/`): + +| Target | What it runs | +|---|---| +| `make test` | Core nginx-tests suite plus the suite of every built module, against the release binary | +| `make test-debug` | Same, against `nginx-debug` and the debug `.so` files | + +These two are the **only** test entry points, and behave identically on all +three platforms. There is no `test-module-` target — use +`make test TEST_MODULES=`. + +`test` and `test-debug` share a single recipe, distinguished at runtime by +`case "$@" in *-debug)`, which sets the binary (`nginx` / `nginx-debug`) and the +`.so` suffix. For each module that has been built (`module-/` exists) and has +a test suite, the recipe stages it into `nginx-tests/module-/` and hands the +directory to the same `prove` invocation that runs the core suite. `prove` is +not recursive, so `.` picks up the core tests exactly once and each +`module-` directory exactly once. + +Staging always runs, regardless of `TEST_MODULES`. That ordering matters: a CI +job does a fresh checkout and then calls `make test TEST_MODULES=` as its +only test invocation, so if staging were skipped when `TEST_MODULES` is set, +`nginx-tests/module-/` would never be created and the run would silently +pass without executing anything. + +### Narrowing a run — `TEST_MODULES` + +`TEST_MODULES` filters what's passed to `prove` **after** staging, by bare +module name — not the `nginx-tests/`-relative directory name. It defaults to +the core suite plus every staged module. The one non-module value is `.`, +which selects the core suite; there is no other way to express "core only". + +```sh +make test # core suite + all built module suites +make test TEST_MODULES=. # core suite only +make test TEST_MODULES=set-misc # one module suite +make test TEST_MODULES=lua/socket.t # one test file +make test TEST_MODULES="set-misc lua" # several modules +``` + +Internally each value is prefixed with `module-` before being checked against +`nginx-tests/` (`set-misc` → `module-set-misc`, `lua/socket.t` → +`module-lua/socket.t`), except `.`, which is passed through unchanged. + +Values that were never staged (a module with no test suite, or one that is not +built) are dropped with a notice; if nothing remains the target exits 0. That is +what lets the CI matrix run `make test TEST_MODULES=` uniformly for every +module, including the ones that ship no tests. + +### Environment variables + +| Variable | Purpose | +|---|---| +| `TEST_NGINX_BINARY` | Path to the nginx binary under test | +| `TEST_NGINX_GLOBALS` | Directives prepended to `nginx.conf`; the Makefile **appends** the generated `load_module` directives to whatever is already in this variable | +| `TEST_NGINX_GLOBALS_HTTP` | Directives injected into the `http {}` block | +| `TEST_NGINX_GLOBALS_STREAM` | Directives injected into the `stream {}` block | +| `TEST_NGINX_PEBBLE_BINARY` | Path to the Pebble ACME test server binary. **Optional** — the acme suite calls `has_daemon($PEBBLE)`, so it skips itself when the variable is unset and `pebble` is not in `PATH` | +| `PROVE_ARGS` | Extra arguments for `prove` (e.g. `-v`, `-j4`) | + +**Skip conditions belong in the suite, not in the Makefile.** nginx-tests +already owns that vocabulary — `has_daemon`, `has`, `try_run`, +`plan(skip_all => ...)`, and guarded `eval { require ... }` — and the +pkg-oss-tests conversion rules require every suite to be self-contained in this +respect. Do not add per-module skip logic to the platform Makefiles; a suite +that needs an external daemon or CPAN module must guard itself so that a plain +`make test` degrades to a skip rather than a failure. + +### Where a module's tests come from + +A module's test directory is not declared per-module. It is resolved by the +platform driver, by convention, relative to the staged local copy: + +``` +pkg-oss-tests//t +``` + +If that directory does not exist, the module simply has no suite and is skipped +— that covers `geoip`, `image-filter`, `ndk`, `otel`, `passenger`, `perl` and +`xslt` with no exception list to maintain. Adding a suite for an existing module +therefore requires **no pkg-oss change at all**: create `/t/` in +pkg-oss-tests and it is picked up. + +Two modules maintain their suite upstream in their own source tree and are +handled by explicit `case` arms in each platform driver: + +```sh +acme) testdir=$$pwd//nginx-acme-$(NGINX_ACME_VERSION)/t ;; +njs) testdir=$$pwd//njs-$(NJS_VERSION)/nginx/t ;; +*) testdir=pkg-oss-tests/$$m/t ;; +``` + +They live in the driver rather than in `Makefile.module-` because `` +— where a module's unpacked source lands in the build tree — is platform +knowledge, not module knowledge: + +| platform | `` | +|---|---| +| alpine | `abuild-module-/src` | +| debian | `debuild-module-/$(SRCDIR)/debian/extra` | +| rpm | `module-/..` | + +This is the same category as the `perl` `objs/` path and the `lua` +`lua-resty-*` paths, which are hardcoded in the drivers for the same reason. +A third in-tree suite means adding one `case` arm to each of the three drivers. + +Both `nginx-tests` and `pkg-oss-tests` are prerequisites of `test` / +`test-debug`, so the checkouts are fetched and copied in unconditionally by the +shared rule shown at the top of this section. + +**Do not point a build or test at `$(CONTRIB)/tarballs/nginx-tests` or +`$(CONTRIB)/tarballs/pkg-oss-tests` directly.** Those are shared source clones. +The staging step does `rm -rf nginx-tests/module-` and copies into it, so if +the local `nginx-tests/` is a symlink to the contrib clone (which is what +`cp -rP` produces when `$(CONTRIB)/tarballs/nginx-tests` is itself a symlink), +staging writes *through* it and pollutes the shared clone with stray +`module-*/` directories. If a checkout starts behaving oddly, run +`git clean -fd` inside `contrib/tarballs/nginx-tests`. + +Staging copies the directory to `nginx-tests/module-/`, replacing any +previous copy, and symlinks `lib -> ../lib` unless the suite ships a `lib/` of +its own (`acme` does: `Test::Nginx::ACME`, `Test::Nginx::DNS`). `prove` is +always given `-I/nginx-tests/lib`, so `Test::Nginx` resolves either way. + +**Variable naming convention:** module variable suffixes always use underscores +even when the module nickname contains dashes (e.g. `set-misc` → `set_misc`). +The recipes look these up through `$(call modname, ...)` (which calls +`tr '-' '_'`), so define them with underscores. + +### NDK load order + +`ndk` (`ngx_devel_kit`) is the project's only inter-module load dependency: +`encrypted-session`, `lua`, and `set-misc` compile against it and need +`ndk_http_module.so` loaded before their own `.so`. There is no per-module +declaration for this — the platform driver derives the dependent set from the +same condition that already determines the build: + +```make +NDK_MODULES= $(filter-out ndk,$(foreach m,$(MODULES),$(if $(findstring ngx_devel_kit,$(MODULE_CONFARGS_$(call modname, $(m)))),$(m)))) +``` + +A module is in `NDK_MODULES` if and only if its `MODULE_CONFARGS_` contains +`ngx_devel_kit` — the same fact that makes it delete `objs/ndk_http_module.so` +in its own `MODULE_PREINSTALL_` so the two packages don't collide. This +derivation cannot drift out of sync with the build the way a hand-maintained +list could. + +It drives two things in `test` / `test-debug`: when any module in +`NDK_MODULES` is built but `module-ndk/` is not, `make module-ndk` runs first; +and the `load_module` loop always emits `ndk` ahead of every other module +(`for m in ndk $(filter-out ndk,$(MODULES))`), not a plain sort — `ndk`'s +module name (`ndk_http_module`) happens to sort before the `ngx_*` dependents +today, but that's a coincidence not a guarantee, so the loop states the order +explicitly instead of relying on it. + +If a future module needs a different inter-module load order, add another +derived variable in this style rather than a per-module test variable. + +--- + +## 12. CI Testing Architecture + +The CI (`github/workflows/ci.yml`) splits each platform into two jobs to avoid +rebuilding nginx once per module: + +| Job | Purpose | +|---|---| +| `alpine-base` / `ubuntu-base` / `redhat-base` | Builds nginx, uploads `base/nginx` as a GitHub Actions artifact | +| `alpine` / `ubuntu` / `redhat` | Module matrix (no `base` entry); downloads artifact; builds and tests modules | + +The module matrix jobs `needs:` their platform's base job, so the artifact is +guaranteed to exist before any module job starts. + +### How Make accepts the downloaded binary + +The artifact is downloaded into `{platform}/base/`. Make sees `base/` already +exists as a directory and considers the `base` target satisfied without +rebuilding. No Makefile changes are required. + +### Per-module test environment — `.github/test-env/` + +Scripts in `.github/test-env/module-.sh` are executed by CI before each +module's test step (`make test TEST_MODULES=`). They write to +`$GITHUB_ENV` to export +module-specific environment variables into the subsequent test step. The script +uses `$GITHUB_WORKSPACE` for path discovery — no platform-specific logic is +needed. + +**To add test setup for a new module:** create +`.github/test-env/module-.sh`. No CI YAML changes are required. + +Example — `module-acme.sh` discovers and activates the Pebble ACME test server: + +```sh +#!/bin/bash +PEBBLE=$(find "$GITHUB_WORKSPACE" -path "*/nginx-acme-*/build/get-pebble.pl" \ + -type f 2>/dev/null | head -1) +[ -n "$PEBBLE" ] && echo "TEST_NGINX_PEBBLE_BINARY=$(perl "$PEBBLE")" >> "$GITHUB_ENV" +``` + +--- + +## 13. Platform Compatibility and Skip Files + +Some modules cannot be built on certain platforms or architectures (e.g. GeoIP +is not available on RHEL ≥ 8; LuaJIT does not support ppc64le/s390x; OTel +requires a newer toolchain than Ubuntu 18.04 or RHEL 7 provide). + +The `check-compat-` target inspects the current OS/distro version and +writes `nginx-module-.skip` when a module must be skipped. The +`make module-` target honours this skip file and exits cleanly. + +**Do not delete `.skip` files manually.** They are regenerated by +`make check-compat-` and exist for a reason. If a module is being enabled +for a new platform, the relevant compatibility check in the platform `Makefile` +must be updated instead. + +--- + +## 14. OSS vs Plus Dual-mode + +All three platform Makefiles support a `BASE_TARGET` variable: + +| Value | Behaviour | +|---|---| +| `oss` (default) | Builds against NGINX Open Source; uses `alpine/alpine/`, `debian/debian/`, standard spec templates | +| `plus` | Builds against NGINX Plus; uses `alpine/alpine-plus/`, `debian/debian-plus/`, Plus spec template; adds EULA and Plus-specific configure flags | + +Usage: + +```sh +BASE_TARGET=plus make module-njs +BASE_TARGET=plus make base +``` + +The `MODULE_TARGET` variable (`oss` / `plus`) controls whether module packages +declare a dependency on `nginx` or `nginx-plus`. It defaults to the same value +as `BASE_TARGET`. + +--- + +## 15. Changelog and Documentation + +### XML changelog format + +`docs/*.xml` is the canonical release history for every package. Each file +contains one or more `` blocks, newest first: + +```xml + + + + + upgraded to njs-1.0.0 + + + + +``` + +Key attributes: +- `apply` — package name (must match the filename stem) +- `ver` — upstream module version +- `rev` — package release number +- `basever` — NGINX version this was built against +- `date` / `time` — release timestamp + +### Generating formatted changelogs + +```sh +make -C docs changes +``` + +This produces `*.rpm-changelog` and `*.deb-changelog` files consumed by the +platform build targets. Run this after editing any `docs/*.xml` file to keep the +generated files current. + +--- + +## 16. `build_module.sh` — Packaging 3rd-party Modules + +`build_module.sh` is a standalone POSIX shell script for packaging arbitrary +3rd-party dynamic modules without modifying this repository. It: + +1. Detects the local package manager (`yum`, `apt-get`, or `apk`) +2. Installs build prerequisites +3. Fetches the module source from a URL or local path +4. Clones this pkg-oss repository +5. Generates a `Makefile.module-` scaffold +6. Calls the appropriate platform `make module-` +7. Copies the finished packages to an output directory + +### Usage + +```sh +./build_module.sh [options] +``` + +### Options + +| Option | Description | +|---|---| +| `-n ` | Module nickname — lowercase alphanumeric only, used in package names | +| `-V ` | Module version string (default: `1.0-1`) | +| `-v []` | Build against this NGINX OSS version (default: current mainline) | +| `-r ` | Build against the OSS version corresponding to this NGINX Plus release (`NN[pN]` or `NN.N[.N]`) | +| `-o ` | Output directory for finished packages (default: `./build-module-artifacts/`) | +| `-y` | Non-interactive — auto-confirm all prompts and overwrite existing files | +| `-f` | Force-convert a static module config to dynamic (experimental) | +| `-s` | Skip dependency installation | + +### Source formats accepted + +- **Git URL** (ending in `.git`): cloned with `git clone --recursive` +- **Zip archive URL**: downloaded and extracted +- **Tarball URL** (any other suffix): downloaded and extracted with `tar` +- **Local directory path**: copied directly + +### Requirements + +- The module source must contain a `config` file that includes `. auto/module` + (dynamic module convention). Use `-f` to attempt auto-conversion if the module + only has a static `config`. +- NGINX version must be ≥ 1.11.5 (dynamic module support). + +### Example + +```sh +# Build the headers-more module against the current mainline +./build_module.sh -n headersmore -y \ + https://github.com/openresty/headers-more-nginx-module/archive/v0.37.tar.gz + +# Build against NGINX Plus R37 +./build_module.sh -n headersmore -r 37 -y \ + https://github.com/openresty/headers-more-nginx-module/archive/v0.37.tar.gz +``` + +Finished packages are placed in `./build-module-artifacts/` (or the path given +with `-o`). + +> **Note:** The script is intended as a demonstration tool. The packages it +> produces are not for redistribution. + +--- + +## 17. Supply-chain and Attestation + +### SHA512 verification + +Every source tarball in `contrib/src//SHA512SUMS` is verified by +`contrib/Makefile` before it is unpacked. The format is standard `sha512sum` +output: + +``` + +``` + +If a checksum is missing or incorrect, the build aborts. Always add the +checksum before pushing a dep update. + +### Attestation artifacts + +`contrib/attestation.mak` provides targets that generate SLSA-style provenance +sidecar files listing each dependency's name, version, commit hash, and SHA512: + +```sh +make attest-base # attestation for the NGINX base package +make attest-module- # attestation for a module +``` + +These are generated as part of the release process and should be regenerated +whenever dependency versions change. + +--- + +## 18. Commit and PR Conventions + +Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/): + +``` +(): + + +``` + +Common types: `feat`, `fix`, `chore`, `docs`, `refactor`, `ci` + +Common scopes: `njs`, `otel`, `brotli`, `debian`, `alpine`, `rpm`, `contrib` + +Rules: +- Subject line ≤ 72 characters +- Present tense, imperative mood ("Add feature" not "Added feature") +- Reference issues and PRs in the commit body +- Squash/rebase locally before submitting a PR; keep the history clean +- Fork the repo, work on a branch, and open a PR when changes are tested + +--- + +## 19. Key Gotchas + +**Always update all three platform Makefile.module files together.** +`alpine/Makefile.module-`, `debian/Makefile.module-`, and +`rpm/SPECS/Makefile.module-` must stay in sync. A version bump in only one +platform will cause divergent package versions across distros. + +**`MODULE_BUILD_DEPENDS` syntax differs by platform.** +- Alpine: space-separated: `MODULE_BUILD_DEPENDS_njs= libedit-dev libxml2-dev` +- Debian: leading comma for each entry: `MODULE_BUILD_DEPENDS_njs= ,libedit-dev,libxml2-dev` + +**Shell inside `define … endef` requires escaped special characters.** +- `$` → `$$` +- `&&` → `\&\&` +- `\` (line continuation in shell) → `\` (single backslash, but watch context) + +**`contrib/tarballs/` is git-ignored and unpopulated in a fresh clone.** +Run `make fetch` or `make install` from `contrib/` before attempting a package +build from source. + +**Never edit generated packaging files.** +Files like `debian/nginx-module-njs/debian/control` or +`rpm/SPECS/nginx-module-njs.spec` are generated outputs. Always edit the +corresponding `.in` template. + +**SHA512SUMS is append-only.** +Remove a line from `contrib/src//SHA512SUMS` only if the corresponding +tarball was never published (i.e. a mistake before any public release). For all +other cases, keep historical entries. + +**`MODULE_RELEASE_` semantics:** +- Reset to `1` when `MODULE_VERSION_` changes (new upstream release). +- Increment (to `2`, `3`, …) for packaging-only fixes that do not change the + upstream module version. + +**The root `Makefile` `make release` is destructive.** +It rewrites version files and injects changelog entries across the whole +repository. Do not run it unless you are performing an intentional version bump +for a release. + +**Platform skip files are authoritative.** +If `nginx-module-.skip` exists in a platform build directory, the module +will not be built there. This is intentional. Fix the underlying compatibility +check in the platform `Makefile` rather than deleting the skip file. + +**`check-compat-%` does not create its own target file.** *(debian and rpm only +— alpine has no compatibility-check or skip-file mechanism at all.)* +The `check-compat-%` recipe writes `.skip` files for incompatible modules but +never creates a file named `check-compat-*`. Because the target file never +exists, Make re-runs the recipe every time it appears as a prerequisite of +`module-%`. When the recipe re-runs after `module-%` was already built, Make +considers `module-%` out of date and triggers a full rebuild. This only affects +`make module-` itself — `make test` has no `module-%` prerequisite, so the +old CI `touch module-${MODULE}` workaround is no longer needed and has been +removed. + +**The test targets are identical on all three platforms.** +`test` and `test-debug` are the only test entry points; there is no +`test-module-%`. They share a single recipe per platform that stages and runs +every built module's suite, narrowable with `TEST_MODULES` (see §11). The three +recipes differ only in the build-tree paths (``, perl `objs/`, lua +`lua-resty-*`), so keep them in sync when changing one. + +**Staging must not be made conditional on `TEST_MODULES`.** +`TEST_MODULES` filters what is handed to `prove`; it must never gate the +staging loop. CI runs `make test TEST_MODULES=` as the only test command +after a fresh checkout, so gating staging on an unset `TEST_MODULES` makes +every per-module CI job exit 0 without running a single test. + +**`contrib/Makefile` tar/unzip output is quiet by default.** +Use `V=1 make install` (or `V=1 make fetch`) to restore verbose tar and unzip +output during source unpacking. diff --git a/alpine/Makefile b/alpine/Makefile index 92a8d57f..43934d1a 100644 --- a/alpine/Makefile +++ b/alpine/Makefile @@ -271,26 +271,47 @@ abuild-module-%: $(BASE_SRC) .deps-module-% fi; \ touch $@ -nginx-tests: +nginx-tests pkg-oss-tests: @{ \ - if [ ! -d "$(CONTRIB)/tarballs/nginx-tests" ]; then \ + if [ ! -d "$(CONTRIB)/tarballs/$@" ]; then \ curdir=`pwd` ; \ - cd $(CONTRIB) && make .sum-nginx-tests ; \ + cd $(CONTRIB) && make .sum-$@ ; \ cd $$curdir ; \ fi ; \ - echo "===> Copying tests from $(CONTRIB)/tarballs/nginx-tests" ; \ - cp -rP $(CONTRIB)/tarballs/nginx-tests nginx-tests ; \ + echo "===> Copying tests from $(CONTRIB)/tarballs/$@" ; \ + cp -rP $(CONTRIB)/tarballs/$@ $@ ; \ } -test: base nginx-tests - @echo "===> Running tests with regular binary/modules" +NDK_MODULES= $(filter-out ndk,$(foreach m,$(MODULES),$(if $(findstring ngx_devel_kit,$(MODULE_CONFARGS_$(call modname, $(m)))),$(m)))) + +test test-debug: base nginx-tests pkg-oss-tests @{ \ + TEST_BIN=nginx ; \ + TEST_SO_SUFFIX= ; \ + case "$@" in \ + *-debug) \ + TEST_BIN="$${TEST_BIN}-debug" \ + TEST_SO_SUFFIX="-debug" \ + ;; \ + esac ; \ + echo "===> Running tests with $$TEST_BIN binary/modules" ; \ pwd=`pwd` ; \ + for m in $(NDK_MODULES); do \ + [ -d module-$$m ] || continue ; \ + [ -d module-ndk ] && break ; \ + echo "===> Building module-ndk, required by module-$$m" ; \ + make module-ndk || exit 1 ; \ + break ; \ + done ; \ globals= ; \ globals_http= ; \ globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + for m in ndk $(filter-out ndk,$(MODULES)); do \ + [ -d module-$$m ] || continue ; \ + for so in module-$$m/*module$${TEST_SO_SUFFIX}.so; do \ + [ -e "$$so" ] || continue ; \ + globals="$$globals load_module $$pwd/$$so;" ; \ + done ; \ done ; \ if [ -d $$pwd/module-perl ]; then \ globals="$$globals env PERL5LIB=$$pwd/abuild-module-perl/src/$(MODULE_SRCDIR)/objs/src/http/modules/perl:$$pwd/abuild-module-perl/src/$(MODULE_SRCDIR)/objs/src/http/modules/perl/blib/arch;" ; \ @@ -299,49 +320,47 @@ test: base nginx-tests globals_http="lua_package_path '$$pwd/abuild-module-lua/src/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/abuild-module-lua/src/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ globals_stream="$$globals_http" ; \ fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-debug: base nginx-tests - @echo "===> Running tests with debug binary/modules" - @{ \ - pwd=`pwd` ; \ - globals= ; \ - globals_http= ; \ - globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module-debug.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + staged_dirs= ; \ + for m in $(MODULES); do \ + [ -d module-$$m ] || continue ; \ + case $$m in \ + acme) testdir=$$pwd/abuild-module-acme/src/nginx-acme-$(NGINX_ACME_VERSION)/t ;; \ + njs) testdir=$$pwd/abuild-module-njs/src/njs-$(NJS_VERSION)/nginx/t ;; \ + *) testdir=pkg-oss-tests/$$m/t ;; \ + esac ; \ + [ -d "$$testdir" ] || continue ; \ + echo "===> Staging module-$$m tests from $$testdir" ; \ + rm -rf nginx-tests/module-$$m ; \ + cp -r "$$testdir" nginx-tests/module-$$m ; \ + [ -e nginx-tests/module-$$m/lib ] || ln -s ../lib nginx-tests/module-$$m/lib ; \ + staged_dirs="$$staged_dirs module-$$m" ; \ done ; \ - if [ -d $$pwd/module-perl ]; then \ - globals="$$globals env PERL5LIB=$$pwd/abuild-module-perl/src/$(MODULE_SRCDIR)/objs/src/http/modules/perl:$$pwd/abuild-module-perl/src/$(MODULE_SRCDIR)/objs/src/http/modules/perl/blib/arch;" ; \ + if [ -n "$(TEST_MODULES)" ]; then \ + run_dirs= ; \ + for m in $(TEST_MODULES); do \ + case "$$m" in \ + .) d=. ;; \ + *) d="module-$$m" ;; \ + esac ; \ + if [ -e "nginx-tests/$${d%%/*}" ]; then \ + run_dirs="$$run_dirs $$d" ; \ + else \ + echo "---> $$m: no tests staged, skipping" ; \ + fi ; \ + done ; \ + else \ + run_dirs=". $$staged_dirs" ; \ fi ; \ - if [ -d $$pwd/module-lua -a ! -e nginx-module-lua.skip ]; then \ - globals_http="lua_package_path '$$pwd/abuild-module-lua/src/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/abuild-module-lua/src/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ - globals_stream="$$globals_http" ; \ - fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx-debug TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-modules: $(addprefix test-module-, $(MODULES)) - -test-module-%: base nginx-tests module-% - @{ \ - module=`echo $@ | cut -d '-' -f 3-` ; \ - testdir="$(MODULE_TESTS_$(shell echo $@ | cut -d '-' -f 3-))" ; \ - if [ -z "$$testdir" ]; then \ - echo "---> Skipping, no tests defined for $$module module" ; \ + if [ -z "$$run_dirs" ]; then \ + echo "---> Nothing to test" ; \ exit 0 ; \ fi ; \ - pwd=`pwd` ; \ - globals= ; \ - for so in `find module-$${module}/ -maxdepth 1 -type f -name "*module.so"`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ - done ; \ - if [ ! -d nginx-tests/module-$${module} ]; then \ - cp -r $${pwd}/abuild-module-$${module}/src/$${testdir} nginx-tests/module-$${module} ; \ - ln -fs ../lib nginx-tests/module-$${module}/lib ; \ - fi ; \ - cd nginx-tests/module-$${module} && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" prove $$PROVE_ARGS . ; \ + cd nginx-tests && \ + TEST_NGINX_BINARY=$$pwd/base/$$TEST_BIN \ + TEST_NGINX_GLOBALS="$$TEST_NGINX_GLOBALS $$globals" \ + TEST_NGINX_GLOBALS_HTTP="$$globals_http" \ + TEST_NGINX_GLOBALS_STREAM="$$globals_stream" \ + prove $$PROVE_ARGS -I$$pwd/nginx-tests/lib $$run_dirs ; \ } check-modules: @@ -385,7 +404,7 @@ check-modules: } clean: - @rm -rf base abuild-base abuild-module-* module-* $(BASE_SRC) nginx-tests .deps-module-* attest-base attest-module-* + @rm -rf base abuild-base abuild-module-* module-* $(BASE_SRC) nginx-tests pkg-oss-tests .deps-module-* attest-base attest-module-* .PHONY: default all modules abuild test test-debug check-modules clean diff --git a/alpine/Makefile.module-acme b/alpine/Makefile.module-acme index 30986048..cd8fd805 100644 --- a/alpine/Makefile.module-acme +++ b/alpine/Makefile.module-acme @@ -16,8 +16,6 @@ MODULE_SOURCES_acme= nginx-acme-$(NGINX_ACME_VERSION).tar.gz \ MODULE_CONFARGS_acme= --add-dynamic-module=$(MODSRC_PREFIX)nginx-acme-$(NGINX_ACME_VERSION) -prerequisites-for-module-acme: - # fixes module dependencies build using rustup-provided rustc/cargo define MODULE_PREBUILD_acme export NGX_ACME_STATE_PREFIX=/var/cache/nginx \&\& \ diff --git a/alpine/Makefile.module-auth-spnego b/alpine/Makefile.module-auth-spnego index e7b6016f..55f3272b 100644 --- a/alpine/Makefile.module-auth-spnego +++ b/alpine/Makefile.module-auth-spnego @@ -17,8 +17,6 @@ MODULE_PATCHES_auth_spnego= MODULE_CONFARGS_auth_spnego= --add-dynamic-module=$(MODSRC_PREFIX)spnego-http-auth-nginx-module-$(SPNEGO_HTTP_AUTH_NGINX_MODULE_GITHASH) -prerequisites-for-module-auth-spnego: - MODULE_BUILD_DEPENDS_auth_spnego=krb5-dev define MODULE_POST_auth_spnego diff --git a/alpine/Makefile.module-encrypted-session b/alpine/Makefile.module-encrypted-session index 8d251aea..b7a2f0f3 100644 --- a/alpine/Makefile.module-encrypted-session +++ b/alpine/Makefile.module-encrypted-session @@ -18,8 +18,6 @@ MODULE_SOURCES_encrypted_session= ngx_devel_kit-$(NGX_DEVEL_KIT_VERSION).tar.gz MODULE_CONFARGS_encrypted_session= --add-dynamic-module=$(MODSRC_PREFIX)ngx_devel_kit-$(NGX_DEVEL_KIT_VERSION) \ --add-dynamic-module=$(MODSRC_PREFIX)encrypted-session-nginx-module-$(ENCRYPTED_SESSION_NGINX_MODULE_VERSION) -prerequisites-for-module-encrypted-session: module-ndk - MODULE_DEPENDS_encrypted_session=$(NDK_DEPENDENCY_TAG) define MODULE_PREINSTALL_encrypted_session diff --git a/alpine/Makefile.module-fips-check b/alpine/Makefile.module-fips-check index d0d1378c..d215d46b 100644 --- a/alpine/Makefile.module-fips-check +++ b/alpine/Makefile.module-fips-check @@ -17,8 +17,6 @@ MODULE_PATCHES_fips_check= $(CONTRIB)/src/nginx-fips-check-module/0001-Added-sup MODULE_CONFARGS_fips_check= --add-dynamic-module=$(MODSRC_PREFIX)nginx-fips-check-module-$(NGINX_FIPS_CHECK_MODULE_VERSION) -prerequisites-for-module-fips-check: - define MODULE_POST_fips_check cat < Copying tests from $(CONTRIB)/tarballs/nginx-tests" ; \ - cp -rP $(CONTRIB)/tarballs/nginx-tests nginx-tests ; \ + echo "===> Copying tests from $(CONTRIB)/tarballs/$@" ; \ + cp -rP $(CONTRIB)/tarballs/$@ $@ ; \ } -test: base nginx-tests - @echo "===> Running tests with regular binary/modules" +NDK_MODULES= $(filter-out ndk,$(foreach m,$(MODULES),$(if $(findstring ngx_devel_kit,$(MODULE_CONFARGS_$(call modname, $(m)))),$(m)))) + +test test-debug: base nginx-tests pkg-oss-tests @{ \ + TEST_BIN=nginx ; \ + TEST_SO_SUFFIX= ; \ + TEST_PERL_OBJS=build-nginx ; \ + case "$@" in \ + *-debug) \ + TEST_BIN="$${TEST_BIN}-debug" \ + TEST_SO_SUFFIX="-debug" \ + TEST_PERL_OBJS="$${TEST_PERL_OBJS}-debug" \ + ;; \ + esac ; \ + echo "===> Running tests with $$TEST_BIN binary/modules" ; \ pwd=`pwd` ; \ + for m in $(NDK_MODULES); do \ + [ -d module-$$m ] || continue ; \ + [ -d module-ndk ] && break ; \ + echo "===> Building module-ndk, required by module-$$m" ; \ + make module-ndk || exit 1 ; \ + break ; \ + done ; \ globals= ; \ globals_http= ; \ globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + for m in ndk $(filter-out ndk,$(MODULES)); do \ + [ -d module-$$m ] || continue ; \ + for so in module-$$m/*module$${TEST_SO_SUFFIX}.so; do \ + [ -e "$$so" ] || continue ; \ + globals="$$globals load_module $$pwd/$$so;" ; \ + done ; \ done ; \ if [ -d $$pwd/module-perl ]; then \ - globals="$$globals env PERL5LIB=$$pwd/debuild-module-perl/$(SRCDIR)/debian/build-nginx/objs/src/http/modules/perl:$$pwd/debuild-module-perl/$(SRCDIR)/debian/build-nginx/objs/src/http/modules/perl/blib/arch;" ; \ + globals="$$globals env PERL5LIB=$$pwd/debuild-module-perl/$(SRCDIR)/debian/$$TEST_PERL_OBJS/objs/src/http/modules/perl:$$pwd/debuild-module-perl/$(SRCDIR)/debian/build-nginx/objs/src/http/modules/perl/blib/arch;" ; \ fi ; \ if [ -d $$pwd/module-lua ]; then \ globals_http="lua_package_path '$$pwd/debuild-module-lua/$(SRCDIR)/debian/extra/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/debuild-module-lua/$(SRCDIR)/debian/extra/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ globals_stream="$$globals_http" ; \ fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-debug: base nginx-tests - @echo "===> Running tests with debug binary/modules" - @{ \ - pwd=`pwd` ; \ - globals= ; \ - globals_http= ; \ - globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module-debug.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + staged_dirs= ; \ + for m in $(MODULES); do \ + [ -d module-$$m ] || continue ; \ + case $$m in \ + acme) testdir=$$pwd/debuild-module-acme/$(SRCDIR)/debian/extra/nginx-acme-$(NGINX_ACME_VERSION)/t ;; \ + njs) testdir=$$pwd/debuild-module-njs/$(SRCDIR)/debian/extra/njs-$(NJS_VERSION)/nginx/t ;; \ + *) testdir=pkg-oss-tests/$$m/t ;; \ + esac ; \ + [ -d "$$testdir" ] || continue ; \ + echo "===> Staging module-$$m tests from $$testdir" ; \ + rm -rf nginx-tests/module-$$m ; \ + cp -r "$$testdir" nginx-tests/module-$$m ; \ + [ -e nginx-tests/module-$$m/lib ] || ln -s ../lib nginx-tests/module-$$m/lib ; \ + staged_dirs="$$staged_dirs module-$$m" ; \ done ; \ - if [ -d $$pwd/module-perl ]; then \ - globals="$$globals env PERL5LIB=$$pwd/debuild-module-perl/$(SRCDIR)/debian/build-nginx-debug/objs/src/http/modules/perl:$$pwd/debuild-module-perl/$(SRCDIR)/debian/build-nginx/objs/src/http/modules/perl/blib/arch;" ; \ - fi ; \ - if [ -d $$pwd/module-lua ]; then \ - globals_http="lua_package_path '$$pwd/debuild-module-lua/$(SRCDIR)/debian/extra/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/debuild-module-lua/$(SRCDIR)/debian/extra/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ - globals_stream="$$globals_http" ; \ + if [ -n "$(TEST_MODULES)" ]; then \ + run_dirs= ; \ + for m in $(TEST_MODULES); do \ + case "$$m" in \ + .) d=. ;; \ + *) d="module-$$m" ;; \ + esac ; \ + if [ -e "nginx-tests/$${d%%/*}" ]; then \ + run_dirs="$$run_dirs $$d" ; \ + else \ + echo "---> $$m: no tests staged, skipping" ; \ + fi ; \ + done ; \ + else \ + run_dirs=". $$staged_dirs" ; \ fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx-debug TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-modules: $(addprefix test-module-, $(MODULES)) - -test-module-%: base nginx-tests module-% - @{ \ - module=`echo $@ | cut -d '-' -f 3-` ; \ - testdir="$(MODULE_TESTS_$(shell echo $@ | cut -d '-' -f 3-))" ; \ - if [ -z "$$testdir" ]; then \ - echo "---> Skipping, no tests defined for $$module module" ; \ + if [ -z "$$run_dirs" ]; then \ + echo "---> Nothing to test" ; \ exit 0 ; \ fi ; \ - pwd=`pwd` ; \ - globals= ; \ - for so in `find module-$${module}/ -maxdepth 1 -type f -name "*module.so"`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ - done ; \ - if [ ! -d nginx-tests/module-$${module} ]; then \ - cp -r $${pwd}/debuild-module-$${module}/$(SRCDIR)/debian/extra/$${testdir} nginx-tests/module-$${module} ; \ - ln -fs ../lib nginx-tests/module-$${module}/lib ; \ - fi ; \ - cd nginx-tests/module-$${module} && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" prove $$PROVE_ARGS . ; \ + cd nginx-tests && \ + TEST_NGINX_BINARY=$$pwd/base/$$TEST_BIN \ + TEST_NGINX_GLOBALS="$$TEST_NGINX_GLOBALS $$globals" \ + TEST_NGINX_GLOBALS_HTTP="$$globals_http" \ + TEST_NGINX_GLOBALS_STREAM="$$globals_stream" \ + prove $$PROVE_ARGS -I$$pwd/nginx-tests/lib $$run_dirs ; \ } + check-modules: @{ \ files=$@-files ; \ @@ -475,7 +497,7 @@ check-modules: } clean: - @rm -rf base module-* rules-base rules-module-* debuild-base debuild-module-* nginx-tests $(BASE_SRC) .deps-module-* + @rm -rf base module-* rules-base rules-module-* debuild-base debuild-module-* nginx-tests pkg-oss-tests $(BASE_SRC) .deps-module-* @rm -f nginx.deb-changelog nginx-*.deb-changelog nginx-module-*.deb-changelog nginx-module-*.skip @rm -f attest-base attest-module-* diff --git a/rpm/SPECS/Makefile b/rpm/SPECS/Makefile index 6d0ed76f..635d45be 100644 --- a/rpm/SPECS/Makefile +++ b/rpm/SPECS/Makefile @@ -387,26 +387,47 @@ check-compat-%: ;; \ esac -nginx-tests: +nginx-tests pkg-oss-tests: @{ \ - if [ ! -d "$(CONTRIB)/tarballs/nginx-tests" ]; then \ + if [ ! -d "$(CONTRIB)/tarballs/$@" ]; then \ curdir=`pwd` ; \ - cd $(CONTRIB) && make .sum-nginx-tests ; \ + cd $(CONTRIB) && make .sum-$@ ; \ cd $$curdir ; \ fi ; \ - echo "===> Copying tests from $(CONTRIB)/tarballs/nginx-tests" ; \ - cp -rP $(CONTRIB)/tarballs/nginx-tests nginx-tests ; \ + echo "===> Copying tests from $(CONTRIB)/tarballs/$@" ; \ + cp -rP $(CONTRIB)/tarballs/$@ $@ ; \ } -test: base nginx-tests - @echo "===> Running tests with regular binary/modules" +NDK_MODULES= $(filter-out ndk,$(foreach m,$(MODULES),$(if $(findstring ngx_devel_kit,$(MODULE_CONFARGS_$(call modname, $(m)))),$(m)))) + +test test-debug: base nginx-tests pkg-oss-tests @{ \ + TEST_BIN=nginx ; \ + TEST_SO_SUFFIX= ; \ + case "$@" in \ + *-debug) \ + TEST_BIN="$${TEST_BIN}-debug" \ + TEST_SO_SUFFIX="-debug" \ + ;; \ + esac ; \ + echo "===> Running tests with $$TEST_BIN binary/modules" ; \ pwd=`pwd` ; \ + for m in $(NDK_MODULES); do \ + [ -d module-$$m ] || continue ; \ + [ -d module-ndk ] && break ; \ + echo "===> Building module-ndk, required by module-$$m" ; \ + make module-ndk || exit 1 ; \ + break ; \ + done ; \ globals= ; \ globals_http= ; \ globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + for m in ndk $(filter-out ndk,$(MODULES)); do \ + [ -d module-$$m ] || continue ; \ + for so in module-$$m/*module$${TEST_SO_SUFFIX}.so; do \ + [ -e "$$so" ] || continue ; \ + globals="$$globals load_module $$pwd/$$so;" ; \ + done ; \ done ; \ if [ -d $$pwd/module-perl ]; then \ globals="$$globals env PERL5LIB=$$pwd/module-perl/src/http/modules/perl:$$pwd/module-perl/src/http/modules/perl/blib/arch;" ; \ @@ -415,55 +436,55 @@ test: base nginx-tests globals_http="lua_package_path '$$pwd/../BUILD/$(MODULE_PACKAGE_PREFIX)-lua-$(BASE_VERSION)/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/../BUILD/$(MODULE_PACKAGE_PREFIX)-lua-$(BASE_VERSION)/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ globals_stream="$$globals_http" ; \ fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-debug: base nginx-tests - @echo "===> Running tests with debug binary/modules" - @{ \ - pwd=`pwd` ; \ - globals= ; \ - globals_http= ; \ - globals_stream= ; \ - for so in `find module-*/ -maxdepth 1 -type f -name "*module-debug.so" | sort -t / -k 2`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ + staged_dirs= ; \ + for m in $(MODULES); do \ + [ -d module-$$m ] || continue ; \ + case $$m in \ + acme) testdir=$$pwd/module-acme/../nginx-acme-$(NGINX_ACME_VERSION)/t ;; \ + njs) testdir=$$pwd/module-njs/../njs-$(NJS_VERSION)/nginx/t ;; \ + *) testdir=pkg-oss-tests/$$m/t ;; \ + esac ; \ + [ -d "$$testdir" ] || continue ; \ + echo "===> Staging module-$$m tests from $$testdir" ; \ + rm -rf nginx-tests/module-$$m ; \ + cp -r "$$testdir" nginx-tests/module-$$m ; \ + [ -e nginx-tests/module-$$m/lib ] || ln -s ../lib nginx-tests/module-$$m/lib ; \ + staged_dirs="$$staged_dirs module-$$m" ; \ done ; \ - if [ -d $$pwd/module-perl ]; then \ - globals="$$globals env PERL5LIB=$$pwd/module-perl/src/http/modules/perl:$$pwd/module-perl/src/http/modules/perl/blib/arch;" ; \ - fi ; \ - if [ -d $$pwd/module-lua ]; then \ - globals_http="lua_package_path '$$pwd/../BUILD/$(MODULE_PACKAGE_PREFIX)-lua-$(BASE_VERSION)/lua-resty-core-$(LUA_RESTY_CORE_VERSION)/lib/?.lua;$$pwd/../BUILD/$(MODULE_PACKAGE_PREFIX)-lua-$(BASE_VERSION)/lua-resty-lrucache-$(LUA_RESTY_LRUCACHE_VERSION)/lib/?.lua;;';" ; \ - globals_stream="$$globals_http" ; \ + if [ -n "$(TEST_MODULES)" ]; then \ + run_dirs= ; \ + for m in $(TEST_MODULES); do \ + case "$$m" in \ + .) d=. ;; \ + *) d="module-$$m" ;; \ + esac ; \ + if [ -e "nginx-tests/$${d%%/*}" ]; then \ + run_dirs="$$run_dirs $$d" ; \ + else \ + echo "---> $$m: no tests staged, skipping" ; \ + fi ; \ + done ; \ + else \ + run_dirs=". $$staged_dirs" ; \ fi ; \ - cd nginx-tests && TEST_NGINX_BINARY=$$pwd/base/nginx-debug TEST_NGINX_GLOBALS="$$globals" TEST_NGINX_GLOBALS_HTTP="$$globals_http" TEST_NGINX_GLOBALS_STREAM="$$globals_stream" prove $$PROVE_ARGS . ; \ - } - -test-modules: $(addprefix test-module-, $(MODULES)) - -test-module-%: base nginx-tests module-% - @{ \ - module=`echo $@ | cut -d '-' -f 3-` ; \ - testdir="$(MODULE_TESTS_$(shell echo $@ | cut -d '-' -f 3-))" ; \ - if [ -z "$$testdir" ]; then \ - echo "---> Skipping, no tests defined for $$module module" ; \ + if [ -z "$$run_dirs" ]; then \ + echo "---> Nothing to test" ; \ exit 0 ; \ fi ; \ - pwd=`pwd` ; \ - globals= ; \ - for so in `find module-$${module}/ -maxdepth 1 -type f -name "*module.so"`; do \ - globals="$$globals load_module $$pwd/$$so;" ; \ - done ; \ - if [ ! -d nginx-tests/module-$${module} ]; then \ - cp -r $${pwd}/module-$${module}/../$${testdir} nginx-tests/module-$${module} ; \ - ln -fs ../lib nginx-tests/module-$${module}/lib ; \ - fi ; \ - cd nginx-tests/module-$${module} && TEST_NGINX_BINARY=$$pwd/base/nginx TEST_NGINX_GLOBALS="$$globals" prove $$PROVE_ARGS . ; \ + cd nginx-tests && \ + TEST_NGINX_BINARY=$$pwd/base/$$TEST_BIN \ + TEST_NGINX_GLOBALS="$$TEST_NGINX_GLOBALS $$globals" \ + TEST_NGINX_GLOBALS_HTTP="$$globals_http" \ + TEST_NGINX_GLOBALS_STREAM="$$globals_stream" \ + prove $$PROVE_ARGS -I$$pwd/nginx-tests/lib $$run_dirs ; \ } + clean: @rm -f base module-* @rm -f nginx.spec nginx-module-*.spec nginx-module-*.skip @rm -rf nginx-tests + @rm -rf pkg-oss-tests @rm -f $(BASE_SRC) $(SRCPATH)/$(BASE_SRC) @rm -f nginx.rpm-changelog nginx-*.rpm-changelog nginx-module-*.rpm-changelog @rm -f .deps-module-*