view .github/workflows/make.yaml @ 32070:bc46d7c2768f stable

GitHub-CI (macos): Fail job if test suite doesn't pass. * .github/workflow/make.yaml (macos): Fail job for any failure or regression in the test suite (instead of just emitting a warning).
author Markus Mützel <markus.muetzel@gmx.de>
date Tue, 02 May 2023 11:38:24 +0200
parents a46c30311908
children 31a68f3ced07 6f9f2e2c2ae8
line wrap: on
line source

name: make
on: [push]
concurrency: ci-${{ github.ref }}

jobs:

  ubuntu:
    runs-on: ${{ matrix.os }}

    strategy:
      # Allow other runners in the matrix to continue if some fail
      fail-fast: false

      matrix:
        # For available GitHub-hosted runners, see:
        # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
        os: [ubuntu-22.04, ubuntu-20.04]
        compiler: [gcc, clang]
        include:
          - compiler: gcc
            compiler-pkgs: "g++ gcc"
            cc: "gcc"
            cxx: "g++"
            extra-config-flags: ""
          - compiler: clang
            compiler-pkgs: "clang libc++-dev libc++abi-dev"
            cc: "clang"
            cxx: "clang++ -stdlib=libc++"
            extra-config-flags: "--without-spqr --without-magick"
          # "ccache" on Ubuntu 20.04 doesn't compress the cache.
          # Clang seems to generally require less cache size (smaller object files?).
          - ccache-max: 1.2G
          - os: ubuntu-20.04
            compiler: gcc
            ccache-max: 6G
          - os: ubuntu-22.04
            compiler: gcc
            ccache-max: 1.2G
          - os: ubuntu-20.04
            compiler: clang
            ccache-max: 3G
          - os: ubuntu-22.04
            compiler: clang
            ccache-max: 400M

    name: ${{ matrix.os }} ${{ matrix.compiler }}

    env:
      CC: ${{ matrix.cc }}
      CXX: ${{ matrix.cxx }}

    steps:
      - name: checkout repository
        uses: actions/checkout@v3

      - name: install dependencies
        env:
          COMPILER_PKGS: ${{ matrix.compiler-pkgs }}
        run: |
          sudo apt -qq update
          sudo apt install -y $COMPILER_PKGS autoconf automake bison ccache \
            dvipng epstool fig2dev flex gfortran gnuplot-x11 gperf gzip \
            icoutils libarpack2-dev libblas-dev libcurl4-gnutls-dev \
            libfftw3-dev libfltk1.3-dev libfontconfig1-dev libfreetype6-dev \
            libgl1-mesa-dev libgl2ps-dev libglpk-dev libgraphicsmagick++1-dev \
            libhdf5-dev liblapack-dev libosmesa6-dev libpcre2-dev \
            libqhull-dev libqscintilla2-qt5-dev libqrupdate-dev \
            libreadline-dev librsvg2-bin libsndfile1-dev libsuitesparse-dev \
            libsundials-dev libtool libxft-dev make openjdk-8-jdk \
            perl portaudio19-dev pstoedit qtbase5-dev qttools5-dev \
            qttools5-dev-tools rapidjson-dev rsync tar texinfo \
            texlive-latex-extra xvfb zlib1g-dev

      - name: prepare ccache
        # create key with human readable timestamp
        # used in action/cache/restore and action/cache/save steps
        id: ccache-prepare
        run: |
          echo "key=ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:$(date +"%Y-%m-%d_%H-%M-%S"):${{ github.sha }}" >> $GITHUB_OUTPUT

      - name: restore ccache
        # setup the github cache used to maintain the ccache from one job to the next
        uses: actions/cache/restore@v3
        with:
          path: ~/.ccache
          key: ${{ steps.ccache-prepare.outputs.key }}
          restore-keys: |
            ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}
            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable

      - name: configure ccache
        env:
          CCACHE_MAX: ${{ matrix.ccache-max }}
        run: |
          test -d ~/.ccache || mkdir ~/.ccache
          echo "max_size = $CCACHE_MAX" >> ~/.ccache/ccache.conf
          ccache -s
          echo "/usr/lib/ccache" >> $GITHUB_PATH

      - name: bootstrap
        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap

      - name: configure
        timeout-minutes: 30
        run: |
          echo $PATH
          echo which ccache
          which ccache
          which $CC
          echo $CC --version
          $CC --version
          which ${CXX% *}
          echo ${CXX% *} --version
          ${CXX% *} --version
          which gfortran
          echo gfortran --version
          gfortran --version
          mkdir .build
          cd .build && ../configure \
            CPPFLAGS="-I/usr/include/hdf5/serial -I/usr/include/suitesparse" \
            LDFLAGS="-L/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/hdf5/serial" \
            ${{ matrix.extra-config-flags }}

      - name: build
        # Parallel make seems to fail intermittently when creating the figures
        # for the manual. The error message says it fails to connect to a
        # display. Maybe an xvfb issue?
        # Use single job make for now which seems to work more reliably.
        run: XDG_RUNTIME_DIR=$RUNNER_TEMP xvfb-run -a make -C ./.build all V=1

      - name: ccache status
        run: ccache -s

      - name: save ccache
        # Save the cache after we are done (successfully) building
        uses: actions/cache/save@v3
        with:
          path: ~/.ccache
          key: ${{ steps.ccache-prepare.outputs.key }}

      - name: check
        timeout-minutes: 60
        run: XDG_RUNTIME_DIR=$RUNNER_TEMP xvfb-run -a make -C ./.build check | tee ./test-suite.log

      - name: display test log
        continue-on-error: true
        # Displaying the log shouldn't take long. Cancel the step if it does.
        timeout-minutes: 5
        run: cat ./.build/test/fntests.log

      - name: analyze test suite results
        # Make sure the test summary lists 0 "FAIL"s and no "REGRESSION"
        run:  |
          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || exit 1
          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || exit 1
          echo No unknown failing tests.

      - name: test history file creation
        # see bug #62365
        # Pipe to an interactive session to trigger appending the command to
        # the history.  This will trigger the creation of a history file.
        run:  |
          echo "history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')" | ./.build/run-octave -i
          [ -f ./a/b/c/history ] || echo "::warning::Creating history file failed"


  macos:
    runs-on: ${{ matrix.os }}

    name: ${{ matrix.os }}

    strategy:
      # Allow other runners in the matrix to continue if some fail
      fail-fast: false

      matrix:
        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
        os: [macos-13, macos-12]
        # Most (or all) homebrew packages are compiled with clang and link
        # against libc++.  So we also use clang to avoid issues with symbols
        # that don't match.
        # compiler: [real-gcc, clang]
        compiler: [clang]
        include:
          # - compiler: real-gcc
          #   cc: "/usr/local/bin/gcc-10"
          #   cxx: "/usr/local/bin/g++-10"
          #   cppflags: "-I/usr/local/opt/hdf5/include -I/usr/local/opt/gl2ps/include -I/usr/local/opt/glpk/include -I/usr/local/opt/pcre/include -I/usr/local/opt/qscintilla2/include -I/usr/local/opt/suite-sparse/include -I/usr/local/opt/sundials/include"
          #   ldflags: "-L/usr/local/opt/hdf5/lib -L/usr/local/opt/gl2ps/lib -L/usr/local/opt/glpk/lib -L/usr/local/opt/pcre/lib -L/usr/local/opt/qscintilla2/lib -L/usr/local/opt/suite-sparse/lib -L/usr/local/opt/sundials/lib"
          - compiler: clang
            cc: "clang"
            cxx: "clang++"

    env:
      CC: ${{ matrix.cc }}
      CXX: ${{ matrix.cxx }}

    steps:
      - name: checkout repository
        uses: actions/checkout@v3

      - name: install dependencies
        # This step sometimes takes long and still recovers. But sometimes it
        # seems to hang indefinitely.
        # Use a pretty long timeout (but still less than the default 6 hours).
        timeout-minutes: 75

        # Homebrew's Python conflicts with the Python that comes pre-installed
        # on the GitHub runners. Some of Octave's dependencies depend on
        # different versions of Homebrew's Python. Enforce using the ones from
        # Homebrew to avoid errors on updates.
        # See: https://github.com/orgs/Homebrew/discussions/3928

        # It looks like "gfortran" isn't working correctly unless "gcc" is
        # re-installed.

        # See also: https://formulae.brew.sh/formula/octave#default
        # The packages are listed in (alphabetically sorted) blocks:
        # The first block is for "direct" dependencies.
        # The second block is for additional dependencies needed when building from a release tarball.
        # The third block is for additional dependencies needed when building from a repository checkout.
        run: |
          brew update
          brew install --overwrite python@3.10 python@3.11
          brew reinstall gcc
          brew install arpack epstool fftw fig2dev fltk fontconfig freetype \
            ghostscript gl2ps glpk gnuplot graphicsmagick hdf5 libsndfile \
            libtool openblas pcre2 portaudio pstoedit qhull qrupdate \
            qscintilla2 qt@5 rapidjson readline suite-sparse sundials texinfo \
            ccache gnu-sed openjdk pkg-config \
            automake autoconf bison gettext icoutils librsvg mactex-no-gui
          eval "$(/usr/libexec/path_helper)"
          echo "/Library/TeX/texbin" >> $GITHUB_PATH
          echo "/usr/local/opt/qt@5/bin" >> $GITHUB_PATH
          echo "/usr/local/opt/texinfo/bin" >> $GITHUB_PATH
          echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH
          echo "/usr/local/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH

      - name: prepare ccache
        # create key with human readable timestamp
        # used in action/cache/restore and action/cache/save steps
        id: ccache-prepare
        run: |
          echo "key=ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:$(date +"%Y-%m-%d_%H-%M-%S"):${{ github.sha }}" >> $GITHUB_OUTPUT

      - name: restore ccache
        # setup the github cache used to maintain the ccache from one job to the next
        uses: actions/cache/restore@v3
        id: restore-ccache
        with:
          path: /Users/runner/Library/Caches/ccache
          key: ${{ steps.ccache-prepare.outputs.key }}
          restore-keys: |
            ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}
            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable

      - name: configure ccache
        # The cache doesn't seem to compress well on macOS. Is it already compressed?
        # Limit the maximum size to avoid exceeding the total cache limits.
        run: |
          test -d /Users/runner/Library/Preferences/ccache || mkdir /Users/runner/Library/Preferences/ccache
          echo "max_size = 0.9G" >> /Users/runner/Library/Preferences/ccache/ccache.conf
          ccache -s
          echo "$(brew --prefix)/opt/ccache/libexec" >> $GITHUB_PATH

      - name: bootstrap
        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap

      - name: configure
        timeout-minutes: 30
        env:
          MY_CPPFLAGS: ${{ matrix.cppflags }}
          MY_LDFLAGS: ${{ matrix.ldflags }}
        # This is a hodgepodge of configure flags put together from the
        # buildbot rules:
        # https://hg.octave.org/octave-buildbot/file/tip/master.cfg#l543
        # And the homebrew formula:
        # https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/octave.rb
        # Amended with additional flags that seem to be needed.
        # Not all of those might be needed or be correct.
        # SUNDIALS >= 6.5.0 doesn't compile with the default flags determined
        # by the configure script. Set CXX manually to enable building with it.
        run: |
          echo $PATH
          echo which ccache
          which ccache
          which $CC
          echo $CC --version
          $CC --version
          which $CXX
          echo $CXX --version
          $CXX --version
          which gfortran
          echo gfortran --version
          gfortran --version
          mkdir .build
          cd .build && ../configure \
            CXX="$CXX -std=gnu++14" \
            F77="ccache gfortran" \
            CPPFLAGS="-I/usr/local/opt/gettext/include -I/usr/local/opt/icu4c/include -I/usr/local/opt/qt@5/include -I/usr/local/opt/readline/include -I/usr/local/opt/sqlite/include $MY_CPPFLAGS" \
            CXXFLAGS="-O2 -g" \
            LDFLAGS="-L/usr/local/lib -L/usr/local/opt/bison/lib -L/usr/local/opt/gettext/lib -L/usr/local/opt/icu4c/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/sqlite/lib $MY_LDFLAGS" \
            PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/qt@5/lib/pkgconfig" \
            QCOLLECTIONGENERATOR="qhelpgenerator" \
            --with-x=no \
            --with-blas="-L/usr/local/opt/openblas/lib -lopenblas" \
            --with-java-homedir="/usr/local/opt/openjdk" \
            --prefix="${HOME}/usr"

      - name: build
        run: make -C ./.build all -j3 V=1

      - name: ccache status
        run: ccache -s

      - name: save ccache
        # Save the cache after we are done (successfully) building
        uses: actions/cache/save@v3
        with:
          path: /Users/runner/Library/Caches/ccache
          key: ${{ steps.ccache-prepare.outputs.key }}

      - name: check
        # Continuing on error in this step means that jobs will be "green" even
        # if the test suite crashes.  But if we don't continue, we'll loose the
        # ccache and other jobs will be cancelled, too.
        # It would be nice if we could mark the job as "yellow" (and continue)
        # in that case.  The second best thing is to display a warning in the
        # job summary (see below).
        continue-on-error: true
        timeout-minutes: 60
        run: |
          echo 'makeinfo_program ("/usr/local/opt/texinfo/bin/makeinfo");' >> ./scripts/startup/site-rcfile
          make -C ./.build check | tee ./test-suite.log

      - name: display test log
        continue-on-error: true
        # Displaying the log shouldn't take long. Cancel the step if it does.
        timeout-minutes: 5
        run: cat ./.build/test/fntests.log

      - name: analyze test suite results
        # Make sure the test summary lists 0 "FAIL"s and no "REGRESSION"
        run: |
          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || exit 1
          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || exit 1
          echo Finished analyzing test suite results.

      - name: test history file creation
        # see bug #62365
        # Pipe to an interactive session to trigger appending the command to
        # the history.  This will trigger the creation of a history file.
        run:  |
          echo "history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')" | ./.build/run-octave -i
          [ -f ./a/b/c/history ] || echo "::warning::Creating history file failed"


  mingw:
    runs-on: ${{ matrix.os }}

    defaults:
      run:
        # Use MSYS2 as default shell
        shell: msys2 {0}

    strategy:
      # Allow other runners in the matrix to continue if some fail
      fail-fast: false

      matrix:
        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
        os: [windows-latest]
        msystem: [MINGW64, MINGW32]
        include:
          - msystem: MINGW64
            mingw-prefix: mingw64
            target-triplet: x86_64-w64-mingw32
            target-prefix: mingw-w64-x86_64
            cc: gcc
            cxx: g++
            f77: gfortran
          - msystem: MINGW32
            mingw-prefix: mingw32
            target-triplet: i686-w64-mingw32
            target-prefix: mingw-w64-i686
            cc: gcc
            cxx: g++
            f77: gfortran

    env:
      CHERE_INVOKING: 1
      CC:  ${{ matrix.cc }}
      CXX:  ${{ matrix.cxx }}
      F77:  ${{ matrix.f77 }}
      TARGET_TRIPLET:  ${{ matrix.target-triplet }}
      # perl uses cmd shell by default
      PERL5SHELL: bash -l -c

    steps:
      - name: get CPU name
        # The runners for the 32-bit target sometimes get stuck in configure
        # when using the Fortran compiler.
        # Does that error depend on the processor of the selected runner?
        shell: pwsh
        run : |
          Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name

      - name: install MSYS2 build environment
        uses: msys2/setup-msys2@v2
        with:
          update: true

          # Use pre-installed version to save disc space on partition with source.
          # We need that space for building.
          release: false

          # The packages are listed in (alphabetically sorted) blocks:
          # The first block is for mandatory dependencies.
          # The second block is for optional dependencies needed when building from a release tarball.
          # The third block is for additional dependencies needed when building from a repository checkout.
          # The fourth block is for additional run-time dependencies (to run test suite) that aren't needed to build.
          install: >-
            base-devel
            ${{ matrix.target-prefix }}-autotools
            ${{ matrix.target-prefix }}-cc
            ${{ matrix.target-prefix }}-gcc-fortran
            ${{ matrix.target-prefix }}-gperf
            ${{ matrix.target-prefix }}-lapack
            ${{ matrix.target-prefix }}-openblas
            ${{ matrix.target-prefix }}-pcre2

            ${{ matrix.target-prefix }}-arpack
            ${{ matrix.target-prefix }}-curl
            ${{ matrix.target-prefix }}-fftw
            ${{ matrix.target-prefix }}-fltk
            ${{ matrix.target-prefix }}-gl2ps
            ${{ matrix.target-prefix }}-glpk
            ${{ matrix.target-prefix }}-ghostscript
            ${{ matrix.target-prefix }}-gnuplot
            ${{ matrix.target-prefix }}-graphicsmagick
            ${{ matrix.target-prefix }}-hdf5
            ${{ matrix.target-prefix }}-libsndfile
            ${{ matrix.target-prefix }}-portaudio
            ${{ matrix.target-prefix }}-qhull
            ${{ matrix.target-prefix }}-qrupdate
            ${{ matrix.target-prefix }}-qscintilla
            ${{ matrix.target-prefix }}-qt5-base
            ${{ matrix.target-prefix }}-qt5-imageformats
            ${{ matrix.target-prefix }}-qt5-svg
            ${{ matrix.target-prefix }}-qt5-tools
            ${{ matrix.target-prefix }}-rapidjson
            ${{ matrix.target-prefix }}-suitesparse
            ${{ matrix.target-prefix }}-sundials

            git
            ${{ matrix.target-prefix }}-ccache
            ${{ matrix.target-prefix }}-icoutils
            ${{ matrix.target-prefix }}-librsvg
            texinfo

            unzip
            zip

          msystem: ${{ matrix.msystem }}

      - name: install run-time dependency "mesa"
        # The mesa3d OpenGL driver seems to be needed for correct off-screen
        # rendering.  But the version from MSYS2 currently crashes Octave on
        # MINGW32.  See: https://github.com/msys2/MINGW-packages/issues/10876
        # Without it, `test getframe` "just" fails without crashing Octave.
        # So, skip installation for MINGW32.
        if: matrix.msystem != 'MINGW32'
        env:
          TARGET_PREFIX: ${{ matrix.target-prefix }}
        run: pacman --noconfirm -S ${TARGET_PREFIX}-mesa

      - name: checkout repository
        uses: actions/checkout@v3

      - name: prepare ccache
        # create key with human readable timestamp
        # used in action/cache/restore and action/cache/save steps
        id: ccache-prepare
        run: |
          echo "ccachedir=$(cygpath -m $(ccache -k cache_dir))" >> $GITHUB_OUTPUT
          echo "key=ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}:$(date +"%Y-%m-%d_%H-%M-%S"):${{ github.sha }}" >> $GITHUB_OUTPUT
          echo "timestamp=$(date +"%Y-%m-%d_%H-%M-%S")" >> $GITHUB_OUTPUT

      - name: restore ccache
        # Setup the github cache used to maintain the ccache from one job to the next
        uses: actions/cache/restore@v3
        with:
          path: ${{ steps.ccache-prepare.outputs.ccachedir }}
          key: ${{ steps.ccache-prepare.outputs.key }}
          restore-keys: |
            ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}
            ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/stable

      - name: configure ccache
        # Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.
        run: |
          which ccache
          test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}
          echo "max_size = 0.9G" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
          echo "compression = true" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
          ccache -p
          ccache -s
          # create ccache helper script for Fortran compiler
          echo -e '#!/bin/bash\nccache '$MINGW_PREFIX'/bin/'$F77' "$@"' > $MINGW_PREFIX/lib/ccache/bin/$F77
          # prepend path to ccache helper scripts to PATH
          echo 'export PATH="$MINGW_PREFIX/lib/ccache/bin:$PATH"' >> ~/.bash_profile

      - name: bootstrap
        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap

      - name: configure
        # configure sometimes hangs while compiling 32bit Fortran.
        # It should take much less than 30 minutes. Cancel the step if it takes longer.
        timeout-minutes: 30
        # FIXME: Fix building with Java support. Override JAVA_HOME for now.
        # FIXME: How do we get a working TeX environment in MSYS2? Disable building the documentation for now.
        run: |
          which $CC
          echo $CC --version
          $CC --version
          which $CXX
          echo $CXX --version
          $CXX --version
          which $F77
          echo $F77 --version
          $F77 --version
          mkdir .build
          cd .build && ../configure \
            JAVA_HOME="" \
            --disable-docs \
            gl_cv_have_weak=no

      - name: build
        # Spawning processes seems to have a big overhead on this platform. Use a somewhat larger number of parallel processes to compensate for that.
        run: |
          make -C ./.build all -j8 V=1

      - name: ccache status
        continue-on-error: true
        run: ccache -s

      - name: save ccache
        # Save the cache after we are done (successfully) building
        uses: actions/cache/save@v3
        with:
          path: ${{ steps.ccache-prepare.outputs.ccachedir }}
          key: ${{ steps.ccache-prepare.outputs.key }}

      - name: check
        # Continuing on error in this step means that jobs will be "green" even
        # if the test suite crashes.  But if we don't continue, we'll loose the
        # ccache and other jobs will be cancelled, too.
        # It would be nice if we could mark the job as "yellow" (and continue)
        # in that case.  The second best thing is to display a warning in the
        # job summary (see below).
        continue-on-error: true
        timeout-minutes: 60

        # Perl scripts cannot be run as executables on Windows (no shebang mechanism).
        # We need to wrap them by calling the perl executable explicitly.

        # mkoctfile seems to have trouble when gcc is called via ccache. So,
        # remove the directory with the ccache wrappers from PATH.

        run: |
          echo "makeinfo_program (sprintf ('%s && cd %s && perl makeinfo', [s=nthargout(2, @system, 'cygpath -w /usr/bin')](1:2), strtrim (s)));" \
            >> ./scripts/startup/site-rcfile
          export PATH=$(echo "$PATH" | sed -e "s|$MINGW_PREFIX/lib/ccache/bin:||g")
          make -C ./.build check | tee ./test-suite.log

      - name: display test log
        continue-on-error: true
        # Displaying the log shouldn't take long. Cancel the step if it does.
        timeout-minutes: 5
        run: cat ./.build/test/fntests.log

      - name: analyze test suite results
        # Make sure the test summary lists 0 "FAIL"s and no "REGRESSION"
        run: |
          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || echo "::warning::At least one test failed"
          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || echo "::warning::At least one regression in test suite"
          echo Finished analyzing test suite results.

      - name: test history file creation
        # see bug #62365
        # Pipe to an interactive session to trigger appending the command to
        # the history.  This will trigger the creation of a history file.
        run:  |
          echo "history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')" | ./.build/run-octave -i
          [ -f ./a/b/c/history ] || echo "::warning::Creating history file failed"

      - name: install and compress
        if: matrix.msystem == 'MINGW64'
        continue-on-error: true
        run: |
          echo "::group::Installing Octave"
          mkdir -p /c/octave/pkg
          make -C ./.build DESTDIR=/c/octave/pkg install
          echo "::endgroup::"
          echo "::group::Compressing Octave package"
          cd /c/octave/pkg
          tar -cvzf octave.tar.gz *
          echo "::endgroup::"

      - name: upload build artifact
        if: matrix.msystem == 'MINGW64'
        continue-on-error: true
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target-prefix }}-octave-${{ steps.ccache-prepare.outputs.timestamp }}
          path: C:\octave\pkg\octave.tar.gz
          retention-days: 7


  cygwin:
    runs-on: ${{ matrix.os }}

    defaults:
      run:
        # Use Cygwin bash as default shell
        shell: C:\cygwin\bin\bash.exe --login -eo pipefail -o igncr '{0}'

    strategy:
      # Allow other runners in the matrix to continue if some fail
      fail-fast: false

      matrix:
        # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
        os: [windows-latest]

    env:
      CHERE_INVOKING: "1"
      CC:  gcc
      CXX:  g++
      F77:  gfortran
      # ccache 3.1 doesn't read configuration files
      CCACHE_COMPRESS: "1"

    steps:
      - name: get CPU name
        shell: pwsh
        run : |
          Get-CIMInstance -Class Win32_Processor | Select-Object -Property Name

      - name: checkout repository
        # This must be done before installing Cygwin because their git is
        # incompatible with this action.
        uses: actions/checkout@v3

      - name: install Cygwin build environment
        uses: cygwin/cygwin-install-action@v2
        with:
          # The packages are listed in (alphabetically sorted) blocks:
          # The first block is for mandatory dependencies.
          # The second block is for optional dependencies needed when building from a release tarball.
          # The third block is for additional dependencies needed when building from a repository checkout.
          # The fourth block is for additional run-time dependencies (to run test suite) that aren't needed to build.

          # FIXME: libklu-devel should depend on libbtf-devel.  Install it manually even if Octave doesn't explicitly use it.
          packages: >-
            autoconf
            automake
            make
            gcc-g++
            gcc-fortran
            bison
            dash
            flex
            gperf
            libtool
            liblapack-devel
            libpcre2-devel
            libreadline-devel

            ghostscript
            gnuplot-base
            libamd-devel
            libarpack-devel
            libbtf-devel
            libbz2-devel
            libcamd-devel
            libccolamd-devel
            libcholmod-devel
            libcolamd-devel
            libcurl-devel
            libcxsparse-devel
            libfftw3-devel
            libfltk-devel
            libfontconfig-devel
            libfreetype-devel
            libGL-devel
            libgl2ps-devel
            libglpk-devel
            libGLU-devel
            libgomp1
            libGraphicsMagick-devel
            libhdf5-devel
            libiconv-devel
            libklu-devel
            libportaudio-devel
            libqhull-devel
            libqrupdate-devel
            libqscintilla2_qt5-devel
            libQt5Core-devel
            libQt5Gui-devel
            libQt5Help-devel
            libsndfile-devel
            libsuitesparseconfig-devel
            libsundials-devel
            libspqr-devel
            libumfpack-devel
            qt5-doc-tools
            rapidjson-devel

            ccache
            git
            icoutils
            rsvg
            texinfo

            unzip
            zip

      - name: prepare ccache
        # create key with human readable timestamp
        # used in action/cache/restore and action/cache/save steps
        id: ccache-prepare
        run: |
          echo "ccachedir=$(cygpath -m ~/.ccache)" >> $GITHUB_OUTPUT
          echo "key=ccache:${{ matrix.os }}:cygwin:${{ github.ref }}:$(date +"%Y-%m-%d_%H-%M-%S"):${{ github.sha }}" >> $GITHUB_OUTPUT

      - name: restore ccache
        # Setup a github cache used to maintain the ccache from one run to the next
        uses: actions/cache/restore@v3.2.2
        with:
          path: ${{ steps.ccache-prepare.outputs.ccachedir }}
          key: ${{ steps.ccache-prepare.outputs.key }}
          restore-keys: |
            ccache:${{ matrix.os }}:cygwin:${{ github.ref }}
            ccache:${{ matrix.os }}:cygwin:refs/heads/stable

      - name: configure ccache
        run: |
          # work around issue with ccache calling itself recursively
          [ -f /usr/bin/ccache.exe ] && mv /usr/bin/ccache.exe /usr/bin/ccache
          which ccache
          ccache -V
          # ccache 3.1 doesn't read configuration files
          # test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}
          # echo "max_size = 0.9G" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
          # echo "compression = true" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
          # limit maximum cache size to avoid exceeding the total disk or cache quota
          ccache -M 0.9G
          ccache -s
          # create ccache symlinks for all compilers
          test -d /usr/lib/ccache/bin || mkdir -p /usr/lib/ccache/bin
          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${CC}.exe
          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${CXX}.exe
          ln -s /usr/bin/ccache /usr/lib/ccache/bin/${F77}.exe
          # prepend path to ccache symlinks to PATH
          echo 'export PATH="/usr/lib/ccache/bin:$PATH"' >> ~/.bash_profile

      - name: bootstrap
        run: GNULIB_URL=https://github.com/coreutils/gnulib.git ./bootstrap

      - name: configure
        # FIXME: Fix building with Java support.  Override JAVA_HOME for now.
        # FIXME: How do we get a working TeX environment in Cygwin?  Disable building the documentation for now.
        run: |
          which $CC
          echo $CC --version
          $CC --version
          which $CXX
          echo $CXX --version
          $CXX --version
          which $F77
          echo $F77 --version
          $F77 --version
          mkdir .build
          cd .build && ../configure \
            --libexecdir=/usr/lib \
            --enable-shared \
            --disable-java \
            --disable-docs \
            JAVA_HOME="" \
            EGREP="grep -E" \
            FLIBS="-lgfortran -lquadmath"

      - name: build
        # Spawning processes seems to have a big overhead on this platform.  Use a somewhat larger number of parallel processes to compensate for that.
        run: |
          EGREP="grep -E" make -C ./.build all -j8 V=1

      - name: ccache status
        continue-on-error: true
        run: ccache -s

      - name: save ccache
        # Save the cache after we are done (successfully) building
        uses: actions/cache/save@v3.2.2
        with:
          path: ${{ steps.ccache-prepare.outputs.ccachedir }}
          key: ${{ steps.ccache-prepare.outputs.key }}

      - name: check
        # Continuing on error in this step means that jobs will be "green" even
        # if the test suite crashes.  But if we don't continue, we'll loose the
        # ccache.
        # It would be nice if we could mark the job as "yellow" (and continue)
        # in that case.  The second best thing is to display a warning in the
        # job summary (see below).
        continue-on-error: true
        timeout-minutes: 60

        # mkoctfile seems to have trouble when gcc is called via ccache.  So,
        # remove the directory with the ccache wrappers from PATH.

        run: |
          export PATH=$(echo "$PATH" | sed -e "s|/usr/lib/ccache/bin:||g")
          EGREP="grep -E" make -C ./.build check | tee ./test-suite.log

      - name: display test log
        continue-on-error: true
        # Displaying the log shouldn't take long.  Cancel the step if it does.
        timeout-minutes: 5
        run: cat ./.build/test/fntests.log

      - name: analyze test suite results
        # Make sure the test summary lists 0 "FAIL"s and no "REGRESSION"
        run: |
          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || echo "::warning::At least one test failed"
          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || echo "::warning::At least one regression in test suite"
          echo Finished analyzing test suite results.

      - name: test history file creation
        # see bug #62365
        # Pipe to an interactive session to trigger appending the command to
        # the history.  This will trigger the creation of a history file.
        run: |
          echo "history_file (make_absolute_filename ('./a/b/c/history')); disp ('test')" | ./.build/run-octave -i
          [ -f ./a/b/c/history ] || echo "::warning::Creating history file failed"