name: "CI for distros"

on:
  push:
    branches:
      - main
      - "dist-*"
    tags:
      - v*
  pull_request:
    branches:
      - "dist-*"
    paths:
      - 'naxsi_src/**'
      - 'unit-tests/**'
      - 'distros/**'

# Automatically cancel any previous workflow on new push.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
  cancel-in-progress: true

jobs:
  tarball:
    runs-on: ubuntu-latest
    name: "Release Tarball"
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      with:
        submodules: recursive
        persist-credentials: false
    - name: Prepare Release
      shell: bash
      run: |
        if [[ "${{ startsWith(github.event.ref, 'refs/tags')}}" = "true" ]]
        then
          RELEASE_ID="${{ github.event.ref }}"
        else
          RELEASE_ID="git-`date "+%Y-%m-%d"`-`git rev-parse --short HEAD`"
        fi
        RELEASE_ID=${RELEASE_ID##refs/tags/}
        echo RELEASE_NAME="naxsi-${RELEASE_ID}-src-with-deps-tgz" >> $GITHUB_ENV
        export TARNAME="naxsi-${RELEASE_ID}-src-with-deps.tar.gz"
        touch "$TARNAME"
        rm -rf .git
        tar --exclude="$TARNAME" -czvf "$TARNAME" .
    - name: Upload tarball
      uses: actions/upload-artifact@v3
      with:
        name: ${{ env.RELEASE_NAME }}
        path: ./*.tar.gz

  zip:
    runs-on: ubuntu-latest
    name: "Release Zip"
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      with:
        submodules: recursive
        persist-credentials: false
    - name: Prepare Release
      shell: bash
      run: |
        if [[ "${{ startsWith(github.event.ref, 'refs/tags')}}" = "true" ]]
        then
          RELEASE_ID="${{ github.event.ref }}"
        else
          RELEASE_ID="git-`date "+%Y-%m-%d"`-`git rev-parse --short HEAD`"
        fi
        RELEASE_ID=${RELEASE_ID##refs/tags/}
        echo RELEASE_NAME="naxsi-${RELEASE_ID}-src-with-deps-zip" >> $GITHUB_ENV
        rm -rf .git
    - name: Upload zip
      uses: actions/upload-artifact@v3
      with:
        name: ${{ env.RELEASE_NAME }}
        path: ./*

  packages:
    runs-on: ubuntu-latest
    name: ${{ matrix.name }}
    container: ${{ matrix.container }}
    strategy:
      fail-fast: false
      matrix:
        name:
          [
            "arch-linux",
            "debian-buster",
            "debian-bullseye",
            "debian-bookworm",
            "ubuntu-focal",
            "ubuntu-jammy",
            "alpine-3.17.4",
            "alpine-3.18.2",
          ]
        include:
          - name: arch-linux
            container: archlinux:latest
            package: arch
          - name: debian-buster
            container: debian:buster
            package: deb
            pcredep: libpcre3-dev
            nginxdep: nginx-common
          - name: debian-bullseye
            container: debian:bullseye
            package: deb
            pcredep: libpcre3-dev
            nginxdep: nginx-common
          - name: debian-bookworm
            container: debian:bookworm-slim
            package: deb
            pcredep: libpcre2-dev
            nginxdep: nginx
          - name: ubuntu-focal
            container: ubuntu:focal
            package: deb
            pcredep: libpcre3-dev
            nginxdep: nginx-common
          - name: ubuntu-jammy
            container: ubuntu:jammy
            package: deb
            pcredep: libpcre3-dev
            nginxdep: nginx-common
          - name: alpine-3.17.4
            container: alpine:3.17.4
            package: apk
          - name: alpine-3.18.2
            container: alpine:3.18.2
            package: apk

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    # APK package
    - name: Install required dependencies
      if: matrix.package == 'apk'
      run: apk add alpine-sdk doas
    - name: Checkout needed repos
      if: matrix.package == 'apk'
      run: |
        rm -rf naxsi_src/libinjection
        git clone https://github.com/libinjection/libinjection.git naxsi_src/libinjection
        git -C naxsi_src/libinjection checkout b9fcaaf9e50e9492807b23ffcc6af46ee1f203b9
        chmod 777 .
    - name: ${{ matrix.name }} package
      if: matrix.package == 'apk'
      run:  sh ./distros/alpine/build-ci.sh
    - name: Test apk package
      if: matrix.package == 'apk'
      run: |
        apk add --no-cache nginx
        apk add --allow-untrusted build/*.apk
    - name: Upload apk package
      if: matrix.package == 'apk'
      uses: actions/upload-artifact@v3
      with:
        name: ${{ matrix.name }}
        path: build/*.apk

    # DEB package
    - name: Update OS & Install deps
      if: matrix.package == 'deb'
      run: |
        if [ -f "/etc/apt/sources.list" ]; then
          cat /etc/apt/sources.list > /tmp/sources.list.orig
          cat /tmp/sources.list.orig | grep -v "#" | sed 's/^deb /deb-src /g' >> /etc/apt/sources.list
        fi
        apt-get -qqy update
        DEBIAN_FRONTEND=noninteractive apt-get -qqy --no-install-recommends install \
            build-essential \
            ca-certificates \
            dpkg-dev \
            gzip \
            git \
            libgd-dev \
            libgeoip-dev \
            ${{ matrix.pcredep }} \
            libperl-dev \
            libssl-dev \
            libxslt1-dev \
            nginx \
            tar \
            wget \
            zlib1g-dev
        if [ -f "/etc/apt/sources.list.d/debian.sources" ]; then
          # bookworm only.
          echo "deb https://ftp.debian.org/debian/ bookworm contrib main non-free non-free-firmware" >> /etc/apt/sources.list.d/nginx.list
          echo "deb-src https://ftp.debian.org/debian/ bookworm contrib main non-free non-free-firmware" >> /etc/apt/sources.list.d/nginx.list
          apt-get -qqy update
          DEBIAN_FRONTEND=noninteractive apt-get -qqy --no-install-recommends install \
            libperl-dev
        fi
    - name: Checkout needed repos
      if: matrix.package == 'deb'
      run: |
        rm -rf naxsi_src/libinjection
        git clone https://github.com/libinjection/libinjection.git naxsi_src/libinjection
        git -C naxsi_src/libinjection checkout b9fcaaf9e50e9492807b23ffcc6af46ee1f203b9
        git clone --depth=1 https://github.com/wargio/deb-creator.git
        chmod 777 .
        apt-get source nginx
    - name: ${{ matrix.name }} package
      if: matrix.package == 'deb'
      run: |
        mkdir -p deb_pkg/
        DEB_PKG=$(realpath deb_pkg)
        NGINX_PACKAGE="${{ matrix.nginxdep }}"
        NAXSI_VERSION=$(grep "NAXSI_VERSION" naxsi_src/naxsi_const.h | cut -d ' ' -f3 | sed 's/"//g')
        LIBPCRE_PACKAGE="${{ matrix.pcredep }}"
        LIBPCRE_VERSION=$(dpkg -s ${{ matrix.pcredep }} | grep '^Version:' | cut -d ' ' -f2 | cut -d '-' -f1)
        NGINX_VERSION=$(dpkg -s nginx | grep '^Version:' | cut -d ' ' -f2 | cut -d '-' -f1)
        NGINX_BUILD_OPTS=$(nginx -V 2>&1 | grep "configure arguments:" | cut -d ":" -f2- | sed -e "s#/build/nginx-[A-Za-z0-9]*/#./#g" | sed 's/--add-dynamic-module=[A-Za-z0-9\/\._-]*//g')
        echo "NGINX_VERSION:    $NGINX_VERSION"
        echo "NGINX_BUILD_OPTS: $NGINX_BUILD_OPTS"
        # build module
        cd nginx-$NGINX_VERSION
        CMDLINE=$(echo ./configure $NGINX_BUILD_OPTS --add-dynamic-module=../naxsi_src/)
        eval $CMDLINE
        make modules
        cd ..
        # install files
        mkdir -p "$DEB_PKG/data/usr/lib/nginx/modules/"
        mkdir -p "$DEB_PKG/data/usr/share/nginx/modules-available/"
        mkdir -p "$DEB_PKG/data/usr/share/naxsi/whitelists"
        mkdir -p "$DEB_PKG/data/usr/share/naxsi/blocking"
        install -Dm755 distros/deb/postinstall.script "$DEB_PKG/postinstall.script"
        install -Dm755 distros/deb/postremove.script "$DEB_PKG/postremove.script"
        install -Dm755 distros/deb/preremove.script "$DEB_PKG/preremove.script"
        install -Dm644 distros/deb/control.install "$DEB_PKG/control.install"
        install -Dm755 "nginx-$NGINX_VERSION/objs/ngx_http_naxsi_module.so" "$DEB_PKG/data/usr/lib/nginx/modules/ngx_http_naxsi_module.so"
        install -Dm644 distros/deb/mod-http-naxsi.conf "$DEB_PKG/data/usr/share/nginx/modules-available/mod-http-naxsi.conf"
        install -Dm644 distros/nginx/naxsi_block_mode.conf "$DEB_PKG/data/usr/share/naxsi/naxsi_block_mode.conf"
        install -Dm644 distros/nginx/naxsi_denied_url.conf "$DEB_PKG/data/usr/share/naxsi/naxsi_denied_url.conf"
        install -Dm644 distros/nginx/naxsi_learning_mode.conf "$DEB_PKG/data/usr/share/naxsi/naxsi_learning_mode.conf"
        install -Dm644 naxsi_rules/naxsi_core.rules "$DEB_PKG/data/usr/share/naxsi/naxsi_core.rules"
        install -Dm644 naxsi_rules/whitelists/*.rules "$DEB_PKG/data/usr/share/naxsi/whitelists"
        install -Dm644 naxsi_rules/blocking/*.rules "$DEB_PKG/data/usr/share/naxsi/blocking"
        # add deb details.
        sed -i "s/@NGINX_PACKAGE@/$NGINX_PACKAGE/" "$DEB_PKG/control.install"
        sed -i "s/@NGINX_VERSION@/$NGINX_VERSION/" "$DEB_PKG/control.install"
        sed -i "s/@LIBPCRE_PACKAGE@/$LIBPCRE_PACKAGE/" "$DEB_PKG/control.install"
        sed -i "s/@LIBPCRE_VERSION@/$LIBPCRE_VERSION/" "$DEB_PKG/control.install"
        sed -i "s/@NAXSI_VERSION@/$NAXSI_VERSION/" "$DEB_PKG/control.install"
        # build deb file
        ./deb-creator/deb-creator "$DEB_PKG"
    - name: Test deb package
      if: matrix.package == 'deb'
      run: dpkg -i deb_pkg/*.deb
    - name: Upload deb package
      if: matrix.package == 'deb'
      uses: actions/upload-artifact@v3
      with:
        name: ${{ matrix.name }}
        path: deb_pkg/*.deb

    # Arch Linux package
    - name: ${{ matrix.name }} package
      if: matrix.package == 'arch'
      run: |
        pacman -Syy --needed --noconfirm sudo base-devel git perl-rename
        chmod 777 distros/arch
        useradd build-user -m
        passwd -d build-user
        printf 'build-user ALL=(ALL) ALL\n' | tee -a /etc/sudoers
        cd distros/arch
        sudo -u build-user makepkg -s --noconfirm
        # Fix package name due github name restrictions
        perl-rename -v 's/:/-/g' *.pkg.tar.zst
    - name: Test arch package
      if: matrix.package == 'arch'
      run: pacman -U --noconfirm distros/arch/*.pkg.tar.zst
    - name: Upload arch package
      if: matrix.package == 'arch'
      uses: actions/upload-artifact@v3
      with:
        name: ${{ matrix.name }}
        path: distros/arch/*.pkg.tar.zst