diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3b1f51a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,217 @@ +name: CI + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, ubuntu-22.04] + nginx_version: ['1.24.0', '1.25.3', '1.26.0'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + libpcre3 libpcre3-dev \ + zlib1g zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + perl \ + cpanminus + + - name: Install Perl test dependencies + run: | + sudo cpanm --notest Test::Nginx + + - name: Cache nginx + id: cache-nginx + uses: actions/cache@v4 + with: + path: ~/nginx-${{ matrix.nginx_version }} + key: nginx-${{ matrix.nginx_version }}-${{ matrix.os }} + + - name: Download and extract nginx + if: steps.cache-nginx.outputs.cache-hit != 'true' + run: | + cd ~ + NGINX_VERSION="${{ matrix.nginx_version }}" + wget -q "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" + tar -xzf "nginx-${NGINX_VERSION}.tar.gz" + + - name: Configure and build nginx with zstd module + run: | + cd ~/nginx-${{ matrix.nginx_version }} + ./configure \ + --prefix=/tmp/nginx \ + --with-http_ssl_module \ + --with-http_v2_module \ + --add-module=${{ github.workspace }} + make -j$(nproc) + sudo make install + + - name: Add nginx to PATH + run: | + echo "/tmp/nginx/sbin" >> $GITHUB_PATH + + - name: Verify nginx installation + run: | + /tmp/nginx/sbin/nginx -V + + - name: Run tests + run: | + export PATH=/tmp/nginx/sbin:$PATH + cd ${{ github.workspace }} + prove -r t/ + env: + TEST_NGINX_BINARY: /tmp/nginx/sbin/nginx + + build-docker: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build test Dockerfile + run: | + cat > Dockerfile.test << 'EOF' + FROM nginx:1.26.0 AS builder + + # Install build dependencies + RUN apt-get update && apt-get install -y \ + build-essential \ + libpcre3-dev \ + zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + wget \ + && rm -rf /var/lib/apt/lists/* + + # Get nginx source + WORKDIR /build + RUN wget -q http://nginx.org/download/nginx-1.26.0.tar.gz && \ + tar -xzf nginx-1.26.0.tar.gz + + # Copy module source + COPY . /build/zstd-nginx-module + + # Build nginx with zstd module + WORKDIR /build/nginx-1.26.0 + RUN ./configure \ + --prefix=/etc/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/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 \ + --user=nginx \ + --group=nginx \ + --with-http_ssl_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_stub_status_module \ + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_slice_module \ + --with-threads \ + --with-file-aio \ + --add-module=/build/zstd-nginx-module && \ + make -j$(nproc) && \ + make install + + # Runtime stage + FROM nginx:1.26.0 + + # Install runtime dependencies + RUN apt-get update && apt-get install -y \ + libzstd1 \ + && rm -rf /var/lib/apt/lists/* + + # Copy compiled nginx with zstd module + COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx + + # Test configuration + RUN nginx -V 2>&1 | grep zstd + + EXPOSE 80 443 + CMD ["nginx", "-g", "daemon off;"] + EOF + + - name: Build Docker image + run: | + docker build -f Dockerfile.test -t nginx-zstd:test . + + - name: Test Docker image + run: | + # Start container + docker run -d --name nginx-zstd-test nginx-zstd:test + sleep 2 + + # Check if nginx is running + docker ps | grep nginx-zstd-test + + # Check nginx version includes zstd + docker exec nginx-zstd-test nginx -V 2>&1 | grep zstd + + # Cleanup + docker stop nginx-zstd-test + docker rm nginx-zstd-test + + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check for trailing whitespace + run: | + if git grep -I --line-number -P '\s+$' -- '*.c' '*.h' 'config' \ + 2>/dev/null; then + echo "Error: Found trailing whitespace" + exit 1 + else + echo "No trailing whitespace found" + fi + + - name: Check file permissions + run: | + # Check that source files don't have execute permissions + if find . -name '*.c' -o -name '*.h' | xargs ls -l \ + | grep '^-rwxr'; then + echo "Error: Source files should not be executable" + exit 1 + else + echo "File permissions are correct" + fi diff --git a/CI_CD_IMPLEMENTATION.md b/CI_CD_IMPLEMENTATION.md new file mode 100644 index 0000000..7d9e13c --- /dev/null +++ b/CI_CD_IMPLEMENTATION.md @@ -0,0 +1,170 @@ +# CI/CD Implementation Summary + +This document describes the CI/CD implementation for the zstd-nginx-module project. + +## Overview + +A comprehensive GitHub Actions CI/CD pipeline has been implemented to automatically build and test the zstd-nginx-module with various nginx versions and operating systems. + +## Workflow File + +Location: `.github/workflows/ci.yml` + +## CI/CD Features + +### 1. Test Job + +The main test job builds nginx with the zstd module and runs the test suite: + +**Matrix Testing:** +- **Operating Systems:** Ubuntu 20.04, Ubuntu 22.04 +- **Nginx Versions:** 1.24.0, 1.25.3, 1.26.0 +- **Total Combinations:** 6 test configurations + +**Steps:** +1. Checkout code +2. Install system dependencies (build tools, libzstd, perl, etc.) +3. Install Perl test dependencies (Test::Nginx) +4. Cache nginx source for faster builds +5. Download and extract nginx source (if not cached) +6. Configure nginx with zstd module using `--add-module` +7. Build nginx +8. Install nginx +9. Verify installation +10. Run test suite with `prove -r t/` + +### 2. Docker Build Job + +Tests building a Docker image with nginx and zstd module: + +**Steps:** +1. Creates a multi-stage Dockerfile for optimal image size +2. Builds nginx with zstd module in builder stage +3. Copies compiled binary to runtime stage +4. Verifies the module is properly integrated +5. Tests the container runs correctly + +### 3. Lint Job + +Performs basic code quality checks: + +**Checks:** +- Trailing whitespace in source files +- Incorrect file permissions on source files + +## Example Files + +Three example files have been added to help users: + +### 1. `example/nginx.conf` + +Complete nginx configuration demonstrating: +- Global zstd compression settings +- Compression level configuration +- Minimum length thresholds +- MIME type filtering +- Static pre-compressed file serving +- Compression ratio logging + +### 2. `example/Dockerfile` + +Production-ready multi-stage Dockerfile showing: +- How to build nginx with zstd module +- Proper dependency installation +- Optimized layer caching +- Runtime image preparation +- Health checks + +### 3. `example/README.md` + +Comprehensive documentation covering: +- Docker usage instructions +- Manual build process +- Configuration examples +- Testing compression +- Performance tips +- Browser compatibility notes + +## Documentation Updates + +### README.md + +Added: +- CI status badge showing workflow status +- Docker installation section with quick start +- Link to example documentation + +## Workflow Triggers + +The CI workflow runs on: +- Push to `main` or `master` branches +- Pull requests to `main` or `master` branches +- Manual workflow dispatch + +## Caching Strategy + +The workflow uses GitHub Actions cache to speed up builds: +- **Cached:** nginx source code by version and OS +- **Benefits:** Faster subsequent builds, reduced network usage + +## Testing + +The test suite uses the Test::Nginx framework which: +- Starts temporary nginx instances +- Tests module functionality +- Validates configuration options +- Ensures proper compression behavior + +## Status + +✅ CI/CD workflow created and validated +✅ YAML syntax verified with yamllint +✅ Example configurations provided +✅ Documentation updated +⏳ Workflow pending approval (common for new workflows) + +## Next Steps for Users + +1. **Repository Maintainer:** Approve the workflow run in GitHub Actions +2. **Review Results:** Check the workflow runs to ensure all tests pass +3. **Customize:** Adjust nginx versions or OS versions as needed +4. **Extend:** Add more test cases or additional checks + +## Maintenance + +To update the CI/CD: + +### Add a New Nginx Version + +Edit `.github/workflows/ci.yml`: +```yaml +matrix: + nginx_version: ['1.24.0', '1.25.3', '1.26.0', '1.27.0'] # Add new version +``` + +### Add a New OS Version + +Edit `.github/workflows/ci.yml`: +```yaml +matrix: + os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04] # Add new OS +``` + +### Add More Tests + +Add new test files to the `t/` directory following the Test::Nginx format. + +## Benefits + +1. **Automated Testing:** Every change is automatically tested +2. **Multi-Version Support:** Ensures compatibility across nginx versions +3. **Quality Assurance:** Catches build and test failures early +4. **Documentation:** Examples help users get started quickly +5. **Visibility:** CI badge shows project health at a glance + +## Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Test::Nginx Documentation](https://metacpan.org/pod/Test::Nginx::Socket) +- [Nginx Module Development](https://nginx.org/en/docs/dev/development_guide.html) +- [Zstandard Compression](https://facebook.github.io/zstd/) diff --git a/README.md b/README.md index 6105896..846f350 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # Name + +[](https://github.com/tokers/zstd-nginx-module/actions/workflows/ci.yml) + zstd-nginx-module - Nginx module for the [Zstandard compression](https://facebook.github.io/zstd/). # Table of Contents @@ -67,6 +70,17 @@ To use theses modules, configure your nginx branch with `--add-module=/path/to/z * System's zstd bundle will be linked if `ZSTD_INC` and `ZSTD_LIB` are not specified. * Both `ngx_http_zstd_static_module` and `ngx_http_zstd_filter_module` will be configured. +## Docker Installation + +A Dockerfile and example configuration are provided in the `example/` directory for easy containerized deployment: + +```bash +docker build -f example/Dockerfile -t nginx-zstd:latest . +docker run -d -p 80:80 nginx-zstd:latest +``` + +See the [example README](example/README.md) for more details on Docker deployment and configuration examples. + # Directives ## ngx_http_zstd_filter_module diff --git a/example/Dockerfile b/example/Dockerfile new file mode 100644 index 0000000..ff33c9c --- /dev/null +++ b/example/Dockerfile @@ -0,0 +1,97 @@ +# Multi-stage Dockerfile for building Nginx with zstd-nginx-module +# +# This Dockerfile demonstrates how to build a production-ready Nginx image +# with the zstd compression module integrated. +# +# Usage: +# docker build -t nginx-zstd:latest . +# docker run -d -p 80:80 nginx-zstd:latest + +ARG NGINX_VERSION=1.26.0 + +# Build stage +FROM nginx:${NGINX_VERSION} AS builder + +# Install build dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + libpcre3-dev \ + zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + wget \ + && rm -rf /var/lib/apt/lists/* + +# Download and extract Nginx source +WORKDIR /build +RUN wget -q http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \ + tar -xzf nginx-${NGINX_VERSION}.tar.gz + +# Copy zstd-nginx-module source +COPY . /build/zstd-nginx-module + +# Configure and build Nginx with zstd module +WORKDIR /build/nginx-${NGINX_VERSION} +RUN ./configure \ + --prefix=/etc/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/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 \ + --user=nginx \ + --group=nginx \ + --with-http_ssl_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_stub_status_module \ + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_slice_module \ + --with-threads \ + --with-file-aio \ + --add-module=/build/zstd-nginx-module && \ + make -j$(nproc) && \ + make install + +# Runtime stage +FROM nginx:${NGINX_VERSION} + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + libzstd1 \ + && rm -rf /var/lib/apt/lists/* + +# Copy compiled Nginx binary with zstd module +COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx + +# Copy example configuration (optional) +COPY example/nginx.conf /etc/nginx/nginx.conf.example + +# Verify the module is loaded +RUN nginx -V 2>&1 | grep -q zstd || (echo "zstd module not found!" && exit 1) + +# Expose ports +EXPOSE 80 443 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost/ || exit 1 + +# Start Nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..4ef1a4a --- /dev/null +++ b/example/README.md @@ -0,0 +1,147 @@ +# Examples + +This directory contains example configurations and Dockerfiles for using the zstd-nginx-module. + +## Contents + +- `nginx.conf` - Example Nginx configuration with zstd compression enabled +- `Dockerfile` - Multi-stage Dockerfile for building Nginx with zstd module + +## Using the Dockerfile + +Build the Docker image: + +```bash +docker build -t nginx-zstd:latest . +``` + +Run the container: + +```bash +docker run -d -p 80:80 --name nginx-zstd nginx-zstd:latest +``` + +Test zstd compression: + +```bash +# Request with zstd accept-encoding +curl -H "Accept-Encoding: zstd" -I http://localhost/ + +# You should see "Content-Encoding: zstd" in the response headers +``` + +## Using the nginx.conf + +The example configuration demonstrates: + +1. **Basic zstd compression** - Enabled globally with compression level 3 +2. **Compression thresholds** - Only compress responses larger than 256 bytes +3. **MIME type filtering** - Compress specific content types +4. **Static pre-compressed files** - Serve `.zst` files when available +5. **Logging compression ratio** - Track compression efficiency with `$zstd_ratio` variable + +To use this configuration: + +1. Copy it to your Nginx configuration directory: + ```bash + cp nginx.conf /etc/nginx/nginx.conf + ``` + +2. Test the configuration: + ```bash + nginx -t + ``` + +3. Reload Nginx: + ```bash + nginx -s reload + ``` + +## Building Nginx Manually + +If you prefer to build Nginx manually without Docker: + +```bash +# Install dependencies +sudo apt-get install -y build-essential libpcre3-dev zlib1g-dev libssl-dev libzstd-dev + +# Download Nginx source +wget http://nginx.org/download/nginx-1.26.0.tar.gz +tar -xzf nginx-1.26.0.tar.gz +cd nginx-1.26.0 + +# Configure with zstd module +./configure --prefix=/usr/local/nginx \ + --with-http_ssl_module \ + --with-http_v2_module \ + --add-module=/path/to/zstd-nginx-module + +# Build and install +make -j$(nproc) +sudo make install +``` + +## Testing Compression + +After setting up Nginx with zstd module, you can test compression: + +```bash +# Create a test HTML file +echo "