name: Regression Linux i386
"on":
  schedule:
    # run daily 0:00 on main branch
    # Since we use the date as a part of the cache key to ensure no
    # stale cache entries hiding build failures we need to make sure
    # we have a cache entry present before workflows that depend on cache
    # are run.
    - cron: '0 0 * * *'
  push:
    branches:
      - main
      - ?.*.x
      - trigger/regression
    paths-ignore:
      - '**.md'
      - 'LICENSE*'
      - NOTICE
  pull_request:
    paths-ignore:
      - '**.md'
      - 'LICENSE*'
      - NOTICE
jobs:
  config:
    runs-on: ubuntu-latest
    outputs:
      pg_latest: ${{ github.event_name == 'pull_request' && steps.setter.outputs.PG_LATEST_ONLY || steps.setter.outputs.PG_LATEST }}
    steps:
    - name: Checkout source code
      uses: actions/checkout@v4
    - name: Read configuration
      id: setter
      run: python .github/gh_config_reader.py

  regress_linux_32bit:
    name: PG${{ matrix.pg }} ${{ matrix.build_type }} linux-i386
    runs-on: ubuntu-latest
    needs: config
    container:
      image: i386/debian:bookworm-slim
      options: --privileged --ulimit core=-1:-1 --ulimit fsize=-1:-1
      env:
        PG_SRC_DIR: pgbuild
        PG_INSTALL_DIR: postgresql
        CLANG: clang-14
        CC: clang-14
        CXX: clang++-14
        DEBIAN_FRONTEND: noninteractive
        # vectorized_aggregation has different output on i386 because int8 is by
        # reference and currently it cannot be used for vectorized hash grouping.
        # vector_agg_text and vector_agg_groupagg use the UMASH hashing library
        # that we can't compile on i386.
        # For the same reason of different hashing, we ignore the results of
        # several bloom filter tests as well.
        IGNORES: >-
          append-*
          bgw_db_scheduler*
          columnar_scan_cost
          compress_bloom_sparse_compat
          compress_bloom_sparse_debug
          compress_qualpushdown_saop
          compression_allocation
          merge_append_partially_compressed
          net
          pg_dump
          telemetry
          transparent_decompress_chunk-*
          transparent_decompression-*
          uncompressed_size
          vector_agg_byte
          vector_agg_filter
          vector_agg_groupagg
          vector_agg_grouping
          vector_agg_text
          vector_agg_uuid
          vectorized_aggregation
          ${{ matrix.pg < 16 && 'columnar_scan_cost' || '' }}
        SKIPS: chunk_adaptive histogram_test-*
        EXTENSIONS: "postgres_fdw test_decoding"
    strategy:
      matrix:
        pg: ${{ fromJson(needs.config.outputs.pg_latest) }}
        build_type: [ Debug ]
      fail-fast: false

    steps:

    # /__e/node16/bin/node (used by actions/checkout@v4) needs 64-bit libraries
    - name: Install 64-bit libraries for GitHub actions
      run: |
        apt-get update
        apt-get install -y lib64atomic1 lib64gcc-s1 lib64stdc++6 libc6-amd64 jq

    - name: Install build dependencies
      run: |
        PG_MAJOR=$(echo "${{ matrix.pg }}" | sed -e 's![.].*!!')
        echo '/tmp/core.%h.%e.%t' > /proc/sys/kernel/core_pattern
        apt-get install -y gcc make cmake libssl-dev libipc-run-perl \
          libtest-most-perl sudo gdb git wget gawk lbzip2 flex bison lcov base-files \
          locales clang-14 llvm-14 llvm-14-dev llvm-14-tools postgresql-client pkgconf \
          icu-devtools

    - name: Checkout TimescaleDB
      uses: actions/checkout@v4

    # We are going to rebuild Postgres daily, so that it doesn't suddenly break
    # ages after the original problem.
    - name: Get date for build caching
      id: get-date
      run: |
        echo "date=$(date +"%d")" >> $GITHUB_OUTPUT

    # we cache the build directory instead of the install directory here
    # because extension installation will write files to install directory
    # leading to a tainted cache
    - name: Cache PostgreSQL ${{ matrix.pg }} ${{ matrix.build_type }}
      id: cache-postgresql
      uses: actions/cache@v4
      with:
        path: ~/${{ env.PG_SRC_DIR }}
        key: "linux-32-bit-postgresql-${{ matrix.pg }}-${{ matrix.cc }}\
          -${{ steps.get-date.outputs.date }}-${{ hashFiles('.github/**') }}"

    - name: Build PostgreSQL ${{ matrix.pg }}
      if: steps.cache-postgresql.outputs.cache-hit != 'true'
      run: |
        wget -q -O postgresql.tar.bz2 \
          https://ftp.postgresql.org/pub/source/v${{ matrix.pg }}/postgresql-${{ matrix.pg }}.tar.bz2
        mkdir -p ~/$PG_SRC_DIR
        tar --extract --file postgresql.tar.bz2 --directory ~/$PG_SRC_DIR --strip-components 1
        cd ~/$PG_SRC_DIR
        # When building on i386 with the clang compiler, Postgres requires -msse2 to be used
        ./configure --prefix=$HOME/$PG_INSTALL_DIR --with-openssl \
          --without-readline --without-zlib --without-libxml --enable-cassert \
          --enable-debug --with-llvm --without-icu LLVM_CONFIG=llvm-config-14 CFLAGS="-msse2"
        make -j $(getconf _NPROCESSORS_ONLN)
        for ext in ${EXTENSIONS}; do
          make -j $(getconf _NPROCESSORS_ONLN) -C contrib/${ext}
        done

    - name: Install PostgreSQL ${{ matrix.pg }}
      run: |
        useradd postgres
        cd ~/$PG_SRC_DIR
        make install
        for ext in ${EXTENSIONS}; do
          make -C contrib/${ext} install
        done
        chown -R postgres:postgres $HOME/$PG_INSTALL_DIR
        sed -i 's/^# *\(en_US.UTF-8\)/\1/' /etc/locale.gen
        locale-gen

    - name: Upload config.log
      if: always() && steps.cache-postgresql.outputs.cache-hit != 'true'
      uses: actions/upload-artifact@v4
      with:
        name: config.log linux-i386 PG${{ matrix.pg }}
        path: ~/${{ env.PG_SRC_DIR }}/config.log

    - name: Build TimescaleDB
      run: |
        # The owner of the checkout directory and the files do not match. Add the directory to
        # Git's "safe.directory" setting. Otherwise git would complain about
        # 'detected dubious ownership in repository'
        git config --global --add safe.directory $(pwd)
        ./bootstrap -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" \
          -DPG_SOURCE_DIR=~/$PG_SRC_DIR -DPG_PATH=~/$PG_INSTALL_DIR \
          -DREQUIRE_ALL_TESTS=ON \
          -DTEST_PG_LOG_DIRECTORY="$(readlink -f .)"
        make -j $(getconf _NPROCESSORS_ONLN) -C build
        make -C build install
        chown -R postgres:postgres .

    - name: Upload CMake Logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: CMake Logs linux-i386 PG${{ matrix.pg }}
        path: |
            build/CMakeCache.txt
            build/CMakeFiles/CMakeConfigureLog.yaml
            build/CMakeFiles/CMakeError.log
            build/CMakeFiles/CMakeOutput.log
            build/compile_commands.json

    - name: make installcheck
      id: installcheck
      shell: bash
      run: |
        set -o pipefail
        export LANG=C.UTF-8
        #
        # Even disabling parallel plans the Sort Method on 32bits
        # is always 'still in progress' for PG17 and PG18. So for now added
        # those tests to SKIPS.
        #
        PG_MAJOR=$(echo "${{ matrix.pg }}" | sed -e 's![.].*!!')
        if [ ${PG_MAJOR} -eq 17 ]; then
          SKIPS="${SKIPS} constraint_exclusion_prepared-17 ordered_append*"
        fi
        if [ ${PG_MAJOR} -eq 18 ]; then
          SKIPS="${SKIPS} constraint_exclusion_prepared-18 ordered_append*"
        fi
        # PostgreSQL cannot be run as root. So, switch to postgres user.
        runuser -u postgres -- \
          make -k -C build installcheck IGNORES="${IGNORES}" \
            SKIPS="${SKIPS}" PSQL="${HOME}/${PG_INSTALL_DIR}/bin/psql" \
            | tee installcheck.log

    - name: Show regression diffs
      if: always()
      id: collectlogs
      shell: bash
      run: |
        find . -name regression.diffs -exec cat {} + > regression.log

        if [[ -s regression.log ]]; then echo "regression_diff=true" >>$GITHUB_OUTPUT; fi
        grep -e 'FAILED' -e 'failed (ignored)' -e 'not ok' installcheck.log || true
        cat regression.log

    - name: Save regression diffs
      if: always() && steps.collectlogs.outputs.regression_diff == 'true'
      uses: actions/upload-artifact@v4
      with:
        name: Regression diff linux-i386 PG${{ matrix.pg }}
        path: |
          regression.log
          installcheck.log

    - name: Save PostgreSQL log
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: PostgreSQL log linux-i386 PG${{ matrix.pg }}
        path: postmaster.*

    - name: Stack trace Linux
      if: always()
      shell: bash
      run: |
        # wait in case there are in-progress coredumps
        sleep 10
        if compgen -G "/tmp/core*" > /dev/null; then
          PG_MAJOR=$(echo "${{ matrix.pg }}" | sed -e 's![.].*!!')
          for file in /tmp/core*
          do
            gdb "${HOME}/${PG_INSTALL_DIR}/bin/postgres" -c $file <<<"
          set verbose on
          set trace-commands on
          show debug-file-directory
          printf "'"'"query = '%s'\n\n"'"'", debug_query_string
          bt full

          # We try to find ExceptionalCondition frame to print the failed condition
          # for searching in logs.
          frame function ExceptionalCondition
          printf "'"'"condition = '%s'\n"'"'", conditionName

          # Hopefully now we should be around the failed assertion, print where
          # we are.
          up 1
          list
          info args
          info locals
            " 2>&1 | tee -a stacktrace.log
          done
          echo "coredumps=true" >>$GITHUB_OUTPUT
          exit 1
        fi


    - name: Coredumps
      if: always() && steps.coredumps.outputs.coredumps == 'true'
      uses: actions/upload-artifact@v4
      with:
        name: Coredumps linux-i386 PG${{ matrix.pg }}
        path: coredumps

    - name: Save stacktraces
      if: always() && steps.coredumps.outputs.coredumps == 'true'
      uses: actions/upload-artifact@v4
      with:
        name: Stacktraces linux-i386 PG${{ matrix.pg }}
        path: stacktrace.log

    - name: Save TAP test logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: TAP test logs ${{ matrix.os }} ${{ matrix.name }} ${{ matrix.pg }}
        path: |
          build/test/tmp_check/log
          build/tsl/test/tmp_check/log

    - name: Upload test results to the database
      if: always()
      shell: bash
      env:
        # GitHub Actions allow you neither to use the env context for the job name,
        # nor to access the job name from the step context, so we have to
        # duplicate it to work around this nonsense.
        JOB_NAME: PG${{ matrix.pg }} ${{ matrix.build_type }} linux-i386
        CI_STATS_DB: ${{ secrets.CI_STATS_DB }}
        GITHUB_EVENT_NAME: ${{ github.event_name }}
        GITHUB_REF_NAME: ${{ github.ref_name }}
        GITHUB_REPOSITORY: ${{ github.repository }}
        GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }}
        GITHUB_RUN_ID: ${{ github.run_id }}
        GITHUB_RUN_NUMBER: ${{ github.run_number }}
        JOB_STATUS: ${{ job.status }}
      run: |
        if [[ "${{ github.event_name }}" == "pull_request" ]] ;
        then
            GITHUB_PR_NUMBER="${{ github.event.number }}"
        else
            GITHUB_PR_NUMBER=0
        fi
        export GITHUB_PR_NUMBER
        scripts/upload_ci_stats.sh
