tests

name: tests

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

on:
  workflow_dispatch:
  push:
    tags:
      - "*"
    branches:
      - main
      - develop
      - "release/*"
      - "hotfix/*"
  pull_request:
    branches-ignore:
      - "docs/*"
      - "doc/*"

jobs:
  unittests:
    runs-on: ${{ matrix.os }}
    timeout-minutes: 200 # for eager mode
    name: tests on ${{ matrix.os }} with ${{ matrix.python-version }} compiled = ${{ matrix.use-graph }}
    env:
      ZFIT_DO_JIT: ${{ matrix.use-graph }}
    strategy:
      max-parallel: 15
      fail-fast: False
      matrix:
        use-graph: [ 1 ]
        python-version: [ "3.9", "3.11", "3.12"]  # omit "3.10" to save compute time
        os: [ ubuntu-latest ]
        extras: [ alldev ]
        include:
          - os: ubuntu-latest
            extras: alldev
            python-version: "3.12"
            use-graph: 0
          - os: macos-latest
            python-version: "3.12"
            use-graph: 1
            extras: alldev
          - os: windows-latest
            python-version: "3.12"
            use-graph: 1
            extras: alldev
          - os: macos-14  # Apple silicon runner
            python-version: '3.12'
            use-graph: 1
            extras: alldev

    steps:
      - name: Get number of CPU cores
        uses: SimenB/github-actions-cpu-cores@v2
        id: cpu-cores
#      - run: echo "ZFIT_HALF_NCORES=$((steps.cpu-cores.outputs.count))" >> $GITHUB_ENV  # todo: set number of cores a bit lower, memory?
#        id: set-ncpus
      - uses: actions/checkout@v4
      - name: Get history and tags for SCM versioning to work
        run: |
          git fetch --prune --unshallow
          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
      - uses: actions/setup-python@v5
        name: Set up Python ${{ matrix.python-version }}
        with:
          python-version: ${{ matrix.python-version }}
      - name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      - name: pip cache
        uses: actions/cache@v4.0.2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}-pip-${{ hashFiles('**/requirements_dev.txt') }}-pip-${{ hashFiles('**/pyproject.toml') }}-pip-${{ hashFiles('**/setup.cfg') }}-pip-${{ hashFiles('**/setup.py') }}
          restore-keys: |
            ${{ runner.os }}-pip-

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install coverage-lcov pytest-xdist pytest-cov
          pip install .[${{ matrix.extras }}]
      - name: Test with pytest
        run: |
          pytest --cov=. --cov-config=pyproject.toml -n2 --cov-report=xml --cov-report=term-missing

#          pytest --cov=. --cov-config=pyproject.toml -n auto --cov-report=xml --cov-report=term-missing  # logical number of cpus, falls back to auto
  #               TODO: fails on windows? add again above pytest?
  #          if [ "$GITHUB_REF" == 'refs/heads/develop' ]; then
  #            echo "PYTEST_ADDOPTS=--longtests-kde --longtests" >> "$GITHUB_ENV"
  #          fi
#           convert to lcov format
#          mkdir coverage && coverage-lcov --output_file_path ./coverage/lcov.info
  #      # TODO(jonas): fix coverage report? Needs converter to lcov format
  #      - name: Coveralls Parallel
  #        uses: coverallsapp/github-action@v2.3.0
  #        with:
  #          github-token: ${{ secrets.github_token }}
  #          flag-name: run-${{ matrix.use-graph }}-${{ matrix.python-version }}-ubuntu
  #          parallel: true
  docs:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    strategy:
      matrix:
        python-version: [ "3.12" ]
    name: Testbuild docs
    steps:
      - uses: actions/checkout@v4
      - name: Get history and tags for SCM versioning to work
        run: |
          git fetch --prune --unshallow
          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
      - uses: actions/setup-python@v5
        name: Set up Python ${{ matrix.python-version }}
        with:
          python-version: ${{ matrix.python-version }}
      - name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      - name: pip cache
        uses: actions/cache@v4.0.2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}-pip-${{ hashFiles('**/requirements_dev.txt') }}-pip-${{ hashFiles('**/pyproject.toml') }}-pip-${{ hashFiles('**/setup.cfg') }}-pip-${{ hashFiles('**/setup.py') }}
          restore-keys: |
            ${{ runner.os }}-pip-

      - name: Install dependencies
        run: |
          python -m pip install uv
          pip install --ignore-requires-python .[docs]
      - name: Build the docs, check for failure
        run: |
          bash utils/ci/testbuild_docs.sh

  tutorials:
    runs-on: ubuntu-latest
    timeout-minutes: 150  # eager mode takes some time
    strategy:
      max-parallel: 8
      fail-fast: False
      matrix:
        use-graph: [ 1 ]
        python-version: [ "3.9", "3.12" ]
        include:
          - os: ubuntu-latest
            extras: alldev-linux
            python-version: "3.11"
            use-graph: 0
    name: Run tutorials, Python ${{ matrix.python-version }}, compiled = ${{ matrix.use-graph }}
    env:
      ZFIT_DO_JIT: ${{ matrix.use-graph }}
    steps:
      - name: Get number of CPU cores
        uses: SimenB/github-actions-cpu-cores@v2
        id: cpu-cores
      - uses: actions/checkout@v4
      - name: Get history and tags for SCM versioning to work
        run: |
          git fetch --prune --unshallow
          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
      - uses: actions/setup-python@v5
        name: Set up Python ${{ matrix.python-version }}

        with:
          python-version: ${{ matrix.python-version }}

      - name: Clone Tutorials
        run: |
          git clone https://github.com/zfit/zfit-tutorials.git

      - name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      - name: pip cache
        uses: actions/cache@v4.0.2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}-pip-${{ hashFiles('**/requirements_dev.txt') }}-pip-${{ hashFiles('**/pyproject.toml') }}-pip-${{ hashFiles('**/setup.cfg') }}-pip-${{ hashFiles('**/setup.py') }}
          restore-keys: |
            ${{ runner.os }}-pip-
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install wheel
          pip install -U .[all]
          pip install nbval pytest-helpers-namespace pytest-xdist
          pip install -r zfit-tutorials/requirements.txt
          pip install -U --force-reinstall .[all]  # yep. Needed. Otherwise i.e. numpy needs to be upgraded

      - name: Run notebooks
        run: |
          pytest --nbval-lax zfit-tutorials --dist loadscope --ignore=zfit-tutorials/experimental --ignore=zfit-tutorials/_unused --ignore=zfit-tutorials/_website -n${{ steps.cpu-cores.outputs.count }}
  examples:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    strategy:
      max-parallel: 8
      fail-fast: False
      matrix:
        use-graph: [ 1 ]
        python-version: [ "3.9", "3.11" ]  # todo: upgrade to 3.12 if nlopt available for 3.12
        include:
          - os: ubuntu-latest
            extras: alldev-linux
            python-version: "3.11"
            use-graph: 0
    name: Run examples, Python ${{ matrix.python-version }}, compiled = ${{ matrix.use-graph }}
    env:
      ZFIT_DO_JIT: ${{ matrix.use-graph }}
    steps:
      - uses: actions/checkout@v4
      - name: Get history and tags for SCM versioning to work
        run: |
          git fetch --prune --unshallow
          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
      - uses: actions/setup-python@v5
        name: Set up Python ${{ matrix.python-version }}
        with:
          python-version: ${{ matrix.python-version }}
      - name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      - name: pip cache
        uses: actions/cache@v4.0.2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}-pip-${{ hashFiles('**/requirements_dev.txt') }}-pip-${{ hashFiles('**/pyproject.toml') }}-pip-${{ hashFiles('**/setup.cfg') }}-pip-${{ hashFiles('**/setup.py') }}
          restore-keys: |
            ${{ runner.os }}-pip-

      - name: Run examples
        run: |
          bash utils/ci/install_test_examples.sh

  finish:
    needs: unittests
    runs-on: ubuntu-latest
    steps:
      - name: Coveralls Finished
        uses: coverallsapp/github-action@v2.3.0
        with:
          github-token: ${{ secrets.github_token }}
          parallel-finished: true


CodeQL

name: "CodeQL"

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

on:
  push:
    branches: [ develop, master ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ develop ]

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'python' ]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          # If you wish to specify custom queries, you can do so here or in a config file.
          # By default, queries listed here will override any specified in a config file.
          # Prefix the list here with "+" to use these queries and those in the config file.
          # queries: ./path/to/local/query, your-org/your-repo/queries@main

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


Changelog check

name: Changelog check

on:
  pull_request:
    types: [labeled, unlabeled, opened, synchronize, reopened]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  changelog:
    name: Check changelog entry
    runs-on: ubuntu-latest
    steps:
    - name: Check change log entry
      uses: scientific-python/action-check-changelogfile@865ff8154dd94f008f08de6bb8d8c1f661113658
      env:
        CHANGELOG_FILENAME: CHANGES.rst
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


CI-devtest

# This test job is separated out into its own workflow to be able to trigger separately
name: CI-devtest

on:
  push:
    branches:
    - main
    - 'v*'
    tags:
    - '*'
  pull_request:
  schedule:
    - cron: "0 3 * * 6"
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  devdeps:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python 3.12
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - name: Install tox
        run: python -m pip install --upgrade tox
      - name: Run tests against dev dependencies
        run: tox -e py312-test-devdeps-alldeps-cov

      - name: Upload coverage to codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml
          verbose: true


CI

# Developer version testing is in separate workflow
name: CI

