name: test

on:
  push:
    branches:
      - integration
      - '**-ci'
      - '**-cig'
  pull_request:
    branches:
      - integration
      - '**-ci'
      - '**-cig'

jobs:
  test:
    runs-on: ubuntu-20.04

    strategy:
      # Let all the jobs run to completion even if one fails
      fail-fast: false

      # The first jobs should be the canaries in the coal mine, i.e. the most likely to fail if there are problems in the code. They
      # should also be a good mix of unit, integration, and documentation tests.
      #
      # In general tests should be ordered from slowest to fastest. This does not make a difference for testing a single commit, but
      # when multiple commits are being tested it is best to have the slowest jobs first so that as jobs become available they will
      # tackle the slowest tests first.
      matrix:
        include:
          # All unit tests (without coverage) for 32-bit
          - param: test --vm=d10 --param=no-performance --param=c-only

          # All integration tests for 32-bit
          - param: test --vm=d10 --param=module=mock --param=module=integration

          # Debian/Ubuntu documentation
          - param: doc --vm=u20

          # All integration tests
          - param: test --vm=u22 --param=build-package --param=module=mock --param=module=integration

          # All unit tests with coverage, backtrace and alternate timezone
          - param: test --vm=u22 --param=c-only --param=no-valgrind --param=tz=America/New_York

          # All unit tests with valgrind (disable coverage and backtrace for performance)
          - param: test --vm=u22 --param=c-only --param=no-coverage --param=no-back-trace

          # All unit tests on the newest gcc available
          - param: test --vm=f38 --param=c-only --param=no-valgrind --param=no-coverage --param=no-performance

          # RHEL documentation
          - param: doc --vm=rh8

          # All integration tests
          - param: test --vm=rh7 --param=module=mock --param=module=integration

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
        with:
          path: pgbackrest

      - name: Run Test
        run: cd ${HOME?} && ${GITHUB_WORKSPACE?}/pgbackrest/test/ci.pl ${{matrix.param}} --param=build-max=2

      # Output the coverage report on failure in case the failure was caused by lack of coverage. This is not ideal since the report
      # needs to be copied from the log output into an HTML file where it can be viewed, but better than nothing.
      - name: Coverage Report
        if: failure()
        run: |
          cat ${GITHUB_WORKSPACE?}/pgbackrest/test/result/coverage/coverage.html

  # Basic tests on other architectures using emulation. The emulation is so slow that running all the unit tests would be too
  # expensive, but this at least shows that the build works and some of the more complex tests run. In particular, it is good to
  # test on one big-endian architecture to be sure that checksums are correct.
  arch:
    runs-on: ubuntu-20.04

    strategy:
      matrix:
        include:
          - arch: ppc64le
            distro: ubuntu20.04
          - arch: s390x
            distro: ubuntu20.04

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
        with:
          path: pgbackrest

      - name: Run Test
        uses: uraimo/run-on-arch-action@v2
        id: runcmd
        with:
          arch: ${{matrix.arch}}
          distro: ${{matrix.distro}}

          # Cache builds
          githubToken: ${{github.token}}

          install: |
            apt-get update
            DEBCONF_NONINTERACTIVE_SEEN=true DEBIAN_FRONTEND=noninteractive apt-get install -y perl sudo libxml-checker-perl libyaml-perl rsync zlib1g-dev libssl-dev libxml2-dev libpq-dev libyaml-dev pkg-config make gcc ccache meson git liblz4-dev liblz4-tool zstd libzstd-dev bzip2 libbz2-dev

          run: |
            git config --global --add safe.directory ${GITHUB_WORKSPACE?}/pgbackrest
            ${GITHUB_WORKSPACE?}/pgbackrest/test/test.pl --min-gen --no-valgrind --no-coverage --no-optimize --build-max=2 --module=command --test=backup
            ${GITHUB_WORKSPACE?}/pgbackrest/test/test.pl --min-gen --no-valgrind --no-coverage --no-optimize --build-max=2 --module=postgres --test=interface

  # Run meson unity build to check for errors, unused functions, and externed functions
  unity:
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
        with:
          path: pgbackrest

      - name: Install
        run: |
          sudo apt-get update
          DEBCONF_NONINTERACTIVE_SEEN=true DEBIAN_FRONTEND=noninteractive sudo apt-get install -y zlib1g-dev libssl-dev libxml2-dev libpq-dev libyaml-dev pkg-config meson liblz4-dev libzstd-dev libbz2-dev

      - name: Build
        run: |
          meson setup --unity=on -Dwerror=true build ${GITHUB_WORKSPACE?}/pgbackrest
          ninja -vC build

      - name: Check
        run: |
          diff ${GITHUB_WORKSPACE?}/pgbackrest/.github/workflows/symbol.out <(nm -gj --defined-only build/src/pgbackrest)

  # Check that code is correctly formatted
  code-format:
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
        with:
          path: pgbackrest

      - name: Check
        run: |
          cd ${HOME?} && ${GITHUB_WORKSPACE?}/pgbackrest/test/ci.pl test --param=code-format-check

  codeql:
    runs-on: ubuntu-latest

    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language:
          - cpp

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Install Packages
        run: sudo apt-get install -y --no-install-recommends libyaml-dev

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: ${{matrix.language}}

      - name: Build
        run: ${GITHUB_WORKSPACE?}/src/configure && make -j 2

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
