variables:
  GIT_SUBMODULE_STRATEGY: recursive
  TERM: linux
  MATLAB_VERSION: R2026a
  OLD_MATLAB_VERSION: R2020a
  SUITESPARSE_VERSION: 7.11.0
  # To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
  FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'

# The next stanza creates the version number used for the source tarball and the
# binary packages. Here are the following possible cases:
# - if VERSION was already set (when manually running a pipeline), use it
# - if we are in the official Dynare repository:
#   + if on a tag: use the tag
#   + if on master: use 8-unstable-$TIMESTAMP-$COMMIT
#   + on another branch: use $BRANCH-$TIMESTAMP-$COMMIT
# - if in a personal repository: use $USER-$TIMESTAMP-$COMMIT
default:
  before_script:
    - 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ -n $CI_COMMIT_TAG ]]; then export VERSION=$CI_COMMIT_TAG; fi'
    - 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ $CI_COMMIT_REF_NAME == master ]]; then export VERSION=8-unstable-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'
    - 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]]; then export VERSION=$CI_COMMIT_REF_NAME-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'
    - 'if [[ -z $VERSION ]]; then export VERSION=$CI_PROJECT_NAMESPACE-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'

stages:
  - build
  - test
  - pkg
  - sign
  - deploy

build_matlab:
  stage: build
  script:
    - meson setup -Dbuild_for=matlab -Dmatlab_path=/opt/MATLAB/$MATLAB_VERSION --buildtype=release -Db_lto=true -Dsuitesparse_src_path=/usr/src/SuiteSparse-$SUITESPARSE_VERSION build-matlab
    - meson compile -v -C build-matlab
  artifacts:
    paths:
      - build-matlab/
    expire_in: 3 days

build_octave:
  stage: build
  script:
    - meson setup -Dbuild_for=octave --buildtype=release -Db_lto=true -Dsuitesparse_src_path=/usr/src/SuiteSparse-$SUITESPARSE_VERSION build-octave
    - meson compile -v -C build-octave
  artifacts:
    paths:
      - build-octave/
    expire_in: 3 days

build_doc:
  stage: build
  script:
    - meson rewrite kwargs set project / version "$VERSION"
    # Use a local copy of MathJax to avoid using CDN (which are a privacy issue)
    # NB: Debian 12 “Bookworm” has MathJax 2. The following needs to be updated
    #     when Debian moves to MathJax 3.
    - meson setup -Dbuild_for=octave -Dmathjax_path=mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML build-doc
    - meson compile -v -C build-doc doc
    - cp -dR /usr/share/javascript/mathjax build-doc/dynare-manual.html/_static/
  artifacts:
    paths:
      - build-doc/
    expire_in: 3 days

pkg_source:
  stage: pkg
  script:
    - meson rewrite kwargs set project / version "$VERSION"
    - git commit -a -m "Source for $VERSION"
    - meson setup -Dbuild_for=octave build-src
    - meson dist -C build-src --no-tests
  artifacts:
    paths:
      - build-src/meson-dist/dynare-*.tar.xz
    expire_in: 3 days
  needs: []