on:
  push:
    branches:
    - main
    - 'v*'
    tags:
    - '*'
  pull_request:
  schedule:
    - cron: "0 3 * * 6"
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  tests:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: py38 oldest dependencies, Linux
            python-version: '3.8'
            tox_env: py38-test-oldestdeps-alldeps
          - name: py39 mandatory dependencies only, Linux
            python-version: '3.9'
            tox_env: py39-test
          - name: py311 with online tests, Linux
            python-version: '3.11'
            tox_env: py311-test-alldeps-online
          - name: linkcheck
            python-version: '3.10'
            tox_env: linkcheck

    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install tox
      run: python -m pip install --upgrade tox
    - name: Install library dependencies and run Tests
      run: tox -e ${{ matrix.tox_env }}

  mac_windows:
    runs-on: ${{ matrix.os }}
    name: ${{ matrix.os }} py310
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, windows-latest]
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.10'
    - name: Install tox
      run: python -m pip install --upgrade tox
    - name: Python 3.10 with latest astropy
      run: tox -e py310-test-alldeps

  stylecheck:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python 3.8
        uses: actions/setup-python@v5
        with:
          python-version: 3.8
      - name: Install tox
        run: python -m pip install --upgrade tox
      - name: Check codestyle
        run: tox -e codestyle


Deploy

name: Deploy
on:
  workflow_dispatch:

  push:
    branches:
      - master
      - dev
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - name: Checkout Spec Repo 'is-04'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-04
          path: cache/is-04
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-04

      - name: Checkout Spec Repo 'is-05'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-05
          path: cache/is-05
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-05

      - name: Checkout Spec Repo 'is-06'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-06
          path: cache/is-06
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-06

      - name: Checkout Spec Repo 'is-07'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-07
          path: cache/is-07
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-07

      - name: Checkout Spec Repo 'is-08'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-08
          path: cache/is-08
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-08

      - name: Checkout Spec Repo 'is-09'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-09
          path: cache/is-09
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-09

      - name: Checkout Spec Repo 'is-10'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/is-10
          path: cache/is-10
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/is-10

      - name: Checkout Spec Repo 'bcp-002-01'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/bcp-002-01
          path: cache/bcp-002-01
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/bcp-002-01

      - name: Checkout Spec Repo 'bcp-002-02'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/bcp-002-02
          path: cache/bcp-002-02
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/bcp-002-02

      - name: Checkout Spec Repo 'bcp-003-01'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/bcp-003-01
          path: cache/bcp-003-01
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/bcp-003-01

      - name: Checkout Spec Repo 'bcp-004-01'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/bcp-004-01
          path: cache/bcp-004-01
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/bcp-004-01

      - name: Checkout Spec Repo 'nmos-parameter-registers'
        uses: actions/checkout@v3
        with:
          repository: AMWA-TV/nmos-parameter-registers
          path: cache/nmos-parameter-registers
      - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
        working-directory: cache/nmos-parameter-registers

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            ${{ secrets.DOCKER_USERNAME }}/nmos-testing
          tags: |
            # Tag all builds with branch name and sha
            type=sha,prefix=${{ github.ref_name }}-
            # Tag if non-master branch with branch name and latest
            type=raw,value=latest,prefix=${{ github.ref_name }}-,enable=${{ github.ref_name != 'master' }}
            # Tag if master branch with latest (no branch name prefix)
            type=raw,value=latest,enable=${{ github.ref_name == 'master' }}

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2.1.0
        with:
          platforms: all

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v2.5.0

      - name: Login to DockerHub
        uses: docker/login-action@v2.1.0
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build
        uses: docker/build-push-action@v4.0.0
        with:
          context: .
          builder: ${{ steps.buildx.outputs.name }}
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}


Lint

name: Lint
on:
  workflow_dispatch:

  pull_request:

  push:
    branches:
      - main
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Install Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '16.x'
      - name: Setup for python lint
        run: pip install flake8
      - name: Lint python
        run: flake8 .
      - name: Setup for documentation lint
        run: make -C .lint distclean build-tools
      - name: Lint documentation
        run: make -C .lint lint


Render

name: Render
on:
  workflow_dispatch:

  push:
    branches:
        - main
        - master
        - 'publish-*'
jobs:
  build:
    runs-on: ubuntu-latest
    name: Build
    steps:
      - name: Use NMOS Render
        uses: docker://amwa/nmos-render:latest
        env:
          SSH_HOST: ${{ secrets.SSH_HOST }}
          SSH_USER: ${{ secrets.SSH_USER }}
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}


Run Python Tests

name: Run Python Tests
on:
  pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install Python 3
        uses: actions/setup-python@v4
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          python -m pip install poetry
          pip --version
          poetry --version
          # Check if poetry lock file is current with pyproject.toml
          poetry check --lock
          poetry install --with=dev
      - name: Run arxiv-base tests with coverage
        run: poetry run pytest --cov=arxiv.base fourohfour --cov-fail-under=67 arxiv/base fourohfour
      # - name: Check Types
      # TODO The types are in bad shape and need to be fixed
      #   run: poetry run mypy --exclude "test*" -p arxiv
      - name: Run other tests
        # These tests are split out because their coverage is low
        run: poetry run pytest --cov=arxiv --cov-fail-under=25 arxiv
      #- name: Check Doc Style
      #  run: poetry run pydocstyle --convention=numpy --add-ignore=D401 arxiv
      - name: Run App Tests
        run: poetry run python tests/run_app_tests.py


CI

name: CI

on:
  push:
    branches: [ master]
  pull_request:
    branches: [ master]

  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Create virtual environment
        run: python -m venv venv

      - name: Activate virtual environment
        run: source venv/bin/activate

      - name: Install dependencies
        run: pip install -r requirements.txt && pip install -r tests/requirements.txt

      - name: Run linter
        run: pylint --output-format msvs --reports y ccmlib || true

      - name: Run linter for tests
        run: pylint --output-format msvs --reports y tests || true

      - name: Run tests
        run: |
          pytest --junitxml=junit.xml tests

      - name: Publish Test Report
        uses: mikepenz/action-junit-report@v4
        if: always()
        with:
          report_paths: 'junit.xml'
          annotate_only: true


Python Formatting Check

name: Python Formatting Check

on:
  push:
    branches:
      - main
      - master
  pull_request:
    branches:
      - main
      - master

jobs:
  formatting:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Set up Python 3.8
      uses: actions/setup-python@v5
      with:
        python-version: '3.8'
    - name: Create virtual environment
      run: python -m venv venv

    - name: Install black
      run: |
        ./venv/bin/pip install --upgrade pip
        ./venv/bin/pip install black

    - name: Run formatting check
      run: make ck-format


Continuous Integration Tests

name: Continuous Integration Tests
on:
  push:
    branches: [master, develop, github_actions]
    paths-ignore:
      - 'docs/**'
  pull_request:
    branches: [master, develop, github_actions]
    paths-ignore:
      - 'docs/**'
  # Allows manual invocation:
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
    - name: Install dependencies
      run: |
        sudo add-apt-repository --yes ppa:inkscape.dev/stable
        sudo apt update
        sudo apt install -y texlive-latex-base texlive-fonts-recommended texlive-lang-cyrillic cm-super
        sudo apt install inkscape
        # Needed for xmllint:
        sudo apt install libxml2-utils
        python -m pip install --upgrade pip
        pip install flake8 pytest
        # Needed by Inkscape extensions and image processing:
        pip install lxml cssselect Pillow
    - name: Test installation script
      run: |
        python test_installation_script.py 2> /dev/null
        python setup.py
        wget https://gitlab.com/inkscape/extensions/-/raw/master/inkex/tester/inkscape.extension.rng
    - name: Perfom unit-tests
      run: |
        export PYTHONPATH="`inkscape --system-data-directory`/extensions:$HOME/.config/inkscape/extensions/"
        python -m pytest --verbose -s pytests
        xmllint --noout --relaxng inkscape.extension.rng textext/textext.inx


CI

name: CI

on:
  workflow_dispatch:
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main
      - develop

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [ "3.9", "3.10", "3.11" ]
    steps:
    - uses: actions/checkout@v4
    - name: Install Python ${{ matrix.py }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.py }}
    - name: Get full Python version
      shell: bash
      run: echo {name}=$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") >> $GITHUB_OUTPUT
       #run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
    - name: Install dependencies
      shell: bash
      run: |
        python -m pip install --upgrade pip
        python -m pip install -e .[test]
    - name: Test with pytest
      shell: bash
      run: |
        pip install pytest
        pytest


Autopublish to TestPyPi

name: Autopublish to TestPyPi

on:
  push:
    tags:
      - '*'

jobs:
  publish:
    name: Build, verify, & upload package
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v3
        with:
          python-version: 3.7

      - name: Pip cache
        uses: actions/cache@v2
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip
          restore-keys: |
            ${{ runner.os }}-pip

      - name: Build, verify, and upload to TestPyPI
        run: |
          pip install --upgrade nox
          nox -s build publish_testpypi
        env:
          TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}


Publish to PyPi

name: Publish to PyPi

on:
  workflow_dispatch:

jobs:
  publish:
    name: Build, verify, & upload package to PyPi
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v3
        with:
          python-version: 3.7

      - name: Pip cache
        uses: actions/cache@v2
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip
          restore-keys: |
            ${{ runner.os }}-pip

      - name: Build, verify, and upload to TestPyPI
        run: |
          pip install --upgrade nox
          nox -s build publish_pypi
        env:
          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}


Release to GitHub and PyPI

name: Release to GitHub and PyPI

on:
  workflow_dispatch:
    inputs:
      prerelease:
        description: 'Is this a pre-release?'
        required: true
        type: boolean

