version: 2.1

parameters:
  vc-commit:
    type: string
    default: "HEAD"
  pkg-commit:
    type: string
    default: "7.4"
  dist-url:
    type: string
    default: ""
  dist-url-sha256:
    type: string
    default: ""
  configure_args:
    type: string
    default: |
        --with-contrib \
        --with-unwind \
        --enable-developer-warnings \
        --enable-debugging-symbols \
        --disable-stack-protector \
        --with-persistent-storage \
  build-pkgs:
    type: string
    default: ""

jobs:
  dist:
    description: Build or download varnish-x.y.z.tar.gz that is used later for the packaging jobs
    docker:
      - image: centos:7
    steps:
      - run:
          name: Install deps
          command: |
            yum install -y epel-release
            yum install -y \
                automake \
                jemalloc-devel \
                git \
                libedit-devel \
                libtool \
                libunwind-devel \
                make \
                pcre2-devel \
                python3 \
                python-sphinx
      - checkout
      - when:
          condition: << pipeline.parameters.dist-url >>
          steps:
            - run:
                name: Download the dist tarball
                command: |
                  curl -Ls '<< pipeline.parameters.dist-url >>' -o varnish-dist.tar.gz
            - when:
                condition: << pipeline.parameters.dist-url-sha256 >>
                steps:
                  - run:
                      name: Verify downloaded tarball
                      command: |
                        echo "<< pipeline.parameters.dist-url-sha256 >> varnish-dist.tar.gz" | sha256sum -c
            - run:
                name: Rename the dist tarball by parsed version
                command: |
                  mkdir parse-version-tmp
                  cd parse-version-tmp
                  tar xzf ../varnish-dist.tar.gz
                  VERSION=$(varnish-*/configure --version | awk 'NR == 1 {print $NF}')
                  cd ..
                  mv -v varnish-dist.tar.gz varnish-${VERSION}.tar.gz
      - unless:
          condition: << pipeline.parameters.dist-url >>
          steps:
            - run:
                name: Create the dist tarball
                command: |
                  git checkout << pipeline.parameters.vc-commit >>
                  # Locally built tarballs are always built with weekly in package name
                  touch .is_weekly
                  # If version is "trunk", override version to add date
                  if grep 'AC_INIT.*trunk.*' ./configure.ac; then
                      sed -i -e "s/AC_INIT(\[\(.*\)\], \[\(.*\)\], \[\(.*\)\])/AC_INIT([\1], [$(date +%Y%m%d)], [\3])/" ./configure.ac
                  else
                      sed -i -e "s/AC_INIT(\[\(.*\)\], \[\(.*\)\], \[\(.*\)\])/AC_INIT([\1], [\2-$(date +%Y%m%d)], [\3])/" ./configure.ac
                  fi
                  ./autogen.des
                  make dist -j 16
      - persist_to_workspace:
          root: .
          paths:
            - .is_weekly
            - varnish*.tar.gz
            - tools/*.suppr
            - .circleci
  tar_pkg_tools:
    description: Builds archives with the packaging tools from https://github.com/varnishcache/pkg-varnish-cache
    docker:
      - image: centos:7
    steps:
      - add_ssh_keys:
          fingerprints:
            - "11:ed:57:75:32:81:9d:d0:a4:5e:af:15:4b:d8:74:27"
      - run:
          name: Grab the pkg repo
          command: |
            yum install -y git
            mkdir -p ~/.ssh
            ssh-keyscan -H github.com >> ~/.ssh/known_hosts
            echo ${CIRCLE_REPOSITORY_URL}
            git clone https://github.com/varnishcache/pkg-varnish-cache.git .
            git checkout << pipeline.parameters.pkg-commit >>
            tar cvzf debian.tar.gz debian --dereference
            tar cvzf redhat.tar.gz redhat --dereference
            tar cvzf alpine.tar.gz alpine --dereference
      - persist_to_workspace:
          root: .
          paths:
            - debian.tar.gz
            - redhat.tar.gz
            - alpine.tar.gz
  package:
    parameters:
      platform:
        description: the Linux distribution, with release, e.g. debian:buster, centos:7
        type: string
      rclass:
        description: the resource class to use, usuall arm.medium or medium
        type: string
    machine:
      image: ubuntu-2004:202111-02
    resource_class: << parameters.rclass >>
    steps:
      - attach_workspace:
          at: ~/project

      - when:
          condition:
            matches:
              pattern: ^alpine.*
              value: << parameters.platform >>
          steps:
            - run:
                # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2
                name: grab the latest docker version
                command: |
                  # using https://docs.docker.com/engine/install/ubuntu/
                  sudo apt-get update
                  sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
                  curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
                  case "<< parameters.rclass >>" in
                      arm.*)  ARCH=arm64;;
                      *)      ARCH=amd64;;
                  esac
                  echo \
                    "deb [signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
                      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
                  sudo apt-get update
                  sudo apt-get install docker-ce docker-ce-cli containerd.io
      - run:
          name: Build for << parameters.platform >> on << parameters.rclass >>
          command: |
            mkdir -p packages
            case "<< parameters.platform >>" in
                debian:*|ubuntu:*)  EXT=deb ;;
                centos:*|fedora:*)  EXT=rpm ;;
                almalinux:*)        EXT=rpm ;;
                alpine:*)           EXT=apk ;;
                *)
                    echo "unrecognized platform: << parameters.platform >>"
                    exit 1
            esac

            case "<< parameters.platform >>" in
                centos:stream)      REPO=quay.io/centos/ ;;
                *)                  REPO= ;;
            esac

            case "<< parameters.rclass >>" in
                arm.*)              ARCH=arm64 ;;
                *)                  ARCH=amd64 ;;
            esac

            docker run \
              --rm \
              -it \
              -e PARAM_DIST=$(echo "<< parameters.platform >>" | cut -d: -f1) \
              -e PARAM_RELEASE=$(echo "<< parameters.platform >>" | cut -d: -f2) \
              -v$(pwd):/varnish-cache \
              --platform linux/$ARCH \
              ${REPO}<< parameters.platform >> \
              /varnish-cache/.circleci/make-$EXT-packages.sh
      - run:
          name: List created packages
          command: find ./packages -type f
      - persist_to_workspace:
          root: .
          paths:
            - "packages"
  build:
    parameters:
      prefix:
        description: the container image prefix (repository or architecture)
        type: string
        default: ""
      dist:
        description: the Linux distribution (debian|ubuntu)
        type: string
      release:
        description: the release name (buster|bullseye|bionic|focal|jammy)
        type: string
      make_target:
        description: the make target to execute during the build
        default: distcheck
        type: string
      extra_conf:
        description: platform-specific configure arguments
        default: ""
        type: string
    docker:
      - image: centos:7
    working_directory: /workspace
    steps:
      - setup_remote_docker:
          version: 20.10.11
      - run:
          name: Install docker
          command: yum install -y docker
      - checkout
      - run:
          name: Extract and build
          command: |
            docker create --name workspace -v /workspace << parameters.prefix >><< parameters.dist >>:<< parameters.release >> /bin/true
            docker cp /workspace workspace:/
            docker run --volumes-from workspace -w /workspace << parameters.prefix >><< parameters.dist >>:<< parameters.release >> sh -c '
            case "<< parameters.dist >>" in
            centos|almalinux|fedora)
                yum groupinstall -y "Development Tools"
                case "<< parameters.dist >>:<< parameters.release >>" in
                    almalinux:9)
                        dnf install -y "dnf-command(config-manager)"
                        yum config-manager --set-enabled crb
                        yum install -y diffutils
                        yum install -y epel-release
                        ;;
                    centos:stream|almalinux:8)
                        dnf install -y "dnf-command(config-manager)"
                        yum config-manager --set-enabled powertools
                        yum install -y diffutils
                        yum install -y epel-release
                        ;;
                    centos:7)
                        yum install -y epel-release
                        ;;
                esac
                yum install -y \
                    cpio \
                    automake \
                    git \
                    jemalloc-devel \
                    libedit-devel \
                    libtool \
                    libunwind-devel \
                    make \
                    pcre2-devel \
                    python3 \
                    /usr/bin/sphinx-build \
                    sudo
                ;;
            debian|ubuntu)
                export DEBIAN_FRONTEND=noninteractive
                export DEBCONF_NONINTERACTIVE_SEEN=true
                apt-get update
                apt-get install -y \
                    autoconf \
                    automake \
                    build-essential \
                    ca-certificates \
                    cpio \
                    git \
                    graphviz \
                    libedit-dev \
                    libjemalloc-dev \
                    libncurses-dev \
                    libpcre2-dev \
                    libtool \
                    libunwind-dev \
                    pkg-config \
                    python3-sphinx \
                    sudo
                ;;
            alpine)
                apk update
                apk add -q \
                    autoconf \
                    automake \
                    build-base \
                    ca-certificates \
                    cpio \
                    git \
                    gzip \
                    libedit-dev \
                    libtool \
                    libunwind-dev \
                    linux-headers \
                    pcre2-dev \
                    py-docutils \
                    py3-sphinx \
                    tar \
                    sudo
                ;;
            archlinux)
                pacman -Syu --noconfirm \
                    ca-certificates \
                    cpio \
                    git \
                    libedit \
                    libtool \
                    libunwind \
                    linux-headers \
                    pcre2 \
                    python-docutils \
                    python-sphinx \
                    tar
                ;;
            esac

            case "<< parameters.dist >>" in
            archlinux)
                useradd varnish
                ;;
            centos|almalinux|fedora)
                adduser varnish
                ;;
            *)
                adduser --disabled-password --gecos "" varnish
                ;;
            esac

            chown -R varnish:varnish .

            export ASAN_OPTIONS=abort_on_error=1,detect_odr_violation=1,detect_leaks=1,detect_stack_use_after_return=1,detect_invalid_pointer_pairs=1,handle_segv=0,handle_sigbus=0,use_sigaltstack=0,disable_coredump=0
            export LSAN_OPTIONS=abort_on_error=1,use_sigaltstack=0,suppressions=$(pwd)/tools/lsan.suppr
            export TSAN_OPTIONS=abort_on_error=1,halt_on_error=1,use_sigaltstack=0,suppressions=$(pwd)/tools/tsan.suppr
            export UBSAN_OPTIONS=halt_on_error=1,print_stacktrace=1,use_sigaltstack=0,suppressions=$(pwd)/tools/ubsan.suppr

            sudo -u varnish \
                autoreconf -i -v
            sudo -u varnish \
                ./configure \
                << pipeline.parameters.configure_args >> \
                << parameters.extra_conf >>
            sudo -u varnish \
                --preserve-env=ASAN_OPTIONS,LSAN_OPTIONS,TSAN_OPTIONS,UBSAN_OPTIONS \
                make << parameters.make_target >> VERBOSE=1 -j 4 -k \
                DISTCHECK_CONFIGURE_FLAGS="<< pipeline.parameters.configure_args >> \
                << parameters.extra_conf >>"
            '

  collect_packages:
    docker:
      - image: centos:7
    steps:
      - attach_workspace:
          at: ~/project
      - run: ls -la ~/project/
      - run:
          name: Tar the packages
          command: |
              tar cvzf packages.tar.gz packages
      - store_artifacts:
          destination: packages.tar.gz
          path: packages.tar.gz


workflows:
  version: 2
  commit:
    unless: &packaging_cond
      or:
        - << pipeline.parameters.build-pkgs >>
        - << pipeline.parameters.dist-url >>
    jobs:
      - build:
          name: build_centos_7
          dist: centos
          release: "7"
      - build:
          name: build_centos_stream
          prefix: quay.io/centos/
          dist: centos
          release: stream
      - build:
          name: build_almalinux_8
          dist: almalinux
          release: "8"
      - build:
          name: build_almalinux_9
          dist: almalinux
          release: "9"
      # fedora is our witness
      - build:
          name: build_fedora_latest
          dist: fedora
          release: latest
          make_target: witness.dot
      - build:
          name: build_fedora_rawhide
          dist: fedora
          release: rawhide
      # latest debian uses sanitizers
      - build:
          name: build_debian_buster
          dist: debian
          release: buster
      - build:
          name: build_debian_bullseye
          dist: debian
          release: bullseye
      - build:
          name: build_debian_bookworm
          dist: debian
          release: bookworm
          extra_conf: --enable-asan --enable-ubsan --enable-workspace-emulator
      # oldest ubuntu goes 32bit
      - build:
          name: build_ubuntu_bionic
          prefix: i386/
          dist: ubuntu
          release: bionic
      - build:
          name: build_ubuntu_focal
          dist: ubuntu
          release: focal
      - build:
          name: build_ubuntu_jammy
          dist: ubuntu
          release: jammy
      - build:
          name: build_alpine
          dist: alpine
          release: "latest"
          extra_conf: --without-contrib
      - build:
          name: build_archlinux
          dist: archlinux
          release: base-devel
  packaging:
    when: *packaging_cond
    jobs: &packaging_jobs
      - dist
      - tar_pkg_tools
      - package:
          name: << matrix.platform >> packages (<< matrix.rclass >>)
          requires:
            - dist
            - tar_pkg_tools
          matrix:
            parameters:
              platform:
                - ubuntu:bionic
                - ubuntu:focal
                - ubuntu:jammy
                - debian:buster
                - debian:bullseye
                - debian:bookworm
                - centos:7
                - centos:stream
                - almalinux:8
                - almalinux:9
                - fedora:latest
                - alpine:3
              rclass:
                - arm.medium
                - medium
      - collect_packages:
          requires:
            - package
  nightly:
    triggers:
      - schedule:
          cron: "0 4 * * *"
          filters:
            branches:
              only:
                - master
    jobs: *packaging_jobs