pkg_windows:
  stage: pkg
  script:
    - meson rewrite kwargs set project / version "$VERSION"
    - mkdir -p windows/deps/tarballs && cp /usr/lib/dynare-runner/matlab64-* /usr/lib/dynare-runner/panua-pardiso-*-win.zip windows/deps/tarballs/
    - make -C windows
    - rm windows/deps/tarballs/matlab64-* # No need to cache these files
  cache:
    - key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
      paths:
        - windows/deps/src/
        # We do not cache octave, sysroot-matlab, sysroot-octave and gcc,
        # because those are simply extracted from a tarball. It
        # would be a waste of space and of (re-compression) time.
    - key: $CI_JOB_NAME
      # This cache is shared between all branches, to save space
      paths:
        - windows/deps/tarballs/
  artifacts:
    paths:
      - windows/exe/*
      - windows/7z/*
    expire_in: 3 days
  needs: [ "build_doc" ]

pkg_macOS:
  stage: pkg
  script:
    - export PATH="/opt/homebrew/bin:$PATH"
    - meson rewrite kwargs set project / version "$VERSION"
    - ln -s ~/tarballs macOS/deps/
    - gmake -C macOS
  cache:
    key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
    paths:
      - macOS/deps/src/
  tags:
    - macOS
  artifacts:
    paths:
      - macOS/pkg/*
    expire_in: 3 days
  needs: [ "build_doc" ]

pkg_matlab_online:
  stage: pkg
  rules:
    - if: '$CI_PROJECT_NAMESPACE == "Dynare" && $CI_COMMIT_REF_NAME == "master"'
      when: on_success
    # Avoid the creation of merge request pipelines containing only that job
    # (other jobs either have no “rules” and are thus not considered in merge
    # request pipelines, or have “rules” but are explicitly disabled in merge
    # request pipelines; additionally, we have no “workflow” stanza)
    # See https://docs.gitlab.com/ci/pipelines/merge_request_pipelines/
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never
    - when: manual
      allow_failure: true
  script:
    - meson rewrite kwargs set project / version "$VERSION"
    - cd scripts/matlab-online && ./packageDynare.sh
  tags:
    - matlab-online
  cache:
    - key: $CI_JOB_NAME
      # This cache is shared between all branches, to save space
      paths:
        - scripts/matlab-online/x13as*.tar.gz
        - scripts/matlab-online/SuiteSparse-*.tar.gz
  artifacts:
    paths:
      - scripts/matlab-online/*.mltbx
    expire_in: 3 days
  needs: []

test_matlab:
  stage: test
  script:
    - meson test -C build-matlab --no-rebuild -j $(($(nproc) / 2))
    # The following is a workaround for MATLAB ⩾ R2025a: sometimes MATLAB
    # leaves zombie fluxbox processes, which make systemd-run exit with a
    # timeout error code.
    - pkill -KILL -x -e fluxbox || true
  artifacts:
    paths:
      - build-matlab/meson-logs/testlog.txt
    when: always
  needs: [ "build_matlab" ]

test_old_matlab:
  stage: test
  variables:
    # Allows the stack to be executable, which is not allowed by default in Debian 13.
    # This is necessary for MATLAB ⩽ R2020a, otherwise it does not start.
    # This workaround may be dropped when we bump our minimal supported MATLAB version.
    GLIBC_TUNABLES: glibc.rtld.execstack=2
  script:
    - meson setup -Dbuild_for=matlab -Dmatlab_path=/opt/MATLAB/$OLD_MATLAB_VERSION --buildtype=release -Db_lto=true build-old-matlab
    - meson compile -v -C build-old-matlab
    - meson test -C build-old-matlab -j $(($(nproc) / 2))
  artifacts:
    paths:
      - build-old-matlab/meson-logs/testlog.txt
    when: always
  needs: []
  when: manual

test_octave:
  stage: test
  variables:
    OPENBLAS_NUM_THREADS: 1
  script:
    # We use xwfb-run rather than wlheadless-run, because as of Octave 10, the
    # Qt graphics backend is not available (i.e. not listed in
    # available_graphics_toolkit) under a pure headless Wayland environment
    # such as our CI runners. In other words, an X11 environment is still
    # needed even for the Qt graphics backend.
    - xwfb-run -- meson test -C build-octave --no-rebuild
  artifacts:
    paths:
      - build-octave/meson-logs/testlog.txt
    when: always
  needs: [ "build_octave" ]
  when: manual

test_clang_format:
  stage: test
  script:
    - meson setup -Dbuild_for=octave build-clang-format
    - ninja -C build-clang-format clang-format-check
  needs: []

test_clang_tidy:
  stage: test
  script:
    - meson setup -Dbuild_for=octave build-clang-tidy
    - ninja -C build-clang-tidy clang-tidy
  needs: []
  when: manual

# For the sign and deploy jobs, we don’t use the “needs” keyword, since we
# don’t want those jobs to start before the “test” and “pkg” stages have
# succeeded. Hence we stick to the “dependencies” keyword.

sign_windows:
  stage: sign
  rules:
    - if: '$CI_PROJECT_NAMESPACE == "Dynare" && $CI_COMMIT_REF_NAME == "master"'
      when: on_success
    - when: never
  tags:
    - sign
  dependencies:
    - pkg_windows
  script:
    - f=(windows/exe/*) && mkdir -p windows/exe-signed/ && osslsigncode sign -pkcs11module /usr/lib/x86_64-linux-gnu/libykcs11.so.2 -key "pkcs11:id=%01;type=private;pin-value=$YUBIKEY_PIN" -certs ~/cepremap-code-signing-comodo-sectigo.pem -n Dynare -i https://www.dynare.org -t http://timestamp.comodoca.com -in ${f[0]} -out windows/exe-signed/${f[0]##*/}
  artifacts:
    paths:
      - windows/exe-signed/*
    expire_in: 3 days

deploy_manual_unstable:
  stage: deploy
  rules:
    - if: '$CI_PROJECT_NAMESPACE == "Dynare" && $CI_COMMIT_REF_NAME == "master"'
      when: on_success
    - when: never
  tags:
    - deploy
  dependencies:
    - build_doc
  script:
    - rsync --recursive --links --delete build-doc/dynare-manual.html/ /srv/www.dynare.org/manual-unstable/

deploy_snapshot_unstable:
  stage: deploy
  rules:
    - if: '$CI_PROJECT_NAMESPACE == "Dynare" && $CI_COMMIT_REF_NAME == "master"'
      when: on_success
    - when: never
  tags:
    - deploy
  dependencies:
    - pkg_source
    - pkg_windows
    - sign_windows
    - pkg_macOS
    - pkg_matlab_online
  script:
    - cp build-src/meson-dist/*.tar.xz /srv/www.dynare.org/snapshot/source/ && ln -sf *.tar.xz /srv/www.dynare.org/snapshot/source/dynare-latest-src.tar.xz
    - f=(windows/exe-signed/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/windows/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/windows/dynare-latest-win.exe
    - f=(windows/7z/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/windows-7z/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/windows-7z/dynare-latest-win.7z
    - f=(macOS/pkg/*.pkg) && cp ${f[0]} /srv/www.dynare.org/snapshot/macos/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/macos/dynare-latest-macos.pkg
    - f=(scripts/matlab-online/*.mltbx) && cp ${f[0]} /srv/www.dynare.org/snapshot/matlab-online/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/matlab-online/dynare-latest.mltbx
    - ~/update-snapshot-list.sh
    - curl -X POST -F token="$WEBSITE_PIPELINE_TRIGGER_TOKEN" -F ref=master https://git.dynare.org/api/v4/projects/40/trigger/pipeline