jobs:
  package:
    name: Build, verify, & upload package
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v3
        with:
          python-version: "3.10"

      - name: Create GitHub Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions.
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          draft: false
          prerelease: ${{ inputs.logLevel }}

      - run: python -m pip install build twine check-wheel-contents
      - run: python -m build --sdist --wheel .
      - run: ls -l dist
      - run: check-wheel-contents dist/*.whl

      - name: Check long_description
        run: python -m twine check dist/*

      - name: Upload to TestPyPI
        uses: pypa/gh-action-pypi-publish@v1.4.2
        with:
          repository_url: https://test.pypi.org/legacy/
          user: __token__
          password: ${{ secrets.TEST_PYPI_PASSWORD }}

      - name: Upload to PyPI
        uses: pypa/gh-action-pypi-publish@v1.4.2
        with:
          user: __token__
          password: ${{ secrets.PYPI_PASSWORD }}


test

name: test

on: [pull_request]

jobs:
  lint:
    name: Check Linting
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: Pip cache
      uses: actions/cache@v2
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip
        restore-keys: |
          ${{ runner.os }}-pip
    - name: Lint
      run: |
        pip install --upgrade nox
        nox -s lint

  analyze:
    name: Analyze Typing
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: Pip cache
      uses: actions/cache@v2
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip
        restore-keys: |
          ${{ runner.os }}-pip
    - name: Lint
      run: |
        pip install --upgrade nox
        nox -s analyze

  test:
    name: Test Python ${{ matrix.python-version }}
    runs-on: ubuntu-latest

    strategy:
      matrix:
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']

    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}
        allow-prereleases: true
    - name: Pip cache
      uses: actions/cache@v2
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip
        restore-keys: |
          ${{ runner.os }}-pip
    - name: Test
      run: |
        pip install --upgrade nox
        nox -s test-${{ matrix.python-version }}

  coverage:
    name: Check code coverage
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: Pip cache
      uses: actions/cache@v2
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip
        restore-keys: |
          ${{ runner.os }}-pip
    - name: Coverage run and report
      run: |
        pip install --upgrade nox
        nox -s coverage

  docs:
    name: Check Docs build
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.8
    - name: Pip cache
      uses: actions/cache@v2
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip
        restore-keys: |
          ${{ runner.os }}-pip
    - name: Build Docs
      run: |
        pip install --upgrade nox
        nox -s docs


push-artifact-to-circle-ci

name: push-artifact-to-circle-ci
concurrency:
  group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
  cancel-in-progress: true
# will be changed to on workflow_run
on:
  workflow_run:
    workflows: ["docs"]
    branches-ignore: ["master"]
    types:
      - completed

jobs:
  Push-Artifact-to-CircleCI:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash -l {0}
    steps:
    - name: Trigger CircleCI download and publication of HTML Doc Artifact
      env:
        EVENT_OBJ:  ${{ toJson(github.event) }}
        COMMIT_SHA:  ${{ github.event.workflow_run.head_sha }}
        REPO_NAME:  ${{ github.event.workflow_run.head_repository.full_name }}
        CIRCLECI_TOKEN: ${{ secrets.CIRCLECI_TOKEN }}
        RUN_ID: ${{github.event.workflow_run.id}}
      run: |
        echo "github.event.workflow_run.head_sha"
        echo ${{ github.event.workflow_run.head_sha }}
        echo "github.event.workflow_run.head_repository.html_url"
        echo ${{ github.event.workflow_run.head_repository.html_url }}
        echo "RUN_ID"
        echo $RUN_ID
        # Acquire the Pull Request Number from Github API
        echo "automated curl"
        PR_NUMBER=$(curl -H "Accept: application/vnd.github.groot-preview+json"   https://api.github.com/repos/$REPO_NAME/commits/$COMMIT_SHA/pulls 2>/dev/null | jq '.[0].number')
        echo "PR_NUMBER"
        echo $PR_NUMBER

        # Use Pull Request Number to trigger pipeline on CircleCI which will just download artifact,
        # unzip it and make it available for browsing
        curl --request POST \
          --url https://circleci.com/api/v2/project/gh/braindecode/braindecode/pipeline \
          --header "Circle-Token: $CIRCLECI_TOKEN" \
          --header 'content-type: application/json' \
          --header 'x-attribution-actor-id: github_actions' \
          --header 'x-attribution-login: github_actions' \
          --data \{\"branch\":\"pull/$PR_NUMBER/head\",\"parameters\":\{\"github-artifact-url\":\"https://nightly.link/braindecode/braindecode/actions/runs/$RUN_ID/HTML-Docs.zip\"\}\}
        # Just for debugging
        echo "EVENT_OBJ"
        echo $EVENT_OBJ


on: [status]
jobs:
  circleci_artifacts_redirector:
    runs-on: ubuntu-latest
    name: Run CircleCI artifacts redirector
    steps:
      - name: GitHub Action step
        uses: larsoner/circleci-artifacts-redirector-action@master
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          api-token: ${{ secrets.CIRCLECI_TOKEN }}
          artifact-path: 0/dev/index.html
          circleci-jobs: fetch_docs_from_github
          job-title: Check rendered doc here!


docs

name: docs
concurrency:
  group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
  cancel-in-progress: true
on:
  push:
    branches:
      - "master"
  pull_request:
    branches:
      - '*' # all branches, including forks

jobs:
  build_docs:
    runs-on: ubuntu-latest
    steps:
      ## Install Braindecode
      - name: Checking Out Repository
        uses: actions/checkout@v4
      # Cache MNE Data
      # The cache key here is fixed except for os
      # so if you download a new mne dataset in the code, best to manually increment the key below
      - name: Create/Restore MNE Data Cache
        id: cache-mne_data
        uses: actions/cache@v3
        with:
          path: ~/mne_data
          key: ${{ runner.os }}-v3
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      - name: Show Python Version
        run: python --version
      # Update pip
      - name: Update pip
        run: pip install --upgrade pip
      # Install with MOABB and docs dependencies
      - name: Install with doc dependencies
        run: pip install -e .[moabb,docs]
      # Show Braindecode Version
      - run: python -c "import braindecode; print(braindecode.__version__)"

      - name: Checking Out Repository
        uses: actions/checkout@v4
      - name: Create Docs
        run: |
          cd docs
          make html
      - name: Upload HTML Docs as Artifacts
        uses: actions/upload-artifact@v2
        with:
          name: HTML-Docs
          path: ./docs/_build/

      - name: Deploy to Github Pages if on Master
        if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
        uses: peaceiris/actions-gh-pages@v3
        with:
          deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
          external_repository: braindecode/braindecode.github.io
          destination_dir: dev
          publish_branch: master
          publish_dir: ./docs/_build/html
          cname: braindecode.org


tests

name: tests
concurrency:
  group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
  cancel-in-progress: true
on:
  push:
    branches:
      - "master"
  pull_request:
    branches:
      - '*' # all branches, including forks

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
        python-version: ["3.8", "3.9", "3.10", "3.11"]
    steps:
    ## Install Braindecode
    - name: Checking Out Repository
      uses: actions/checkout@v4
    # Cache MNE Data
    # The cache key here is fixed except for os
    # so if you download a new mne dataset in the code, best to manually increment the key below
    - name: Create/Restore MNE Data Cache
      id: cache-mne_data
      uses: actions/cache@v3
      with:
        path: ~/mne_data
        key: ${{ runner.os }}-v3
    - uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}
    - name: Show Python Version
      run: python --version
    # Update pip
    - name: Update pip
      run: python -m pip install --upgrade pip
    - name: Install Braindecode from Current Checkout
      run: pip install -e .[moabb,tests]
    # Show Braindecode Version
    - run: python -c "import braindecode; print(braindecode.__version__)"

    ## Run Tests
    - name: Run Tests # See https://stackoverflow.com/a/59959080/1469195 for the cov-report logic
      run: pytest --cov=braindecode test/ --cov-report term --cov-report xml:coverage.xml
    - name: Upload Coverage to Codecov
      uses: codecov/codecov-action@v4
      if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8'}}
      with:
        fail_ci_if_error: true
        file: ./coverage.xml
        path_to_write_report: ./codecov_report.txt
        env_vars: OS,PYTHON
        token: ${{ secrets.CODECOV_TOKEN }}


Check Whats News Changes

name: Check Whats News Changes
concurrency:
  group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
  cancel-in-progress: true
on:
  pull_request:
    types: [ assigned, opened, synchronize, reopened, labeled, unlabeled ]
    branches:
      - '*'
jobs:
  check-whats-news:
    runs-on: ubuntu-20.04
    steps:
      - uses: tarides/changelog-check-action@v2
        with:
          changelog: docs/whats_new.rst


pre-commit-codestyle

name: pre-commit-codestyle
concurrency:
  group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
  cancel-in-progress: true

on: [pull_request]

jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-python@v5
    - uses: pre-commit/action@v3.0.1


packaging

name: packaging

on:
  # Make sure packaging process is not broken
  push:
    branches: [main, dev]
  pull_request:
  # Make a package for release
  release:
    types: [published]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: ["3.10"]

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip setuptools setuptools_scm twine wheel flit
    - name: Create packages
      run: python -m flit build
    - name: Run twine check
      run: twine check dist/*
    - uses: actions/upload-artifact@v2
      with:
        name: tox-gh-actions-dist
        path: dist


tox checks

# NB: this name is used in the status badge
name: tox checks

on:
  push:
    branches:
      - main
      - dev
  pull_request:
    branches:
      - main
      - dev
  workflow_dispatch:
  schedule:
    - cron: "0 5 * * 6"  # 5:00 UTC every Saturday

jobs:
  lint:
    name: ${{ matrix.toxenv }}
    runs-on: ubuntu-latest

    strategy:
      matrix:
        toxenv:
          - clean
          - check
          - docs

    steps:
      - name: Git clone
        uses: actions/checkout@v2

      - name: Set up Python ${{ env.default_python || '3.10' }}
        uses: actions/setup-python@v2
        with:
          python-version: "${{ env.default_python || '3.10' }}"

      - name: Pip cache
        uses: actions/cache@v2
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ matrix.toxenv }}-${{ hashFiles('tox.ini', 'pyproject.toml') }}
          restore-keys: |
            ${{ runner.os }}-pip-${{ matrix.toxenv }}-
            ${{ runner.os }}-pip-
      - name: Install dependencies
        run: |
          python -m pip install -U pip
          python -m pip install -U setuptools wheel
          python -m pip install -U tox
      - name: Run ${{ matrix.toxenv }}
        run: python -m tox -e ${{ matrix.toxenv }}


tox pytests

name: tox pytests

on:
  push:
    branches:
      - main
      - dev
  pull_request:
    branches:
      - main
      - dev
  workflow_dispatch:
  schedule:
    - cron: "0 5 * * 6"  # 5:00 UTC every Saturday

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11"]

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install tox tox-gh-actions coverage coveralls
    - name: Test with tox
      run: tox

    - name: Check test coverage
      run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 84 || 85 }}

    - name: Report to coveralls
      run: coveralls
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        COVERALLS_SERVICE_NAME: github


changelog

name: changelog
on:
  - pull_request

jobs:
  check_has_news_in_changelog_dir:
    if: |
      ! (
        contains(github.event.pull_request.labels.*.name, 'no-news-is-good-news') ||
        github.event.pull_request.title == '[pre-commit.ci] pre-commit autoupdate'
      )
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:  # do a deep fetch to allow merge-base and diff
          fetch-depth: 0
      - name: check PR adds a news file
        run: |
          news_files="$(git diff --name-only "$(git merge-base origin/main "$GITHUB_SHA")" "$GITHUB_SHA" -- changelog.d/*.rst)"
          if [ -n "$news_files" ]; then
            echo "Saw new files. changelog.d:"
            echo "$news_files"
          else
            echo "No news files seen"
            exit 1
          fi


CI/CD

name: CI/CD

on:
  push:
    branches:
      - "*"
    tags:
      - "*"
  pull_request:

jobs:
  lint:
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
      - name: install requirements
        run: |
          python -m pip install -U pip setuptools wheel
          python -m pip install pre-commit tox
      - name: run pre-commit
        run: pre-commit run -a
      - name: mypy (sdk)
        run: |
          cd compute_sdk
          tox -e mypy
      - name: mypy (endpoint)
        run: |
          cd compute_endpoint
          tox -e mypy

  # ensure docs can build, imitating the RTD build as best we can
  check-docs:
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: build docs
        run: make docs

  safety-check-endpoint:
    timeout-minutes: 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: install requirements
        run: |
          python -m pip install -U pip setuptools
          python -m pip install './compute_sdk' './compute_endpoint'
          python -m pip install safety
          rm -rf /opt/hostedtoolcache/Python/*/x64/lib/python3.*/site-packages/pip-23.{0,1,2}*
      - name: run safety check
        run: safety check

  test-sdk:
    timeout-minutes: 5
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
    name: "Test SDK on py${{ matrix.python-version }} x ${{ matrix.os }} "
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: python -m pip install -U pip setuptools
      - run: python -m pip install tox
      - name: run tests
        run: |
          cd compute_sdk
          tox -e py

  test-endpoint:
    timeout-minutes: 8
    runs-on: ubuntu-latest
    services:
      rabbitmq:
        image: rabbitmq
        ports:
          - 5672:5672
        # needed because the rabbitmq container does not provide a healthcheck
        options: --health-cmd "rabbitmq-diagnostics -q check_running && rabbitmq-diagnostics -q check_virtual_hosts && rabbitmq-diagnostics -q check_port_connectivity" --health-interval 10s --health-timeout 5s --health-retries 5
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11"]
    name: "Test Endpoint on py${{ matrix.python-version }} x ${{ matrix.os }} "
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: python -m pip install -U pip setuptools
      - run: python -m pip install tox
      - name: run tests
        run: |
          cd compute_endpoint
          tox -e py -- --log-cli-level=ERROR
      - name: Collect Docker Logs
        if: failure()
        uses: jwalton/gh-docker-logs@v2.2.2


daily

name: daily
on:
  # build every day at 4:00 AM UTC
  schedule:
    - cron: '0 4 * * *'
  workflow_dispatch:

env:
  TARGET_PYTHON_VERSION: '3.11'

jobs:
  smoke-test-staging:
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: main
    - uses: actions/setup-python@v5
      with:
        python-version: '${{ env.TARGET_PYTHON_VERSION }}'
    - run: |
        python -m venv .venv
        .venv/bin/python -m pip install --upgrade pip setuptools wheel
        .venv/bin/python -m pip install tox
    - name: run smoke tests (ECS staging)
      env:
        FUNCX_SMOKE_CLIENT_ID: ${{ secrets.API_CLIENT_ID }}
        FUNCX_SMOKE_CLIENT_SECRET: ${{ secrets.API_CLIENT_SECRET_STAGING }}
        GLOBUS_SDK_ENVIRONMENT: "staging"
      run: |
        source .venv/bin/activate
        cd smoke_tests
        make staging

  safety-check-sdk:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: main
    - uses: actions/setup-python@v5
      with:
        python-version: '${{ env.TARGET_PYTHON_VERSION }}'
    - name: install requirements
      run: |
        python -m venv .venv
        .venv/bin/python -m pip install --upgrade pip setuptools wheel
        .venv/bin/python -m pip install './compute_sdk'
        .venv/bin/python -m pip install safety
    - name: run safety check
      run: .venv/bin/safety check

  safety-check-endpoint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: main
    - uses: actions/setup-python@v5
      with:
        python-version: '${{ env.TARGET_PYTHON_VERSION }}'
    - name: install requirements
      run: |
        python -m venv .venv
        .venv/bin/python -m pip install --upgrade pip setuptools wheel
        .venv/bin/python -m pip install './compute_endpoint'
        .venv/bin/python -m pip install safety
    - name: run safety check
      run: .venv/bin/safety check

  slack-notify:
    needs:
      - smoke-test-staging
      - safety-check-sdk
      - safety-check-endpoint
    if: always()
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '${{ env.TARGET_PYTHON_VERSION }}'
      - run: python -m pip install --upgrade requests
      - name: notify slack
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_CHANNEL: '#commits'
          SLACK_MESSAGE_TITLE: 'Daily Smoke Tests on Staging'
          SLACK_FAILURE_MESSAGE: 'Daily test failed on staging'
        run: ./.github/_support/github-slack-notify.py ${{ needs.smoke-test-staging.result }}


hourly

name: hourly

on:
  schedule:
    - cron: "0 * * * *"
  workflow_dispatch:
    inputs:
      tags:
        required: false
        description: "manual test"

jobs:
  smoke-test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
    - uses: actions/checkout@v4
      with:
        ref: main
    - uses: actions/setup-python@v5
      with:
        python-version: "3.11"
    - run: python -m pip install -U pip setuptools
    - run: python -m pip install tox
    - name: Run smoke tests to check liveness of hosted services
      env:
        FUNCX_SMOKE_CLIENT_ID: ${{ secrets.API_CLIENT_ID }}
        FUNCX_SMOKE_CLIENT_SECRET: ${{ secrets.API_CLIENT_SECRET }}
      run: |
        cd smoke_tests
        make prod

  slack-notify:
    needs: [smoke-test]
    if: always()
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
      - run: python -m pip install -U requests
      - name: notify slack
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_CHANNEL: '#commits'
          SLACK_MESSAGE_TITLE: 'Hourly Automated Tests'
          SLACK_FAILURE_MESSAGE: '@channel - Hourly run failed'
        run: ./.github/_support/github-slack-notify.py ${{ needs.smoke-test.result }}


name: smoke_test

on:
  push:
    paths:
      - 'smoke_tests/**'
    branches:
      - "*"
    tags:
      - "*"
  pull_request:
    paths:
      - 'smoke_tests/**'

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-python@v5
      with:
        python-version: "3.11"
    - run: python -m pip install -U pip setuptools
    - run: python -m pip install tox
    - name: Run smoke tests (localdeps)
      env:
        FUNCX_SMOKE_CLIENT_ID: ${{ secrets.API_CLIENT_ID }}
        FUNCX_SMOKE_CLIENT_SECRET: ${{ secrets.API_CLIENT_SECRET }}
      run: |
        cd smoke_tests
        tox -e localdeps


pre-commit

name: pre-commit

on:
  pull_request:
  push:
    branches: [master, dev]

jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-python@v2
    - uses: pre-commit/action@v3.0.0


pytest

name: pytest

on:
  pull_request:
  push:
    branches: [master, dev]

jobs:
  pytest:
    strategy:
      matrix:
        python-version: ["3.7", "3.8", "3.9", "3.10"]
      fail-fast: false
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -U \
          matplotlib \
          scipy \
          rectpack \
          klayout \
          freetype-py \
          pytest
        pip install -e .
    - name: Run test
      uses: GabrielBB/xvfb-action@v1
      with:
        run: |
          pytest


build

---
name: build

on:
  pull_request:
    branches: [master]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
        with:
          extras: '-E pandas'
      - name: Linting and static code checks
        run: pre-commit run --all-files

  build_docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Build docs
        run: cd docs && make html SPHINXOPTS="-W --keep-going"

  build_package:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Build package
        run: poetry build

  test_core:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Test core
        run: pytest tests/tests_unit -n8 --dist loadscope --maxfail 10 -m 'not dsl' --test-deps-only-core

  test_full:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        python-version: ['3.8', '3.11', '3.12']  # TODO: 3.9, 3.10 (requires a lot of work for FakeCogResGen for tests)
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
        with:
          python_version: ${{ matrix.python-version }}
          extras: '-E all'

      - name: Test full
        env:
          LOGIN_FLOW: client_credentials
          COGNITE_CLIENT_SECRET: ${{ secrets.COGNITE_CLIENT_SECRET }}
          COGNITE_TOKEN_URL: https://login.microsoftonline.com/dff7763f-e2f5-4ffd-9b8a-4ba4bafba5ea/oauth2/v2.0/token
          COGNITE_TOKEN_SCOPES: https://greenfield.cognitedata.com/.default
          COGNITE_CLIENT_ID: 14fd282e-f77a-457d-add5-928ec2bcbf04
          COGNITE_PROJECT: python-sdk-test
          COGNITE_BASE_URL: https://greenfield.cognitedata.com
          COGNITE_CLIENT_NAME: python-sdk-integration-tests
        run: pytest tests --durations=10 --cov --cov-report term --cov-report xml:coverage.xml -n8 --dist loadscope --reruns 2 --maxfail 20

      - uses: codecov/codecov-action@v4
        if: matrix.os == 'windows-latest' && matrix.python-version == '3.8'
        with:
          token: ${{ secrets.CODECOV_TOKEN }}


release

---
name: release

on:
  push:
    branches: [master]

jobs:
  test_full_build_and_release:
    runs-on: windows-latest
    environment: CD
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
        with:
          extras: '-E all'

      - name: Test full
        env:
          LOGIN_FLOW: client_credentials
          COGNITE_CLIENT_SECRET: ${{ secrets.COGNITE_CLIENT_SECRET }}
          COGNITE_TOKEN_URL: https://login.microsoftonline.com/dff7763f-e2f5-4ffd-9b8a-4ba4bafba5ea/oauth2/v2.0/token
          COGNITE_TOKEN_SCOPES: https://greenfield.cognitedata.com/.default
          COGNITE_CLIENT_ID: 14fd282e-f77a-457d-add5-928ec2bcbf04
          COGNITE_PROJECT: python-sdk-test
          COGNITE_BASE_URL: https://greenfield.cognitedata.com
          COGNITE_CLIENT_NAME: python-sdk-integration-tests
        run: pytest tests --durations=10 --cov --cov-report term --cov-report xml:coverage.xml -n8 --dist loadscope --reruns 2 --maxfail 20

      - uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          file: ./coverage.xml

      - name: Build package
        run: poetry build

      - name: Build docs
        run: cd docs && make html

      - name: Release to PyPI
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
        run: twine upload --skip-existing --verbose dist/*

      # TODO: Make this work again
      # - name: Push code snippets to service-contracts
      #   env:
      #     GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      #   run: sh ./scripts/deploy_code_snippets.sh || echo 'PR failed. There is probably
      #     nothing to commit'


build

---
name: build

on:
  pull_request:
    branches: [master]

jobs:
  build_and_test_jupyter_pyodide:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Build package
        run: poetry build
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Install dependencies
        run: npm install pyodide@0.25.1 # JupyterLite currently using pyodide 0.25.0
      - name: Install cognite-sdk in pyodide environment
        run: |
          whl_file=$(find dist -name "*.whl" | sed 's|^dist/||') # Find the built wheel file, remove dist/ prefix
          echo "Found built wheel file: $whl_file"
          SDK_FILE_PATH=$whl_file \
          PACKAGES="[\"pyodide-http\", \"http://localhost:3000/dist/$whl_file\"]" \
          node scripts/test-pyodide.js


---
name: build

on:
  pull_request:
    branches: [master]

jobs:
  build_and_test_streamlit_pyodide:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Build package
        run: poetry build
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Install dependencies
        run: npm install pyodide@0.25.1 # stlite currently using pyodide 0.25.1
      - name: Install cognite-sdk in pyodide environment
        run: |
          whl_file=$(find dist -name "*.whl" | sed 's|^dist/||') # Find the built wheel file, remove dist/ prefix
          echo "Found built wheel file: $whl_file"
          SDK_FILE_PATH=$whl_file \
          PACKAGES="[\"pyodide-http\", \"http://localhost:3000/dist/$whl_file\"]" \
          node scripts/test-pyodide.js


Codespell

---
name: Codespell

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  codespell:
    name: Check for spelling errors
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Codespell
        uses: codespell-project/actions-codespell@v2


Build docs

name: Build docs

on:
  pull_request:
    branches: [ master, 'maint/*' ]

jobs:
  build:
    if: "(github.repository_owner != 'nipreps') && !contains(github.event.head_commit.message, '[skip ci]')"
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Determine current branch/tag name
      run: |
        if [[ "$GITHUB_REF" == refs/pull/* ]]; then
          CURBRANCH=${GITHUB_REF%/*}
          CURBRANCH=${CURBRANCH##*/}
        elif [[ "$GITHUB_REF" == refs/heads/* ]]; then
          CURBRANCH=${GITHUB_REF##*/}
        elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
          echo "This build should not be picking up a tag, cancelling."
          exit 1
        fi

        # Remove forward slashes
        CURBRANCH=$( echo $CURBRANCH | sed 's+/+_+g' )
        echo "Building branch/tag ${CURBRANCH:-<unknown>}, from git ref <$GITHUB_REF>"
        echo "CURBRANCH=${CURBRANCH}" >> ${GITHUB_ENV}

    - name: Install GraphViz
      run: |
        sudo apt-get update -y
        sudo apt-get install -y --no-install-recommends graphviz

    - name: Install dependencies
      run: |
        pip install -r docs/requirements.txt

    - name: Build docs
      run: |
          make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html


Build & update docs

name: Build & update docs

on:
  push:
    branches: [ 'doc/*', 'docs/*', master, "maint/*" ]
    tags: [ '*' ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
      with:
        ssh-key: "${{ secrets.NIPREPS_DEPLOY }}"
        fetch-depth: 0

    - name: Determine current branch/tag name & set-up git author
      run: |
        if [[ "$GITHUB_REF" == refs/tags/* ]]; then
          CURBRANCH=${GITHUB_REF##*/}
        elif [[ "$GITHUB_REF" == refs/pull/* ]]; then
          CURBRANCH=${GITHUB_REF%/*}
          CURBRANCH=${CURBRANCH##*/}
        elif [[ "$GITHUB_REF" == refs/heads/* ]]; then
          CURBRANCH=${GITHUB_REF##*/}
        fi

        # Remove forward slashes
        CURBRANCH=$( echo $CURBRANCH | sed 's+/+_+g' )
        echo "Building branch/tag ${CURBRANCH:-<unknown>}, from git ref <$GITHUB_REF>"
        echo "CURBRANCH=${CURBRANCH}" >> ${GITHUB_ENV}

        # Pacify git if we were to commit something
        git config user.email "nipreps@gmail.com"
        git config user.name "NiPreps Bot"
    - name: Install GraphViz
      run: |
        sudo apt-get update -y
        sudo apt-get install -y --no-install-recommends graphviz

    - name: Install dependencies
      run: |
        pip install -r docs/requirements.txt

    - name: Build docs
      run: |
          make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html

    - name: Push created tag to gh-pages
      if: startsWith(github.ref, 'refs/tags/')
      run: |
        MAJOR_MINOR=${CURBRANCH%.*}
        if [[ "${MAJOR_MINOR}" == "" ]]; then
            echo "Could not identify release series"
            exit 1
        fi
        git checkout -b gh-pages origin/gh-pages
        git rm -r ${MAJOR_MINOR}/ || true
        # It is fundamental that the directory does not exist at all.
        rm -rf ${MAJOR_MINOR}
        cp -r $HOME/docs/$CURBRANCH $PWD/${MAJOR_MINOR}
        git add ${MAJOR_MINOR}
        python -c "from pathlib import Path; import json; f=Path('versions.json'); d=json.loads(f.read_text()); d['tags'].append(\"${MAJOR_MINOR}\"); d['tags'] = list(sorted(set(d['tags']))); f.write_text(json.dumps(d, indent=4)); print('Updated versions.json')"
        git add versions.json
        git commit -m "rel(${CURBRANCH}): Update docs of ${MAJOR_MINOR} series" || true
        git push

    - name: Push "master" docs to gh-pages after a PR is merged
      if: github.ref == 'refs/heads/master'
      run: |
        if [[ "${CURBRANCH}" != "master" ]]; then
            echo "$CURBRANCH is not the default development branch"
            exit 1
        fi
        git checkout -b gh-pages origin/gh-pages
        git rm -r master/ || true
        # It is fundamental that the directory does not exist at all.
        rm -rf master
        cp -r $HOME/docs/$CURBRANCH $PWD/master
        git add master
        git commit -am "docs(master): Update docs of development line" || true
        git push


Python package

# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python package

on:
  push:
    branches: [ '**' ]
    tags: [ '*' ]
  pull_request:
    branches: [ master, 'maint/*' ]
  schedule:
    - cron: '0 0 * * *'

concurrency:
  group: python-${{ github.ref }}
  cancel-in-progress: true

jobs:
  job_metadata:
    if: github.repository == 'nipreps/niworkflows'
    runs-on: ubuntu-latest
    outputs:
      commit_message: ${{ steps.get_commit_message.outputs.commit_message }}
      version: ${{ steps.show_version.outputs.version }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Print head git commit message
        id: get_commit_message
        run: |
          if [[ -z "$COMMIT_MSG" ]]; then
            COMMIT_MSG=$(git show -s --format=%s $REF)
          fi
          echo commit_message=$COMMIT_MSG | tee -a $GITHUB_OUTPUT
        env:
          COMMIT_MSG: ${{ github.event.head_commit.message }}
          REF: ${{ github.event.pull_request.head.sha }}
      - name: Detect version
        id: show_version
        run: |
          if [[ "$GITHUB_REF" == refs/tags/* ]]; then
            VERSION=${GITHUB_REF##*/}
          else
            pipx run hatch version  # Once to avoid output of initial setup
            VERSION=$( pipx run hatch version )
          fi
          echo version=$VERSION | tee -a $GITHUB_OUTPUT

  build:
    if: github.repository == 'nipreps/niworkflows'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Python 3
      uses: actions/setup-python@v5
      with:
        python-version: 3
    - name: Display Python version
      run: python -c "import sys; print(sys.version)"
    - name: Build niworkflows
      run: pipx run build
    - name: Check distributions
      run: pipx run twine check dist/*
    - uses: actions/upload-artifact@v3
      with:
        name: dist
        path: dist/

  get_data:
    if: github.repository == 'nipreps/niworkflows'
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash -l {0}
    steps:
    - name: Create test data directory
      run: mkdir -p $HOME/.cache/stanford-crn
    - name: Load test data cache
      uses: actions/cache@v4
      id: stanford-crn
      with:
        path: ~/.cache/stanford-crn/
        key: data-v0-${{ github.ref_name }}-${{ github.sha }}
        restore-keys: |
          data-v0-${{ github.ref_name }}-
          data-v0-
    - name: Setup conda
      uses: conda-incubator/setup-miniconda@v3
      with:
        auto-activate-base: true
        activate-environment: ""
    - name: Verify environment
      run: |
        conda info
        which python
    - name: Install datalad
      run: |
        python -m pip install datalad-installer
        datalad-installer --sudo ok git-annex
        python -m pip install datalad datalad-osf
        datalad wtf
    - name: Pacify git
      run: |
        git config --global user.email "github@niworkflows.ci"
        git config --global user.name "Niworkflows Action"
    - name: Fetch test data
      run: |
        DS=$HOME/.cache/stanford-crn
        datalad install -r -s https://github.com/nipreps-data/niworkflows-data.git $DS
        cd $DS
        git -C BIDS-examples-1-enh-ds054 checkout enh/ds054
        datalad update -r --merge -d .
        datalad get -J 2 -r ds000003 ds000030/sub-10228/func

  test:
    needs: [build, get_data, job_metadata]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
        install: [repo]
        include:
          - python-version: "3.11"
            install: sdist
          - python-version: "3.11"
            install: wheel
          - python-version: "3.11"
            install: editable

    env:
      INSTALL_TYPE: ${{ matrix.install }}

    steps:
    - uses: actions/checkout@v4
      if: matrix.install == 'repo' || matrix.install == 'editable'
      with:
        fetch-depth: 0
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
    - name: Load test data cache
      uses: actions/cache@v4
      id: stanford-crn
      with:
        path: ~/.cache/stanford-crn/
        key: data-v0-${{ github.ref_name }}-${{ github.sha }}
    - name: Load TemplateFlow cache
      uses: actions/cache@v4
      id: templateflow
      with:
        path: ~/.cache/templateflow
        key: templateflow-v0-${{ github.ref_name }}-${{ strategy.job-index }}-${{ github.sha }}
        restore-keys: |
          templateflow-v0-${{ github.ref_name }}-
          templateflow-v0-
    - name: Fetch packages
      if: matrix.install == 'sdist' || matrix.install == 'wheel'
      uses: actions/download-artifact@v3
      with:
        name: dist
        path: dist/
    - name: Select archive
      run: |
        if [ "$INSTALL_TYPE" = "sdist" ]; then
          ARCHIVE=$( ls dist/*.tar.gz )
        elif [ "$INSTALL_TYPE" = "wheel" ]; then
          ARCHIVE=$( ls dist/*.whl )
        elif [ "$INSTALL_TYPE" = "repo" ]; then
          ARCHIVE="."
        elif [ "$INSTALL_TYPE" = "editable" ]; then
          ARCHIVE="-e ."
        fi
        echo "ARCHIVE=$ARCHIVE" | tee -a $GITHUB_ENV
    - name: Install package
      run: python -m pip install $ARCHIVE
    - name: Check version
      run: |
        INSTALLED_VERSION=$(python -c 'import niworkflows; print(niworkflows.__version__, end="")')
        echo "INSTALLED: \"${INSTALLED_VERSION}\""
        test "${INSTALLED_VERSION}" = "${VERSION}"
      env:
        VERSION: ${{ needs.job_metadata.outputs.version }}
    - name: Install test dependencies
      run: python -m pip install "niworkflows[tests]"
    - name: Run tests
      run: pytest -sv --doctest-modules --cov niworkflows --pyargs niworkflows
    - uses: codecov/codecov-action@v4
      name: Submit to CodeCov
      with:
        token: ${{ secrets.CODECOV_TOKEN }}

  test-pre:
    needs: [get_data, job_metadata]
    if: ${{ !contains(needs.job_metadata.outputs.commit_message, '[skip pre]') }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
        install: [repo]
        pip-flags: ['--pre']

    env:
      INSTALL_TYPE: ${{ matrix.install }}
      PIP_FLAGS: ${{ matrix.pip-flags }}

    steps:
    - name: Debug commit message
      run: echo "${{ needs.job_metadata.outputs.commit_message }}"
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
    - name: Load test data cache
      uses: actions/cache@v4
      id: stanford-crn
      with:
        path: ~/.cache/stanford-crn/
        key: data-v0-${{ github.ref_name }}-${{ github.sha }}
    - name: Load TemplateFlow cache
      uses: actions/cache@v4
      id: templateflow
      with:
        path: ~/.cache/templateflow
        key: templateflow-v0-${{ github.ref_name }}-${{ strategy.job-index }}-${{ github.sha }}
        restore-keys: |
          templateflow-v0-${{ github.ref_name }}-
          templateflow-v0-
    - name: Install package
      run: python -m pip install $PIP_FLAGS .
    - name: Check version
      run: |
        INSTALLED_VERSION=$(python -c 'import niworkflows; print(niworkflows.__version__, end="")')
        echo "INSTALLED: \"${INSTALLED_VERSION}\""
        test "${INSTALLED_VERSION}" = "${VERSION}"
      env:
        VERSION: ${{ needs.job_metadata.outputs.version }}
    - name: Install test dependencies
      run: python -m pip install $PIP_FLAGS "niworkflows[tests]"
    - name: Run tests
      run: pytest -sv --doctest-modules --cov niworkflows --pyargs niworkflows
    - uses: codecov/codecov-action@v4
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
      name: Submit to CodeCov

  flake8:
    if: github.event_name != 'schedule'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Set up Python 3
      uses: actions/setup-python@v5
      with:
        python-version: 3
    - run: pipx run flake8 niworkflows/


Docs CI

name: Docs CI

on: [push, pull_request]

jobs:
  docs:
    # pull requests are a duplicate of a branch push if they are from within the
    # same repo. Skip these
    if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
    strategy:
      matrix:
        python-version: [3.8]
      fail-fast: false
    runs-on: ubuntu-latest
    env:
      TOX_DIRECT: 1

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0 # So we get history for version numbers

      - name: Install Packages
        run: sudo apt-get install graphviz

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: pip install -e .[dev] && pipdeptree

      - name: Build Docs
        run: tox -e docs

      - name: Upload built docs as artifacts
        uses: actions/upload-artifact@v3
        with:
          name: docs
          path: build

      - name: Set env.REPOSITORY_NAME # just the repo, as opposed to org/repo
        run: echo "REPOSITORY_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV

      - name: Deploy documentation to blueskyproject.io.
        if: github.repository_owner == 'bluesky' && github.ref_name == 'master'
        # We pin to the SHA, not the tag, for security reasons.
        # https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
        uses: peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501 # v3.7.3
        with:
          deploy_key: ${{ secrets.ACTIONS_DOCUMENTATION_DEPLOY_KEY }}
          publish_branch: master
          publish_dir: build/html
          external_repository: bluesky/bluesky.github.io
          destination_dir: ${{ env.REPOSITORY_NAME }} # just the repo name, without the "bluesky/"
          keep_files: true # Keep old files.
          force_orphan: false # Keep git history.


Code CI

name: Code CI

on:
  push:
  pull_request:
  schedule:
    - cron: "00 4 * * *" # daily at 4AM

jobs:
  lint:
    # pull requests are a duplicate of a branch push if they are from within the
    # same repo. Skip these
    if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
    runs-on: "ubuntu-latest"
    steps:
      - uses: actions/checkout@v2

      - name: Lint
        run: pip install --user .[dev] && tox -e pre-commit,mypy

  build:
    if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
    runs-on: "ubuntu-latest"
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0 # So we get history for version numbers

      - name: Create Sdist and Wheel
        # Set SOURCE_DATE_EPOCH from git commit for reproducible build
        # https://reproducible-builds.org/
        run: SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) pipx run build --sdist --wheel

      - name: Upload Wheel and Sdist as artifacts
        uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist

      - name: Install wheel and check cli works
        run: pip install dist/*.whl && python -m ophyd --version

  test:
    if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
    runs-on: ubuntu-latest
    env:
      TEST_CL: pyepics

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0 # So we get history for version number

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: pip install --upgrade setuptools && pip install -e .[dev] && pipdeptree

      - name: Start IOCs in containers.
        run: |
          source ${GITHUB_WORKSPACE}/scripts/epics_exports.sh
          source ${GITHUB_WORKSPACE}/scripts/epics_docker.sh

      - name: Test with pytest
        run: pytest -k "${TEST_CL} or /v2/"

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v2
        with:
          name: ${{ matrix.python }}
          files: cov.xml

  release:
    needs: [build]
    runs-on: ubuntu-latest
    # upload to PyPI and make a release on every tag
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
    steps:
      - uses: actions/download-artifact@v3

      - name: Github Release
        # We pin to the SHA, not the tag, for security reasons.
        # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
        uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14
        with:
          files: dist/*
          generate_release_notes: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Publish to PyPI
        env:
          TWINE_USERNAME: __token__
          # The PYPI_PASSWORD must be a pypi token with the "pypi-" prefix with sufficient permissions to upload this package
          # https://pypi.org/help/#apitoken
          TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
        run: pipx run twine upload dist/*


libEnsemble-simple-CI

name: libEnsemble-simple-CI

on:
  pull_request:
    types:
      - ready_for_review
      - opened
      - reopened
      - synchronize

jobs:
    test-libE:
        if: '! github.event.pull_request.draft'
        runs-on: ${{ matrix.os }}
        strategy:
            fail-fast: false
            matrix:
                os: [ubuntu-latest]
                mpi-version: [mpich]
                python-version: [3.9, "3.10", "3.11", "3.12"]
                pydantic-version: ["2.6.4"]
                comms-type: [m, l]
                include:
                    - os: macos-latest
                      python-version: "3.11"
                      mpi-version: "mpich=4.2.1"
                      pydantic-version: "2.6.4"
                      comms-type: m
                    - os: macos-latest
                      python-version: "3.11"
                      mpi-version: "mpich=4.2.1"
                      pydantic-version: "2.6.4"
                      comms-type: l
                    - os: ubuntu-latest
                      mpi-version: mpich
                      python-version: "3.10"
                      pydantic-version: "1.10.13"
                      comms-type: m
                    - os: ubuntu-latest
                      mpi-version: mpich
                      python-version: "3.10"
                      pydantic-version: "1.10.13"
                      comms-type: l

        env:
            HYDRA_LAUNCHER: "fork"
            TERM: xterm-256color
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

        defaults:
            run:
                shell: bash -l {0}

        steps:
        - uses: actions/checkout@v4
        - name: Setup conda - Python ${{ matrix.python-version }}
          uses: conda-incubator/setup-miniconda@v3
          with:
            activate-environment: condaenv
            miniconda-version: "latest"
            python-version: ${{ matrix.python-version }}
            channels: conda-forge
            channel-priority: flexible
            auto-update-conda: true

        - uses: actions/cache/restore@v4
          name: Restore cached dependencies
          id: cache
          if: matrix.os == 'ubuntu-latest'
          with:
            path: |
              /home/runner/.local
              /usr/share/miniconda3/envs/condaenv
              /usr/share/miniconda3/bin
              /usr/share/miniconda3/lib
              /usr/share/miniconda3/include
            key: libe-${{ github.ref_name }}-${{ matrix.python-version }}-${{ matrix.comms-type }}-${{ matrix.pydantic-version }}-basic

        - name: Force-update certifi
          run: |
            python --version
            pip install -I --upgrade certifi

        - name: Install Ubuntu compilers
          if: matrix.os == 'ubuntu-latest'
          run: conda install gcc_linux-64

        # Roundabout solution on macos for proper linking with mpicc
        - name: Install macOS compilers
          if: matrix.os == 'macos-latest'
          run: |
            conda install clang_osx-64

        - name: Install basic testing/feature dependencies
          run: |
            pip install -r install/testing_requirements.txt
            pip install -r install/misc_feature_requirements.txt

            git clone --recurse-submodules -b develop https://github.com/POptUS/IBCDFO.git
            pushd IBCDFO/minq/py/minq5/
            export PYTHONPATH="$PYTHONPATH:$(pwd)"
            echo "PYTHONPATH=$PYTHONPATH" >> $GITHUB_ENV
            popd
            pushd IBCDFO/ibcdfo_pypkg/
            pip install -e .
            popd

        - name: Install mpi4py and MPI from conda
          run: |
            conda install mpi4py ${{ matrix.mpi-version }}

        - name: Install generator dependencies
          run: |
            python -m pip install --upgrade pip
            pip install mpmath matplotlib
            conda install numpy nlopt scipy

        - uses: actions/cache/save@v4
          name: Save dependencies to cache
          if: matrix.os == 'ubuntu-latest'
          with:
            path: |
              /home/runner/.local
              /usr/share/miniconda3/envs/condaenv
              /usr/share/miniconda3/bin
              /usr/share/miniconda3/lib
              /usr/share/miniconda3/include
            key: libe-${{ github.ref_name }}-${{ matrix.python-version }}-${{ matrix.comms-type }}

        - name: Install libEnsemble, flake8
          run: |
            pip install pydantic==${{ matrix.pydantic-version }}
            pip install -e .
            flake8 libensemble

        - name: Remove various tests on newer pythons
          if: matrix.python-version >= '3.11'
          run: |
            rm ./libensemble/tests/functionality_tests/test_local_sine_tutorial*.py # matplotlib errors on 3.12

        - name: Run simple tests, Ubuntu
          if: matrix.os == 'ubuntu-latest'
          run: |
           ./libensemble/tests/run-tests.sh -A "-W error" -z -${{ matrix.comms-type }}

        - name: Run simple tests, macOS
          if: matrix.os == 'macos-latest'
          run: |
            ./libensemble/tests/run-tests.sh -A "-W error" -z -${{ matrix.comms-type }}

        - name: Merge coverage
          run: |
            mv libensemble/tests/.cov* .

        - name: Upload coverage reports to Codecov
          uses: codecov/codecov-action@v4
          env:
            CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

    spellcheck:
        name: Spellcheck release branch
        if: contains(github.base_ref, 'develop')
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v4
        - uses: crate-ci/typos@v1.20.10


libEnsemble-complete-CI

name: libEnsemble-complete-CI

on:
  workflow_dispatch:

jobs:
    test-libE:
        runs-on: ${{ matrix.os }}
        strategy:
            fail-fast: false
            matrix:
                os: [ubuntu-latest]
                mpi-version: [mpich]
                python-version: [3.9, "3.10", "3.11", "3.12"]
                pydantic-version: ["2.6.4"]
                comms-type: [m, l]
                include:
                    - os: macos-latest
                      python-version: 3.11
                      mpi-version: "mpich=4.2.0"
                      pydantic-version: "2.6.4"
                      comms-type: m
                    - os: macos-latest
                      python-version: 3.11
                      mpi-version: "mpich=4.2.0"
                      pydantic-version: "2.6.4"
                      comms-type: l
                    - os: ubuntu-latest
                      python-version: "3.10"
                      mpi-version: "mpich"
                      pydantic-version: "2.6.4"
                      comms-type: t
                    - os: ubuntu-latest
                      mpi-version: "openmpi"
                      pydantic-version: "2.6.4"
                      python-version: "3.12"
                      comms-type: l
                    - os: ubuntu-latest
                      mpi-version: mpich
                      python-version: "3.10"
                      pydantic-version: "1.10.13"
                      comms-type: m
                    - os: ubuntu-latest
                      mpi-version: mpich
                      python-version: "3.10"
                      pydantic-version: "1.10.13"
                      comms-type: l

        env:
            HYDRA_LAUNCHER: "fork"
            TERM: xterm-256color
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

        defaults:
            run:
                shell: bash -l {0}

        steps:
        - uses: actions/checkout@v4
        - name: Setup conda - Python ${{ matrix.python-version }}
          uses: conda-incubator/setup-miniconda@v3
          with:
            activate-environment: condaenv
            miniconda-version: "latest"
            python-version: ${{ matrix.python-version }}
            channels: conda-forge
            channel-priority: flexible
            auto-update-conda: true

        - uses: actions/cache/restore@v4
          name: Restore cached dependencies
          id: cache
          if: matrix.os == 'ubuntu-latest'
          with:
            path: |
              /home/runner/work/libensemble/libensemble/heffte/build/
              /home/runner/.local
              /usr/share/miniconda3/envs/condaenv
              /usr/share/miniconda3/bin
              /usr/share/miniconda3/lib
              /usr/share/miniconda3/include
            key: libe-${{ github.ref_name }}-${{ matrix.python-version }}-${{ matrix.comms-type }}-${{ matrix.pydantic-version }}-extra

        - name: Force-update certifi
          run: |
            python --version
            pip install -I --upgrade certifi

        - name: Install Ubuntu compilers
          if: matrix.os == 'ubuntu-latest'
          run: conda install gcc_linux-64

        # Roundabout solution on macos for proper linking with mpicc
        - name: Install macOS compilers
          if: matrix.os == 'macos-latest'
          run: |
            conda install clang_osx-64

        - name: Install mpi4py and MPI from conda
          if: (matrix.python-version != '3.10' && matrix.os == 'ubuntu-latest') || matrix.os == 'macos-latest'
          run: |
            conda install mpi4py ${{ matrix.mpi-version }}

        - name: Install mpi4py from pip, MPI from conda
          if: matrix.python-version == '3.10' && matrix.os == 'ubuntu-latest'
          run: |
            conda install ${{ matrix.mpi-version }}
            pip install mpi4py

        - name: Install generator dependencies
          run: |
            python -m pip install --upgrade pip
            pip install mpmath matplotlib ax-platform
            conda env update --file install/gen_deps_environment.yml

        - name: Install ax-platform
          run: |
            pip install ax-platform

        - name: Install gpcam
          if: matrix.python-version != '3.12'
          run: |
            pip install gpcam

        - name: Install surmise
          if: matrix.os != 'macos-latest'
          run: |
            pip install --upgrade git+https://github.com/bandframework/surmise.git

        - name: Build ytopt and dependencies
          if: matrix.python-version <= '3.10' && matrix.os != 'macos-latest'
          run: |
            pip install scikit-learn==1.4.0
            pip install pandas==2.2.1
            pip install ConfigSpace
            pip install "ray[default]"
            git clone https://github.com/ytopt-team/scikit-optimize.git
            cd scikit-optimize
            pip install .
            cd ..
            git clone -b version1 https://github.com/ytopt-team/autotune.git
            cd autotune
            pip install .
            cd ..
            git clone -b main https://github.com/ytopt-team/ytopt.git
            cd ytopt
            pip install .
            cd ..

        - name: Install generator dependencies for Ubuntu tests
          if: matrix.os == 'ubuntu-latest' && matrix.python-version != '3.12'
          run: |
            sudo apt-get install bc

            # pip install dragonfly-opt
            # pip install git+https://github.com/dragonfly/dragonfly.git
            pip install git+https://github.com/jlnav/dragonfly.git@fix/remove_npobject
            pip install scikit-build packaging Tasmanian --user

        - name: Install other testing dependencies
          run: |
            conda install octave
            conda install pyzmq
            pip install -r install/testing_requirements.txt
            pip install -r install/misc_feature_requirements.txt
            git clone https://github.com/argonne-lcf/balsam.git
            sed -i -e "s/pyzmq>=22.1.0,<23.0.0/pyzmq>=23.0.0,<24.0.0/" ./balsam/setup.cfg
            cd balsam; pip install -e .; cd ..

            git clone --recurse-submodules -b develop https://github.com/POptUS/IBCDFO.git
            pushd IBCDFO/minq/py/minq5/
            export PYTHONPATH="$PYTHONPATH:$(pwd)"
            echo "PYTHONPATH=$PYTHONPATH" >> $GITHUB_ENV
            popd
            pushd IBCDFO/ibcdfo_pypkg/
            pip install -e .
            popd

        - name: Build heffte
          if: matrix.os != 'macos-latest'
          run: |
            # begin heffte build and dependencies
            sudo apt install libfftw3-dev
            git clone https://github.com/icl-utk-edu/heffte.git
            mkdir heffte/build
            cd heffte/build
            pwd
            cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=./ -D Heffte_ENABLE_AVX=ON -D Heffte_ENABLE_FFTW=ON ../
            make -j 4
            make install
            cp ./benchmarks/speed3d_c2c ../../libensemble/tests/regression_tests/
            # end heffte build and dependencies

        - uses: actions/cache/save@v4
          name: Save dependencies to cache
          if: matrix.os == 'ubuntu-latest'
          with:
            path: |
              /home/runner/work/libensemble/libensemble/heffte/build/
              /home/runner/.local
              /usr/share/miniconda3/envs/condaenv
              /usr/share/miniconda3/bin
              /usr/share/miniconda3/lib
              /usr/share/miniconda3/include
            key: libe-${{ github.ref_name }}-${{ matrix.python-version }}-${{ matrix.comms-type }}

        - name: Install libEnsemble, flake8, lock environment
          run: |
            pip install pydantic==${{ matrix.pydantic-version }}
            pip install -e .
            flake8 libensemble

        - name: Remove various tests on newer pythons
          if: matrix.python-version >= '3.11'
          run: |
            rm ./libensemble/tests/regression_tests/test_ytopt_heffte.py
            rm ./libensemble/tests/regression_tests/test_gpCAM.py
            rm ./libensemble/tests/regression_tests/test_persistent_gp.py

        - name: Remove test for persistent Tasmanian on Python 3.12
          if: matrix.python-version >= '3.12'
          run: |
            rm ./libensemble/tests/regression_tests/test_persistent_tasmanian.py
            rm ./libensemble/tests/regression_tests/test_persistent_tasmanian_async.py

        - name: Remove Balsam/Globus-compute tests on Pydantic 2
          if: matrix.pydantic-version == '2.6.4'
          run: |
            rm ./libensemble/tests/unit_tests/test_ufunc_runners.py
            rm ./libensemble/tests/unit_tests/test_executor_balsam.py

        - name: Run extensive tests, Ubuntu
          if: matrix.os == 'ubuntu-latest'
          run: |
           ./libensemble/tests/run-tests.sh -e -z -${{ matrix.comms-type }}

        - name: Run extensive tests, macOS
          if: matrix.os == 'macos-latest'
          run: |
            ./libensemble/tests/run-tests.sh -e -z -${{ matrix.comms-type }}

        - name: Merge coverage
          run: |
            mv libensemble/tests/.cov* .

        - name: Upload coverage reports to Codecov
          uses: codecov/codecov-action@v4
          env:
            CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

    spellcheck:
        name: Spellcheck release branch
        if: contains(github.base_ref, 'develop')
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v4
        - uses: crate-ci/typos@v1.20.10


CI

name: CI

on:
  push:
    branches:
      - "main"
  pull_request:
    branches:
      - "main"
  schedule:
    - cron:  "0 0 * * *"

jobs:
  test:
    if: github.event.pull_request.draft == false
    name: GMSO Tests
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [macOS-latest, macOS-13, ubuntu-latest]
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    defaults:
      run:
        shell: bash -l {0}

    steps:
      - uses: actions/checkout@v3
        name: Checkout Branch / Pull Request

      - name: Install Mamba
        uses: mamba-org/setup-micromamba@v1
        with:
          environment-file: environment-dev.yml
          create-args: >-
            python=${{ matrix.python-version }}

      - name: Install Package
        run: python -m pip install -e .

      - name: Test (OS -> ${{ matrix.os }} / Python -> ${{ matrix.python-version }})
        run: python -m pytest -v --cov=gmso --cov-report=xml --cov-append --cov-config=setup.cfg --color yes --pyargs gmso

      - name: Upload Coverage Report
        uses: codecov/codecov-action@v2
        with:
          name: GMSO-Coverage
          verbose: true

  bleeding-edge-test:
    if: github.event.pull_request.draft == false
    name: Bleeding Edge mosdef Tests for GMSO
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash -l {0}

    steps:
      - uses: actions/checkout@v3
        name: Checkout Branch / Pull Request

      - name: Install Mamba
        uses: mamba-org/setup-micromamba@v1
        with:
          environment-file: environment-dev.yml
          create-args: python=3.10

      - name: Clone mBuild and Foyer and forcefield-utilities
        run: |
          git clone https://github.com/mosdef-hub/mbuild.git
          git clone https://github.com/mosdef-hub/foyer.git
          git clone https://github.com/mosdef-hub/forcefield-utilities.git

      - name: Update Environment with mbuild/foyer/ffutils Dependencies
        run: |
          micromamba update --name gmso-dev --file mbuild/environment.yml
          micromamba update --name gmso-dev --file foyer/environment.yml
          micromamba update --name gmso-dev --file forcefield-utilities/environment-dev.yml

      - name: Install Packages from Source
        run: |
          pip install -e mbuild
          pip install -e foyer
          pip install -e forcefield-utilities
          pip install -e .

      - name: Run Bleeding Edge Tests
        run: |
          python -m pytest -v --color yes --pyargs gmso

  docker:
    runs-on: ubuntu-latest
    needs: test
    name: Build Docker Image
    if: github.event_name != 'pull_request'

    steps:
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Get Tagged Version
        run: |
          echo "DOCKER_TAGS=mosdef/gmso:${GITHUB_REF_NAME}, mosdef/gmso:stable" >> $GITHUB_ENV
        if: github.ref_type == 'tag'

      - name: Get Push Version
        run: |
          echo "DOCKER_TAGS=mosdef/gmso:${GITHUB_REF_NAME}, mosdef/gmso:latest" >> $GITHUB_ENV
        if: github.ref_type == 'branch'

      - name: Docker Image Info
        run: |
          echo Docker Image tags: ${DOCKER_TAGS}

      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ env.DOCKER_TAGS }}


CodeQL

name: "CodeQL"

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  schedule:
    - cron: "41 4 * * 6"

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ python ]

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

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

      - name: Autobuild
        uses: github/codeql-action/autobuild@v2

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
        with:
          category: "/language:${{ matrix.language }}"


CI pipeline on Mamba

# Basic Mamba CI pipeline on top of CCTBX

name: CI pipeline on Mamba

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]
  # run daily to ensure that changes to dependenices are not breaking tests
  schedule:
    - cron: "30 21 * * *"
  workflow_dispatch:

env:
  # MOPAC_COMMAND: $CONDA_PREFIX/bin/mopac
  # XTBHOME: $CONDA_PREFIX
  PY: "python3.10"
  #CLEANUP_TESTS: 'FALSE'

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash -leo pipefail {0} {0}

    steps:
      - name: checkout code
        uses: actions/checkout@v4

      - name: df
        run: df -h

      - uses: mamba-org/setup-micromamba@v1.8.0
        with:
          environment-file: environment.yaml
          cache-environment: true
          environment-name: qrefine-ci-mamba
          post-cleanup: all

      - name: run installer
        run: |
          sh build_into_conda.sh

      - name: smoke test
        run: |
          source $CONDA_PREFIX/lib/$PY/site-packages/build/setpaths.sh
          qr.refine --help
          env

      - name: qr.test
        run: |
          cd  /home/runner/work/qrefine/qrefine/
          pwd
          mkdir testing_workdir
          cd testing_workdir
          source $CONDA_PREFIX/lib/$PY/site-packages/build/setpaths.sh
          qr.test | tee ../qr_test.txt

      - name: looks at testing_workdir
        if: always()
        run: ls -R
        working-directory: /home/runner/work/qrefine/qrefine/testing_workdir

      - name: Archive qr test output
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: qr-test-output
          path: ./qr_test.txt

      - name: Archive qr-log files output
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: tests-dir
          path: /home/runner/work/qrefine/qrefine/testing_workdir

    # Too much noise at the moment
    #- name: Report Status
    #  if: always()
    #  uses: ravsamhq/notify-slack-action@v2
    #  with:
    #    status: ${{ job.status }}
    #    notify_when: 'failure'
    #  env:
    #    SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}


name: Publish image to public repository on dockerhub

on:
  workflow_dispatch:

env:
  container_name: qrefine/cctbx-qr

jobs:
  push:
    runs-on: ubuntu-latest
    steps:

      - name: Checkout
        uses: actions/checkout@v4

      - name: set name
        id: vars
        run: |
          calculatedSha=$(git rev-parse --short ${{ github.sha }})
          echo "container_name=$container_name:v$GITHUB_RUN_NUMBER" >> $GITHUB_ENV
          echo "Container Name:  $container_name:v$GITHUB_RUN_NUMBER"
          echo "Build/Run ID  :  $GITHUB_RUN_NUMBER"
          echo "Git hash      :  $calculatedSha"

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Docker build
        uses: docker/build-push-action@v5
        with:
          file: Dockerfile
          push: true
          tags: ${{env.container_name}}

      # - name: Build, tag, and push docker image to Dockerhub
      #   env:
      #     IMAGE_TAG: ${{ github.sha }}
      #   run: |
      #     docker build -f Dockerfile -t $REGISTRY/$REPOSITORY:$IMAGE_TAG  .
      #     docker push -a $REGISTRY/$REPOSITORY