Publish on Pypi

name: Publish on Pypi

on:
  workflow_dispatch:
    inputs:
      version:
        description: "The tag of the package to publish on Pypi (ex: 1.0.0, 1.0.0.dev0)"
        required: true

jobs:
  test-package:
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: Extract Github Tag Version
        id: vars
        run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT

      - name: Ensure package version is properly set
        run: |
          echo """
          import json, sys, os
          with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
            version_o = json.load(version_file)
          version = f'{version_o.get(\"major\")}.{version_o.get(\"minor\")}.{version_o.get(\"patch\")}'
          if vext := version_o.get(\"ext\"):
            version = f'{version}.{vext}'
          if version != sys.argv[1]:
            raise ValueError(f\"Invalid version {version} / {sys.argv[1]}\")
          if sys.argv[1] != sys.argv[2]:
            raise ValueError(f\"Invalid tag version {sys.argv[2]} with package version {sys.argv[1]}\")
          """ > /tmp/check.py
          python /tmp/check.py "${{ github.event.inputs.version }}" "${{ steps.vars.outputs.tag }}"

      - name: Download assets from github release tag
        run: |
          gh release download ${{ github.event.inputs.version }} --dir dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Verify there is a release asset
        run: |
          if [ ! -f dist/${{ github.event.repository.name }}-${{ github.event.inputs.version }}.tar.gz ]; then
            echo "No release asset found"
            exit 1
          fi

  publish-to-pypi:
    needs: [test-package]
    timeout-minutes: 20
    environment: publish
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Download assets from tag
        run: |
          gh release download ${{ github.event.inputs.version }} --dir dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          user: __token__
          password: ${{ secrets.PYPI_API_TOKEN }}

  test-published-package:
    needs: [publish-to-pypi]
    timeout-minutes: 30
    strategy:
      matrix:
        python-versions: ['3.8','3.9','3.10', '3.11']
        os: [ubuntu-latest,windows-latest,macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-versions }}

      - name: Install package
        run: |
          pip install --upgrade pip
          pip install --no-cache-dir ${{ github.event.repository.name }}==${{ github.event.inputs.version }}


Create Github Dev Release

name: Create Github Dev Release

on:
  workflow_dispatch:
    inputs:
      taipy-config-version:
        description: "The taipy-config version to use (ex: 2.3.0.dev0)"

jobs:
  release-dev-package:
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ssh-key: ${{secrets.DEPLOY_KEY}}

      - uses: actions/setup-python@v4
        with:
          python-version: 3.8

      - name: Ensure package version has 'dev' suffix
        run: |
          echo """
          import json, sys, os
          SUFFIX = 'dev'
          with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
              version_o = json.load(version_file)
          version = f'{version_o.get(\"major\")}.{version_o.get(\"minor\")}.{version_o.get(\"patch\")}'
          if vext := version_o.get(\"ext\"):
              version = f'{version}.{vext}'
          if SUFFIX not in version:
              raise ValueError(f\"version {version} does not contain suffix {SUFFIX}\")
          """ > /tmp/check1.py
          python /tmp/check1.py

      - name: Extract package version
        id: current-version
        run: |
          echo """
          import json, os
          with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
              version_o = json.load(version_file)
          version = f'{version_o.get(\"major\")}.{version_o.get(\"minor\")}.{version_o.get(\"patch\")}'
          if vext := version_o.get(\"ext\"):
              version = f'{version}.{vext}'
          print(f'VERSION={version}')
          """ > /tmp/check2.py
          python /tmp/check2.py >> $GITHUB_OUTPUT

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install build

      - name: Check dependencies are available
        if: github.event.inputs.taipy-config-version != ''
        run: |
          curl https://pypi.org/simple/taipy-config/ | grep -o ">taipy-config-${{ github.event.inputs.taipy-config-version }}\.tar\.gz<"

      - name: Update setup.py locally
        if: github.event.inputs.taipy-config-version != ''
        run: |
          mv setup.py setup.taipy.py
          echo """
          import sys
          with open('setup.taipy.py', mode='r') as setup_r, open('setup.py', mode='w') as setup_w:
              in_requirements = False
              looking = True
              for line in setup_r:
                  if looking:
                      if line.lstrip().startswith('requirements') and line.rstrip().endswith('['):
                          in_requirements = True
                      elif in_requirements:
                          if line.strip() == ']':
                              looking = False
                          else:
                              if line.lstrip().startswith('\"taipy-config@git+https'):
                                  start = line.find('\"taipy-config')
                                  end = line.rstrip().find(',')
                                  line = f'{line[:start]}\"taipy-config=={sys.argv[1]}\"{line[end:]}'
                  setup_w.write(line)
          """ > /tmp/write_setup_taipy.py
          python /tmp/write_setup_taipy.py "${{ github.event.inputs.taipy-config-version }}"

      - name: Build package
        run: python setup.py build_py && python -m build

      - name: Install the package and test it
        run: |
          # Install package
          echo "Installing package..."
          pip install ./dist/${{ github.event.repository.name }}-${{ steps.current-version.outputs.VERSION }}.tar.gz

          # Run tests
          python -c "import taipy as tp; tp.Scenario"

      - name: Extract commit hash
        shell: bash
        run: echo "##[set-output name=hash;]$(echo $(git rev-parse HEAD))"
        id: extract_hash

      - name: Create/update release and tag
        run: |
          echo "Creating release ${{ steps.current-version.outputs.VERSION }}"
          gh release create ${{ steps.current-version.outputs.VERSION }} ./dist/${{ github.event.repository.name }}-${{ steps.current-version.outputs.VERSION }}.tar.gz --target ${{ steps.extract_hash.outputs.hash }} --prerelease --title ${{ steps.current-version.outputs.VERSION }} --notes "Dev Release ${{ steps.current-version.outputs.VERSION }}"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Reset changes
        run: |
          git reset --hard HEAD
          git clean -fdx

      - name: Increase dev version
        id: new-version
        run: |
          echo """
          import json, os
          with open(f'src{os.sep}taipy{os.sep}core{os.sep}version.json') as version_file:
              version_o = json.load(version_file)
              if version_o is None or 'dev' not in version_o['ext']:
                  raise ValueError('Invalid version file. Version must contain dev suffix.')
              prev_version = version_o['ext']
              new_version = 'dev' + str(int(version_o['ext'].replace('dev', '')) + 1)
              with open(f'src{os.sep}taipy{os.sep}core{os.sep}version.json') as r:
                  text = r.read().replace(prev_version, new_version)
              with open(f'src{os.sep}taipy{os.sep}core{os.sep}version.json', mode='w') as w:
                  w.write(text)
              with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
                  version_o = json.load(version_file)
              version = f'{version_o.get(\"major\")}.{version_o.get(\"minor\")}.{version_o.get(\"patch\")}'
              if vext := version_o.get(\"ext\"):
                  version = f'{version}.{vext}'
              print(f'VERSION={version}')
          """ > /tmp/increase_dev_version.py
          python /tmp/increase_dev_version.py >> $GITHUB_OUTPUT

      - uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: Update version to ${{ steps.new-version.outputs.VERSION }}


Create Github Release

name: Create Github Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: "The release/package version to create (ex: 1.0.0)"
        required: true

jobs:
  release-package:
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: Extract branch name
        shell: bash
        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
        id: extract_branch

      - name: Ensure package version is properly set
        run: |
          echo """
          import json, sys, os
          with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
              version_o = json.load(version_file)
          version = f'{version_o.get(\"major\")}.{version_o.get(\"minor\")}.{version_o.get(\"patch\")}'
          if vext := version_o.get(\"ext\"):
              version = f'{version}.{vext}'
          if version != sys.argv[1]:
              raise ValueError(f\"Invalid version {version} / {sys.argv[1]}\")
          """ > /tmp/check1.py
          python /tmp/check1.py "${{ github.event.inputs.version }}"

      - name: Validate branch name
        run: |
          echo """
          import json, sys, os
          with open(f\"src{os.sep}taipy{os.sep}core{os.sep}version.json\") as version_file:
              version = json.load(version_file)
          if f'release/{version.get(\"major\")}.{version.get(\"minor\")}' != sys.argv[1]:
              raise ValueError(f'Branch name mismatch: release/{version.get(\"major\")}.{version.get(\"minor\")} != {sys.argv[1]}')
          """ > /tmp/check2.py
          python /tmp/check2.py "${{ steps.extract_branch.outputs.branch }}"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install build

      - name: Build and install package
        run: |
          python setup.py build_py && python -m build
          pip install dist/*.tar.gz

      - name: Extract commit hash
        shell: bash
        run: echo "##[set-output name=hash;]$(echo $(git rev-parse HEAD))"
        id: extract_hash

      - name: Create/update release and tag
        run: |
            gh release create ${{ github.event.inputs.version }} ./dist/${{ github.event.repository.name }}-${{ github.event.inputs.version }}.tar.gz --target ${{ steps.extract_hash.outputs.hash }} --title ${{ github.event.inputs.version }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


Python tests

name: Python tests

on:
  push:
    branches: [ develop, dev/*, release/* ]
  pull_request:
    branches: [ develop , dev/*, release/* ]

jobs:
  backend:
    timeout-minutes: 20
    strategy:
      matrix:
        python-versions: ['3.8', '3.9', '3.10', '3.11']
        os: [ubuntu-latest, windows-latest, macos-latest]
      fail-fast: false
    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-versions }}

      - name: Install Tox
        run: pip install tox

      - name: Run linter and all tests except Pyodbc's, Pymysql's, Psycopg2's, and Fastparquet
        if: matrix.python-versions == '3.10' && matrix.os == 'windows-latest'
        env:
          TOX_PARALLEL_NO_SPINNER: 1
        run: tox -p all

      - name: Ensure no usage of manager or repository classes without factory
        if: matrix.python-versions == '3.10' && matrix.os == 'ubuntu-latest'
        run: |
          ! grep -rP '_ScenarioManager(?!Factory)' taipy --exclude="_scenario_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_DataManager(?!Factory)' taipy --exclude="_data_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_TaskManager(?!Factory)' taipy --exclude="_task_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_SequenceManager(?!Factory)' taipy --exclude="_sequence_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_JobManager(?!Factory)' taipy --exclude="_job_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_CycleManager(?!Factory)' taipy --exclude="_cycle_manager*.py" --exclude-dir="__pycache__"
          ! grep -rP '_ScenarioRepository(?!Factory)' taipy --exclude="_scenario_repository*.py" --exclude-dir="__pycache__"
          ! grep -rP '_DataRepository(?!Factory)' taipy --exclude="_data_repository*.py" --exclude-dir="__pycache__"
          ! grep -rP '_TaskRepository(?!Factory)' taipy --exclude="_task_repository*.py" --exclude-dir="__pycache__"
          ! grep -rP '_SequenceRepository(?!Factory)' taipy --exclude="_sequence_repository*.py" --exclude-dir="__pycache__"
          ! grep -rP '_JobRepository(?!Factory)' taipy --exclude="_job_repository*.py" --exclude-dir="__pycache__"
          ! grep -rP '_CycleRepository(?!Factory)' taipy --exclude="_cycle_repository*.py" --exclude-dir="__pycache__"

      - name: Run all tests
        if: matrix.python-versions != '3.10' || matrix.os != 'windows-latest'
        env:
          TOX_PARALLEL_NO_SPINNER: 1
        run: tox -e all-tests


Benchmark on taipy-integration-testing

name: Benchmark on taipy-integration-testing
on:
  push:
    branches: [develop]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger taipy-integration-testing
        uses: peter-evans/repository-dispatch@v1
        with:
          token: ${{secrets.TAIPY_INTEGRATION_TESTING_ACCESS_TOKEN}}
          repository: avaiga/taipy-integration-testing
          event-type: benchmark
          client-payload: '{"repo": "taipy-core", "commitSHA": "${{ github.sha }}"}'


name: Integration testings on taipy-integration-testing
on:
  push:
    branches: [ develop, dev/* ]
  pull_request:
    branches: [ develop , dev/* ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger taipy-integration-testing
        uses: convictional/trigger-workflow-and-wait@v1.6.1
        with:
          owner: Avaiga
          repo: taipy-integration-testing
          github_token: ${{secrets.TAIPY_INTEGRATION_TESTING_ACCESS_TOKEN}}
          workflow_file_name: tests.yml
          ref: develop
          wait_interval: 60
          propagate_failure: true
          trigger_workflow: true
          wait_workflow: true
          client_payload: '{"repo": "taipy-core", "commitSHA": "${{ github.sha }}"}'


ci

name: ci

on:
  push:
    branches:
      - master
      - renovate/*
      - dev/*
    tags:
      - v*
  pull_request:
    branches:
      - master
      - dev/*
      - stable/*

jobs:
  ci:
    uses: AmpelProject/Ampel-interface/.github/workflows/ci.yml@e880b6e4cc9827cb4a85a06d00cb36738d9dda93 # ci-py12-v3
    secrets: inherit
    with:
      mongo: true
      lint: true
      # renovate: datasource=conda depName=conda-forge/python
      python-version: "3.12.4"
      # renovate: datasource=pypi depName=ruff
      ruff-version: "0.4.9"


docs

name: docs
on:
    push:
        branches:
            - master
jobs:
    deploy:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
              with:
                  fetch-depth: 0
            - uses: actions/setup-python@v5
              with:
                  python-version: "3.11"
            - name: Install GDAL
              run: |
                  python -m pip install --upgrade pip
                  pip install --find-links=https://girder.github.io/large_image_wheels --no-cache GDAL pyproj
            - name: Test GDAL installation
              run: |
                  python -c "from osgeo import gdal"
                  gdalinfo --version
            - name: Install libgeos
              run: sudo apt -y install libgeos-dev
            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  pip install --user --no-cache-dir Cython
                  pip install .[all]
            - name: LOAD EE CREDENTIALS
              run: python ./.github/ee_token.py
              env:
                  EARTHENGINE_TOKEN: ${{ secrets.EARTHENGINE_TOKEN }}
            - name: GEEMAP-TEST
              run: |
                  python -m unittest discover tests/
            - run: pip install -r requirements_docs.txt
            - run: cp -R examples/data docs/data
            - run: mkdocs gh-deploy --force
              env:
                  USE_FOLIUM: ${{ secrets.USE_FOLIUM }}
                  USE_MKDOCS: ${{ secrets.USE_MKDOCS }}


pypi

# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: pypi

on:
    release:
        types: [created]

jobs:
    deploy:
        runs-on: ubuntu-latest

        steps:
            - uses: actions/checkout@v4
            - name: Set up Python
              uses: actions/setup-python@v5
              with:
                  python-version: "3.x"
            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  pip install setuptools wheel twine
            - name: Build and publish
              env:
                  TWINE_USERNAME: ${{ secrets.PYPI_USERS }}
                  TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
              run: |
                  pip install build
                  python -m build
                  twine upload dist/*


macOS build

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

name: macOS build
jobs:
    test-macOS:
        runs-on: ${{ matrix.config.os }}
        name: ${{ matrix.config.os }} (${{ matrix.config.py }})
        strategy:
            fail-fast: false
            matrix:
                config:
                    - { os: macOS-latest, py: "3.11" }
        env:
            SDKROOT: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
        steps:
            - name: CHECKOUT CODE
              uses: actions/checkout@v4
            - name: SETUP PYTHON
              uses: actions/setup-python@v5
              with:
                  python-version: ${{ matrix.config.py }}
            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  pip install --no-cache-dir Cython
                  pip install -r requirements.txt
                  pip install .


Linux build

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

name: Linux build
jobs:
    test-ubuntu:
        runs-on: ubuntu-latest
        strategy:
            fail-fast: false
            matrix:
                python-version: ["3.8", "3.9", "3.10", "3.11"]
        steps:
            - uses: actions/checkout@v4
            - name: Set up Python
              uses: actions/setup-python@v5
              with:
                  python-version: ${{ matrix.python-version }}
            - name: Install GDAL
              run: |
                  python -m pip install --upgrade pip
                  pip install --no-cache-dir Cython
                  pip install --find-links=https://girder.github.io/large_image_wheels --no-cache GDAL
            - name: Test GDAL installation
              run: |
                  python -c "from osgeo import gdal"
                  gdalinfo --version
            - name: Install dependencies
              run: |
                  pip install .[all]
            - name: PKG-TEST
              run: |
                  python -m unittest discover tests/
              env:
                  HEREMAPS_API_KEY: ${{ secrets.HEREMAPS_API_KEY }}
                  PLANET_API_KEY: ${{ secrets.PLANET_API_KEY }}
                  EARTHENGINE_TOKEN: ${{ secrets.EARTHENGINE_TOKEN }}


Windows build

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

name: Windows build
jobs:
    test-windows:
        runs-on: windows-latest
        steps:
            - uses: actions/checkout@v4
            - name: Install miniconda
              uses: conda-incubator/setup-miniconda@v3
              with:
                  auto-activate-base: true
                  python-version: "3.11"
            - name: Install GDAL
              run: conda install -c conda-forge gdal --yes
            - name: Test GDAL installation
              run: |
                  python -c "from osgeo import gdal"
                  gdalinfo --version
            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  pip install --no-cache-dir Cython
                  pip install -r requirements.txt
                  pip install .


CodeQL

# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
    push:
        branches: ["master"]
    pull_request:
        # The branches below must be a subset of the branches above
        branches: ["master"]
    schedule:
        - cron: "31 20 * * 6"

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

        strategy:
            fail-fast: false
            matrix:
                language: ["javascript", "python"]
                # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
                # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

        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.

                  # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
                  # queries: security-extended,security-and-quality

            # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
            # If this step fails, then you should remove it and run the build manually (see below)
            - name: Autobuild
              uses: github/codeql-action/autobuild@v3

            # ℹ Command-line programs to run using the OS shell.
            # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

            #   If the Autobuild fails above, remove it and uncomment the following three lines.
            #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

            # - run: |
            #   echo "Run, Build Application using script"
            #   ./location_of_script_within_repo/buildscript.sh

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


Dependency Review

# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: "Dependency Review"
on: [pull_request]

permissions:
    contents: read

jobs:
    dependency-review:
        runs-on: ubuntu-latest
        steps:
            - name: "Checkout Repository"
              uses: actions/checkout@v4
            - name: "Dependency Review"
              uses: actions/dependency-review-action@v4


docs-build

name: docs-build
on:
    pull_request:
        branches:
            - master
jobs:
    deploy:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
              with:
                  fetch-depth: 0
            - uses: actions/setup-python@v5
              with:
                  python-version: "3.11"
            - name: Install GDAL
              run: |
                  python -m pip install --upgrade pip
                  pip install --find-links=https://girder.github.io/large_image_wheels --no-cache GDAL pyproj
            - name: Test GDAL installation
              run: |
                  python -c "from osgeo import gdal"
                  gdalinfo --version
            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  pip install --user --no-cache-dir Cython
                  pip install .[all]
            - name: LOAD EE CREDENTIALS
              run: python ./.github/ee_token.py
              env:
                  EARTHENGINE_TOKEN: ${{ secrets.EARTHENGINE_TOKEN }}
            - name: GEEMAP-TEST
              run: |
                  python -m unittest discover tests/
            - run: pip install -r requirements_docs.txt
            - run: cp -R examples/data docs/data
            - run: mkdocs build
              env:
                  USE_FOLIUM: ${{ secrets.USE_FOLIUM }}
                  USE_MKDOCS: ${{ secrets.USE_MKDOCS }}
            - name: Deploy to Netlify
              uses: nwtgck/actions-netlify@v3.0
              with:
                  publish-dir: "./site"
                  production-branch: master
                  github-token: ${{ secrets.GITHUB_TOKEN }}
                  deploy-message: "Deploy from GitHub Actions"
                  enable-pull-request-comment: true
                  enable-commit-comment: false
                  overwrites-pull-request-comment: true
              env:
                  NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
                  NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
              timeout-minutes: 10


Docker Image CI

name: Docker Image CI

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

jobs:
    build:
        runs-on: ubuntu-latest

        steps:
            - uses: actions/checkout@v4
            - name: Build the Docker image
              run: docker build . --file Dockerfile --tag ${{ github.repository }}:$(date +%s)


Publish Docker image

name: Publish Docker image

on:
    release:
        types: [published]

jobs:
    push_to_registries:
        name: Push Docker image to multiple registries
        runs-on: ubuntu-latest
        permissions:
            packages: write
            contents: read
        steps:
            - name: Check out the repo
              uses: actions/checkout@v4

            - name: Log in to Docker Hub
              uses: docker/login-action@v3
              with:
                  username: ${{ secrets.DOCKER_USERNAME }}
                  password: ${{ secrets.DOCKER_PASSWORD }}

            - name: Log in to the Container registry
              uses: docker/login-action@v3
              with:
                  registry: ghcr.io
                  username: ${{ github.actor }}
                  password: ${{ secrets.GITHUB_TOKEN }}

            - name: Extract metadata (tags, labels) for Docker
              id: meta
              uses: docker/metadata-action@v5
              with:
                  images: |
                      giswqs/geemap
                      ghcr.io/${{ github.repository }}

            - name: Build and push Docker images
              uses: docker/build-push-action@v6
              with:
                  context: .
                  push: true
                  tags: ${{ steps.meta.outputs.tags }}
                  labels: ${{ steps.meta.outputs.labels }}


Linux installation

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

name: Linux installation
jobs:
    test-ubuntu:
        runs-on: ubuntu-latest
        strategy:
            fail-fast: false
            matrix:
                python-version: ["3.12"]
        steps:
            - uses: actions/checkout@v4
            - name: Set up Python
              uses: actions/setup-python@v5
              with:
                  python-version: ${{ matrix.python-version }}
            - name: Install package
              run: |
                  pip install setuptools
                  pip install .
            - name: Test import
              run: python -c "import geemap; print('geemap import successful')"


Version Bump merged

name: Version Bump merged

on:
  pull_request:
    types:
      - "closed"
    branches:
      - "main"

jobs:
  trigger-release:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged &&
        startsWith(github.head_ref, 'bump_version_to_') &&
        startsWith(github.event.pull_request.title, 'Bump version') &&
        contains(github.event.pull_request.title, ' → ')
    environment: Create Release
    steps:
      - name: Get new version
        id: get-new-version
        run: |
          NEW_VERSION=$(echo ${{ github.head_ref }} | cut -d _ -f4 )
          echo "::set-output name=version::$NEW_VERSION"
      - name: Is prerelease?
        id: is-prerelease
        run: |
          IS_PRERELEASE=$([[ "${{ steps.get-new-version.outputs.version }}" == *-[a-z]* ]] && echo true || echo false)
          echo "::set-output name=result::$IS_PRERELEASE"
      - name: Create Release
        # Using full SHA for security
        # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
        uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
        with:
          token: ${{ secrets.ACCESS_TOKEN }}
          tag: v${{ steps.get-new-version.outputs.version }}
          name: v${{ steps.get-new-version.outputs.version }} Release
          commit: main
          prerelease: ${{ steps.is-prerelease.outputs.result }}


CI

name: CI

# Workflow does NOT trigger on a feature branch until a pull request is created.
# Workflow will always run when a pull request is merged to the default branch.
on:
  pull_request: {}
  push:
      branches: ["main"]
env:
  PYTHON_VERSION: "3.12"

jobs:
  bandit:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch

      - name: Run bandit
        run: hatch run bandit-ci

  black:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - name: Set up Python
        uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch

      - name: Run black
        run: hatch run black-check

  flake8:
    runs-on: ubuntu-latest
    steps:
        - name: Check out code
          uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
          with:
            python-version: ${{ env.PYTHON_VERSION }}
        - name: Initialize Hatch
          uses: ./.github/actions/initialize-hatch

        - name: Run flake8
          run: hatch run flake8-check

  isort:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch

      - name: Run isort
        run: hatch run isort-check

  mypy:
    runs-on: ubuntu-latest
    steps:
        - name: Check out code
          uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
          with:
            python-version: ${{ env.PYTHON_VERSION }}
        - name: Initialize Hatch
          uses: ./.github/actions/initialize-hatch

        - name: Run mypy
          run: hatch run typing

  renovate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - name: 🧼 lint renovate config # Validates changes to renovate.json config file
        uses: suzuki-shunsuke/github-action-renovate-config-validator@b54483862375f51910a60c4f498e927d4f3df466 # v1.0.1
        with:
          config_file_path: 'renovate.json'

  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
    steps:
        - name: Check out code
          uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
          with:
            python-version: ${{ matrix.python-version }}
        - name: Initialize Hatch
          uses: ./.github/actions/initialize-hatch

        - name: Run pytest
          run: hatch run test-ci --cov-report xml:coverage-${{ matrix.python-version }}.xml --junitxml=test-results-${{ matrix.python-version }}.xml

        - name: Upload pytest test results artifact
          uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
          with:
            name: pytest-results-${{ matrix.python-version }}
            path: test-results-${{ matrix.python-version }}.xml
          # Use always() to always run this step to publish test results when there are test failures
          if: ${{ always() }}

        - name: Upload coverage results artifact
          uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
          with:
            name: pytest-coverage-${{ matrix.python-version }}
            path: coverage-${{ matrix.python-version }}.xml
          # Use always() to always run this step to publish test results when there are test failures
          if: ${{ always() }}

        - name: Publish coverage results to Codecov
          uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
          with:
            file: coverage-${{ matrix.python-version }}.xml
            fail_ci_if_error: true
            token: ${{ secrets.CODECOV_TOKEN }}

  verify-wheel:
    runs-on: ubuntu-latest
    strategy:
          matrix:
            python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ matrix.python-version }}
      - name: Build wheel
        uses: ./.github/actions/build-dist
      - name: Verify wheel
        uses: ./.github/actions/verify-wheel
        with:
          package-import-name: "columbo"

  build-devbox-image:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - name: Build devbox image
        run: docker-compose build devbox

  validate-doc-examples:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch

      - name: Validate docs
        run: hatch run test-docs-examples

  build-docs:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch
        with:
          environment-name: "docs"

      - name: Build Docs
        run: hatch run docs:build

      - name: Upload coverage results artifact
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: docs-site
          path: site/

  update-dev-docs:
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch
        with:
          environment-name: "docs"
          activate: "true"

      - name: Push documentation changes
        uses: ./.github/actions/publish-docs-with-mike
        with:
          version_name: dev


Publish Release

name: Publish Release

env:
  PYTHON_VERSION: "3.12"

on:
  release:
    types: [published]

jobs:
  update_docs_for_version_bump:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Initialize Hatch
        uses: ./.github/actions/initialize-hatch
        with:
          environment-name: "docs"
          activate: "true"

      - name: Push documentation changes
        uses: ./.github/actions/publish-docs-with-mike
        with:
          new_version: true

  build-distributions:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: Build wheel
        uses: ./.github/actions/build-dist

      - name: Upload distribution artifacts
        uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
        with:
          name: distributions
          path: ./dist

  publish-to-pypi:
    runs-on: ubuntu-latest
    environment: "Publish Release"
    permissions:
      id-token: write
    needs: ["build-distributions"]
    steps:
      - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
        with:
            name: distributions
            path: ./dist

      - name: Publish distribution 📦 to PyPI
        uses: pypa/gh-action-pypi-publish@ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0 # v1.9.0


coverage

name: coverage

on:
  push:
    branches:
      - master

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.8']

    steps:
    - uses: actions/checkout@v2
    - 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
        python -m pip install tox
        python -m pip install coverage
    - name: Run tests with coverage
      run: |
        tox -e coverage
        coverage xml
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v1


tests

# 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: tests

on: [push, pull_request]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.12'] # , 'pypy3']  # pypy3 is broken on github actions right now
        django-version: ['3.2', '4.0', '4.1', '4.2', '5.0']

    steps:
    - uses: actions/checkout@v2
    - 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
        python -m pip install tox
    - name: Run tests
      run: |
        python .github/run-tests.py ${{ matrix.python-version }} ${{ matrix.django-version }}

#  lint:
#    runs-on: ubuntu-latest
#    strategy:
#      matrix:
#        python-version: ['3.8']
#
#    steps:
#    - uses: actions/checkout@v2
#    - 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
#        python -m pip install tox
#    - name: Run lint
#      run: |
#        tox -e lint
#    - name: Run black
#      run: |
#        tox -e black -- --check --diff


CI

# 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: CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  build:

    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ["3.7", "3.8", "3.9"]
        include:
          - os: macos-latest
            python-version: "3.8"
    runs-on: ${{ matrix.os }}

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements/dev.txt
        pip install "Pillow==9.1.1"
        # MindSpore must be installed following the instruction from official web, but not from pypi.
        # That's why we exclude mindspore from requirements.txt. Does this work?
        pip install "mindspore>=1.8"
    - name: Lint with pre-commit
      uses: pre-commit/action@v3.0.0
    - name: Test with pytest (UT)
      run: |
        pytest tests/modules/*.py
    - name: Test with pytest (ST)
      run: |
        pytest tests/tasks/*.py


Upload Python Package

# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Upload Python Package

on:
  release:
    types: [published]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: "3.8"

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements/dev.txt
        pip install "Pillow==9.1.1"
        pip install "mindspore>=1.8,<=1.10"
        pip install build twine
    - name: Build package
      run: |
        python -m build
    - name: Publish package
      env:
        TWINE_USERNAME: __token__
        TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
      run: |
        twine upload dist/*


docs

name: docs
on:
  push:
    branches:
      - main
  pull_request:

permissions:
  contents: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python 3.8
        uses: actions/setup-python@v4
        with:
          python-version: 3.8
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements/docs.txt
          pip install "Pillow==9.1.1"
          pip install "mindspore>=1.8,<=1.10"
      - name: Build site
        run: mkdocs build
      - name: Deploy to gh-pages
        if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'mindspore-lab/mindcv'
        run: mkdocs gh-deploy --force


Deploy

name: Deploy

on:
  push:
  merge_group:
  release:
    types:
      - published

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: [3.9, "3.10", "3.11"]
    uses: qiboteam/workflows/.github/workflows/deploy-pip-poetry.yml@main
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      publish: ${{ github.event_name == 'release' && github.event.action == 'published' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' }}
      poetry-extras: --with test,docs --all-extras
    secrets: inherit


docs

name: docs

on:
  workflow_dispatch:
  push:
    branches: [main]
    tags:
      - "*"

jobs:
  evaluate-label:
    runs-on: ubuntu-latest
    outputs:
      label: ${{ steps.label_step.outputs.version}}
    steps:
      - name: checks for the label
        id: label_step
        run: |
          if [[ "${{ github.ref  }}" == "refs/heads/main" ]]; then # TODO: modify the branch after merging
                echo "version=latest" >> $GITHUB_OUTPUT
          fi
          if [[ "${{ github.ref_type }}" == "branch" ]] && [[ "${{ github.ref  }}" != "refs/heads/main" ]]; then # TODO: modify the branch after merging
                exit 1
          fi
          if [[ "${{ github.ref_type }}" == "tag" ]]; then
                echo "version=stable" >> $GITHUB_OUTPUT
          fi

  deploy-docs:
    needs: [evaluate-label]
    uses: qiboteam/workflows/.github/workflows/deploy-ghpages-latest-stable.yml@main
    with:
      python-version: "3.10"
      package-manager: "poetry"
      dependency-path: "**/poetry.lock"
      trigger-label: "${{needs.evaluate-label.outputs.label}}"
      poetry-extras: --with docs
      project: qibocal


Tests

name: Tests

on:
  workflow_dispatch:
  push:
  merge_group:

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: [3.9, "3.10", "3.11"]
    uses: qiboteam/workflows/.github/workflows/rules-poetry.yml@main
    with:
      os: ${{ matrix.os }}
      python-version: ${{ matrix.python-version }}
      doctests: ${{ matrix.os == 'ubuntu-latest'}}
      poetry-extras: --with test,docs --all-extras
    secrets: inherit


Backport

name: Backport
on:
  pull_request:
    types:
      - closed
      - labeled
    paths-ignore:
      - '_quarto.yml'
      - 'quarto-materials/*'
      - '**/.md'

jobs:
  backport:
    runs-on: ubuntu-latest
    name: Backport
    steps:
      - name: Backport
        uses: tibdex/backport@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}


libTileDB-SOMA CodeCov

name: libTileDB-SOMA CodeCov

on:
  pull_request:
    paths-ignore:
      - "apis/python/**"
      - "apis/r/**"
      - ".pre-commit-config.yaml"
  push:
    branches:
      - main
      - 'release-*'
  workflow_dispatch:

jobs:
  codecov:
    runs-on: macos-latest
    steps:
    - name: Checkout TileDB-SOMA
      uses: actions/checkout@v3
    - name: Build libTileDB-SOMA
      run: TILEDBSOMA_COVERAGE="--coverage" ./scripts/bld --no-tiledb-deprecated=true
    - name: Run libTileDB-SOMA unittests
      run: ctest --test-dir build/libtiledbsoma -C Release --verbose --rerun-failed --output-on-failur
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        gcov: true
        flags: libtiledbsoma
        gcov_include: $(find libtiledbsoma -name "*.h" -or -name "*.cc")


pkgdown

# Workflow derived from https://github.com/r-lib/actions/tree/master/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help

on:
  #push:
  #  # To publish docs from your branch: list the branch name here instead of main.
  #  branches: [main]
  #pull_request:
  #  # To publish docs from your branch: list the branch name here instead of main.
  #  branches: [main]
  release:
    types: [published]
  schedule:
    - cron: "42 9 * * *"
  workflow_dispatch:

name: pkgdown

jobs:
  pkgdown:
    runs-on: ubuntu-latest
    # This is GitHub Actions magic -- there are no secrets we as package owners need to set up or manage
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3

      - uses: r-lib/actions/setup-pandoc@v1
        with:
          working-directory: "apis/r"

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true
          working-directory: "apis/r"

      - name: Set additional repositories (macOS)
        if: ${{ matrix.os != 'ubuntu-latest' }}
        run: echo 'options(repos = c("https://tiledb-inc.r-universe.dev", getOption("repos")), timeout = 300L)' | tee -a ~/.Rprofile

      - name: Set additional repositories (Linux)
        if: ${{ matrix.os == 'ubuntu-latest' }}
        run: |
          rversion <- paste(strsplit(as.character(getRversion()), split = '\\.')[[1L]][1:2], collapse = '.')
          codename <-  system('. /etc/os-release; echo ${VERSION_CODENAME}', intern = TRUE)
          repo <- "https://tiledb-inc.r-universe.dev"
          (opt <- sprintf('options(repos = c("%s/bin/linux/%s/%s", "%s", getOption("repos")), timeout = 300L)', repo, codename, rversion, repo))
          cat(opt, "\n", file = "~/.Rprofile", append = TRUE)
        shell: Rscript {0}

      - name: Install tiledb-r
        run: cd apis/r && Rscript tools/install-tiledb-r.R

      # Run this daily to surface errors as tracked at
      # https://github.com/single-cell-data/TileDB-SOMA/issues/2052
      - name: Install dependencies
        run: ./apis/r/tools/install-pkgdown-dependencies.sh

      # Run this on releases, or on workflow dispatch
      - name: Deploy package
        if: github.event_name != 'schedule'
        run: ./apis/r/tools/deploy-pkgdown.sh


TileDB-SOMA Python CI (Full)

name: TileDB-SOMA Python CI (Full)

# This workflow calls ./python-ci-single.yml on the full {os} x {python version}
# matrix. Since that's CI-resource-intensive, it runs only for main branch and
# releases.
on:
  push:
    branches:
      - main
      - 'release-*'
  release:
    types: [published]
  # You can also invoke this workflow manually from
  #   https://github.com/single-cell-data/TileDB-SOMA/actions/workflows/python-ci-full.yml
  # to test a working branch on the full matrix.
  workflow_dispatch:

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        # TODO: decide on Windows CI coverage
        os: [ubuntu-22.04, macos-12]
        # os: [ubuntu-22.04, macos-12, windows-2019]
        # TODO: add 3.12
        # https://github.com/single-cell-data/TileDB-SOMA/issues/1849
        python-version: ['3.8', '3.9', '3.10', '3.11']
        include:
          - runs-on: ubuntu-22.04
            cc: gcc-11
            cxx: g++-11
          - runs-on: macos-12
            cc: clang
            cxx: clang++
    uses: ./.github/workflows/python-ci-single.yml
    with:
      os: ${{ matrix.os }}
      python_version: ${{ matrix.python-version }}
      cc: ${{ matrix.cc }}
      cxx: ${{ matrix.cxx }}
      report_codecov: ${{ matrix.os == 'ubuntu-22.04' && matrix.python-version == '3.11' }}
      run_lint: ${{ matrix.os == 'ubuntu-22.04' && matrix.python-version == '3.11' }}
    secrets: inherit


TileDB-SOMA Python CI (Minimal)

name: TileDB-SOMA Python CI (Minimal)

# This workflow calls ./python-ci-single.yml on a limited subset of the
# {os} x {python version} matrix. It runs for all branches, in contrast to
# ./python-ci-full.yml, which exhausts the matrix but only for main & releases,
# since that's CI-resource-intensive.
#
# To test the full matrix on a working branch, invoke ./python-ci-full.yml from
#   https://github.com/single-cell-data/TileDB-SOMA/actions/workflows/python-ci-full.yml
on:
  pull_request:
    branches:
      - main
      - 'release-*'
    paths:
      - '**'
      - '!**.md'
      - '!apis/r/**'
      - '!docs/**'
      - '!.github/**'
      - '.github/workflows/python-ci-minimal.yml'
      - '.github/workflows/python-ci-single.yml'
  workflow_dispatch:

jobs:
  build:
    strategy:
      fail-fast: true

      matrix:
        os: [ubuntu-22.04, macos-12]
        python-version: ['3.8', '3.11']
        include:
          - os: ubuntu-22.04
            cc: gcc-11
            cxx: g++-11
          - os: macos-12
            cc: clang
            cxx: clang++
    uses: ./.github/workflows/python-ci-single.yml
    with:
      os: ${{ matrix.os }}
      python_version: ${{ matrix.python-version }}
      cc: ${{ matrix.cc }}
      cxx: ${{ matrix.cxx }}
      report_codecov: ${{ matrix.python-version == '3.11' }}
      run_lint: ${{ matrix.python-version == '3.11' }}
    secrets: inherit


TileDB-SOMA Python CI (Packaging)

# This CI confirms the Python package continues to install properly in the many
# different required contexts

name: TileDB-SOMA Python CI (Packaging)

on:
  push:
    paths:
      - '.github/workflows/python-ci-packaging.yml'
      - 'apis/python/MANIFEST.in'
      - 'apis/python/pyproject.toml'
      - 'apis/python/setup.py'
      - 'apis/python/version.py'
      - 'apis/python/src/tiledbsoma/__init__.py'
      - 'libtiledbsoma/cmake/inputs/Config.cmake.in'
      - 'libtiledbsoma/cmake/inputs/tiledbsoma.pc.in'
      - 'libtiledbsoma/cmake/Modules/FindTileDB_EP.cmake'
      - 'libtiledbsoma/cmake/Modules/TileDBCommon.cmake'
      - 'libtiledbsoma/cmake/Superbuild.cmake'
      - 'libtiledbsoma/CMakeLists.txt'
  pull_request:
    paths:
      - '.github/workflows/python-ci-packaging.yml'
      - 'apis/python/MANIFEST.in'
      - 'apis/python/pyproject.toml'
      - 'apis/python/setup.py'
      - 'apis/python/version.py'
      - 'apis/python/src/tiledbsoma/__init__.py'
      - 'libtiledbsoma/cmake/inputs/Config.cmake.in'
      - 'libtiledbsoma/cmake/inputs/tiledbsoma.pc.in'
      - 'libtiledbsoma/cmake/Modules/FindTileDB_EP.cmake'
      - 'libtiledbsoma/cmake/Modules/TileDBCommon.cmake'
      - 'libtiledbsoma/cmake/Superbuild.cmake'
      - 'libtiledbsoma/CMakeLists.txt'
  workflow_dispatch:

jobs:

  # Confirm shared object copying when building the Python package
  # https://github.com/single-cell-data/TileDB-SOMA/pull/1937
  docker:
    runs-on: ubuntu-latest
    name: "SO copying (docker) TILEDB_EXISTS: ${{ matrix.TILEDB_EXISTS }} TILEDBSOMA_EXISTS: ${{ matrix.TILEDBSOMA_EXISTS }}"
    strategy:
      fail-fast: false
      matrix:
        TILEDB_EXISTS: ["no", "yes"]
        TILEDBSOMA_EXISTS: ["no", "yes"]
        exclude:
          - TILEDB_EXISTS: "no"
            TILEDBSOMA_EXISTS: "yes"
    container:
      image: ubuntu:22.04
    defaults:
      run:
        shell: bash
    steps:
      - name: Docker image info
        run: |
          uname -a
          cat /etc/lsb-release
      - name: Setup
        run: |
          apt-get update
          apt-get install --yes cmake git python-is-python3 python3 python3-pip python3-venv unzip wget
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # for setuptools-scm
      - name: Configure Git
        run: |
          # This is a permissions quirk due to running Git as root inside of a Docker container
          git config --global --add safe.directory $(pwd)
          git branch
      - name: Install pre-built libtiledb
        if: ${{ matrix.TILEDB_EXISTS == 'yes' }}
        run: |
          mkdir -p external
          # Please do not edit manually -- let scripts/update-tiledb-version.py update this
          wget --quiet https://github.com/TileDB-Inc/TileDB/releases/download/2.24.0/tiledb-linux-x86_64-2.24.0-ff3879b.tar.gz
          tar -C external -xzf tiledb-linux-x86_64-*.tar.gz
          ls external/lib/
          echo "LD_LIBRARY_PATH=$(pwd)/external/lib" >> $GITHUB_ENV
          echo "PKG_CONFIG_PATH=$(pwd)/external/lib/pkgconfig" >> $GITHUB_ENV
          echo "TILEDB_PATH=$(pwd)/external" >> $GITHUB_ENV
      - name: Build and install libtiledbsoma
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'yes' }}
        run: |
          cmake -S libtiledbsoma -B build-libtiledbsoma \
            -D CMAKE_BUILD_TYPE=Release \
            -D CMAKE_PREFIX_PATH=$(pwd)/external/ \
            -D CMAKE_INSTALL_PREFIX:PATH=$(pwd)/external/ \
            -D OVERRIDE_INSTALL_PREFIX=OFF \
            -D DOWNLOAD_TILEDB_PREBUILT=OFF \
            -D TILEDB_REMOVE_DEPRECATIONS=ON \
            -D FORCE_BUILD_TILEDB=OFF
          cmake --build build-libtiledbsoma -j $(nproc)
          cmake --build build-libtiledbsoma --target install-libtiledbsoma
          ls external/lib/
          echo "TILEDBSOMA_PATH=$(pwd)/external" >> $GITHUB_ENV
      - name: Setup Python
        run: |
          python --version
          python -m venv ./venv-soma
          ./venv-soma/bin/python -m pip install --prefer-binary pybind11-global typeguard sparse wheel
          ./venv-soma/bin/python -m pip list
      - name: Build wheel
        run: |
          echo env vars: $LD_LIBRARY_PATH $PKG_CONFIG_PATH $TILEDB_PATH $TILEDBSOMA_PATH
          cd apis/python
          ../../venv-soma/bin/python setup.py bdist_wheel
      - name: Inspect wheel
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep '\.so'
      - name: Confirm libtiledb.so is copied
        if: ${{ matrix.TILEDB_EXISTS == 'no' }}
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledb.so
      - name: Confirm libtiledb.so is **not** copied when using external shared object
        if: ${{ matrix.TILEDB_EXISTS == 'yes' }}
        run: |
          if unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledb.so
          then
            echo "libtiledb.so was copied into the wheel when it was built against an external shared object"
            exit 1
          fi
      - name: Confirm libtiledbsoma.so is copied
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'no' }}
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledbsoma.so
      - name: Confirm libtiledbsoma.so is **not** copied when using external shared object
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'yes' }}
        run: |
          if unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledbsoma.so
          then
            echo "libtiledbsoma.so was copied into the wheel when it was built against an external shared object"
            exit 1
          fi
      - name: Install wheel
        run: ./venv-soma/bin/python -m pip install --prefer-binary apis/python/dist/tiledbsoma-*.whl
      - name: Check linking and RPATH
        run: |
          ldd ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so
          readelf -d ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so  | grep R*PATH
      - name: Runtime test
        run: ./venv-soma/bin/python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"
      - name: Confirm linking to installed shared objects
        run: |
          rm -fr build/ build-libtiledbsoma/ dist/ apis/python/build apis/python/src/tiledbsoma/*tile*.so*
          # should only show shared objects installed in virtual env or in ./external/
          find . -name '*tile*.so*'
          ./venv-soma/bin/python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"

  # Confirm shared object copying when building the Python package
  # https://github.com/single-cell-data/TileDB-SOMA/pull/1937
  # Same as job above, but running on macOS instead of in a Docker container
  macos:
    runs-on: macos-13
    name: "SO copying (macos) TILEDB_EXISTS: ${{ matrix.TILEDB_EXISTS }} TILEDBSOMA_EXISTS: ${{ matrix.TILEDBSOMA_EXISTS }}"
    strategy:
      fail-fast: false
      matrix:
        TILEDB_EXISTS: ["no", "yes"]
        TILEDBSOMA_EXISTS: ["no", "yes"]
        exclude:
          - TILEDB_EXISTS: "no"
            TILEDBSOMA_EXISTS: "yes"
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # for setuptools-scm
      - name: Check if System Integrity Protection (SIP) is enabled
        run: csrutil status
      - name: Install pre-built libtiledb
        if: ${{ matrix.TILEDB_EXISTS == 'yes' }}
        run: |
          mkdir -p external
          # Please do not edit manually -- let scripts/update-tiledb-version.py update this
          wget --quiet https://github.com/TileDB-Inc/TileDB/releases/download/2.24.0/tiledb-macos-x86_64-2.24.0-ff3879b.tar.gz
          tar -C external -xzf tiledb-macos-x86_64-*.tar.gz
          ls external/lib/
          echo "DYLD_LIBRARY_PATH=$(pwd)/external/lib" >> $GITHUB_ENV
          echo "PKG_CONFIG_PATH=$(pwd)/external/lib/pkgconfig" >> $GITHUB_ENV
          echo "TILEDB_PATH=$(pwd)/external" >> $GITHUB_ENV
      - name: Build and install libtiledbsoma
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'yes' }}
        run: |
          cmake -S libtiledbsoma -B build-libtiledbsoma \
            -D CMAKE_BUILD_TYPE=Release \
            -D CMAKE_PREFIX_PATH=$(pwd)/external/ \
            -D CMAKE_INSTALL_PREFIX:PATH=$(pwd)/external/ \
            -D OVERRIDE_INSTALL_PREFIX=OFF \
            -D DOWNLOAD_TILEDB_PREBUILT=OFF \
            -D TILEDB_REMOVE_DEPRECATIONS=ON \
            -D FORCE_BUILD_TILEDB=OFF
          cmake --build build-libtiledbsoma -j $(nproc)
          cmake --build build-libtiledbsoma --target install-libtiledbsoma
          ls external/lib/
          echo "TILEDBSOMA_PATH=$(pwd)/external" >> $GITHUB_ENV
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Setup Python virtual env
        run: |
          python --version
          python -m venv ./venv-soma
          ./venv-soma/bin/python -m pip install --prefer-binary pybind11-global typeguard sparse wheel setuptools
          ./venv-soma/bin/python -m pip list
      - name: Build wheel
        run: |
          echo env vars: $DYLD_LIBRARY_PATH $PKG_CONFIG_PATH $TILEDB_PATH $TILEDBSOMA_PATH
          cd apis/python
          ../../venv-soma/bin/python setup.py bdist_wheel
      - name: Inspect wheel
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep -e '\.dylib' -e '\.so'
      - name: Confirm libtiledb.dylib is copied
        if: ${{ matrix.TILEDB_EXISTS == 'no' }}
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledb.dylib
      - name: Confirm libtiledb.dylib is **not** copied when using external shared object
        if: ${{ matrix.TILEDB_EXISTS == 'yes' }}
        run: |
          if unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledb.dylib
          then
            echo "libtiledb.dylib was copied into the wheel when it was built against an external shared object"
            exit 1
          fi
      - name: Confirm libtiledbsoma.dylib is copied
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'no' }}
        run: unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledbsoma.dylib
      - name: Confirm libtiledbsoma.dylib is **not** copied when using external shared object
        if: ${{ matrix.TILEDBSOMA_EXISTS == 'yes' }}
        run: |
          if unzip -l apis/python/dist/tiledbsoma-*.whl | grep -q libtiledbsoma.dylib
          then
            echo "libtiledbsoma.dylib was copied into the wheel when it was built against an external shared object"
            exit 1
          fi
      - name: Install wheel
        run: ./venv-soma/bin/python -m pip install --prefer-binary apis/python/dist/tiledbsoma-*.whl
      - name: Check linking and RPATH
        run: otool -L ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so
      - name: Runtime test
        run: ./venv-soma/bin/python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"
      - name: Confirm linking to installed shared objects
        run: |
          rm -fr build/ build-libtiledbsoma/ dist/ apis/python/build apis/python/src/tiledbsoma/*tile*.dylib*
          # should only show shared objects installed in virtual env or in ./external/
          find . -name '*tile*.so*'
          find . -name '*tile*.dylib*'
          ./venv-soma/bin/python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"

  # Tests that the --libtiledbsoma flag to setup.py continues working
  setuptools:
    runs-on: ${{ matrix.os }}
    name: "setuptools (${{ matrix.os }})"
    strategy:
      fail-fast: false
      matrix:
        os: ["ubuntu-22.04", "macos-12"]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # for setuptools-scm
      - name: Install pre-built libtiledb
        run: |
          mkdir -p external
          if [ `uname -s` == "Darwin" ];
          then
            # Please do not edit manually -- let scripts/update-tiledb-version.py update this
            wget --quiet https://github.com/TileDB-Inc/TileDB/releases/download/2.24.0/tiledb-macos-x86_64-2.24.0-ff3879b.tar.gz
          else
            # Please do not edit manually -- let scripts/update-tiledb-version.py update this
            wget --quiet https://github.com/TileDB-Inc/TileDB/releases/download/2.24.0/tiledb-linux-x86_64-2.24.0-ff3879b.tar.gz
          fi
          tar -C external -xzf tiledb-*.tar.gz
          ls external/lib/
      - name: Build and install libtiledbsoma
        run: |
          cmake -S libtiledbsoma -B build-libtiledbsoma \
            -D CMAKE_BUILD_TYPE=Release \
            -D CMAKE_PREFIX_PATH=$(pwd)/external/ \
            -D CMAKE_INSTALL_PREFIX:PATH=$(pwd)/external/ \
            -D OVERRIDE_INSTALL_PREFIX=OFF \
            -D DOWNLOAD_TILEDB_PREBUILT=OFF \
            -D TILEDB_REMOVE_DEPRECATIONS=ON \
            -D FORCE_BUILD_TILEDB=OFF
          cmake --build build-libtiledbsoma -j 2
          cmake --build build-libtiledbsoma --target install-libtiledbsoma
          ls external/lib/
      # Delete all cmake executables from the runner. This will ensure that
      # tiledbsoma-py has to use the cli flags to find the external
      # libtiledbsoma.so and not build it from source by shelling out to cmake
      - name: Delete cmake
        run: |
          echo before
          which -a cmake
          which -a cmake | xargs sudo rm -f
          echo after
          which -a cmake || echo cmake removed
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Setup Python virtual env
        run: |
          python --version
          python -m venv ./venv-soma
          ./venv-soma/bin/python -m pip install --prefer-binary pybind11-global typeguard sparse wheel setuptools
          ./venv-soma/bin/python -m pip list
      - name: Install TileDB-SOMA-Py with setuptools and --libtiledbsoma
        run: |
          cd apis/python
          ../../venv-soma/bin/python setup.py install \
            --single-version-externally-managed \
            --record record.txt \
            --tiledb=$GITHUB_WORKSPACE/external/ \
            --libtiledbsoma=$GITHUB_WORKSPACE/external/
      - name: Check linking and RPATH (Linux)
        if: runner.os == 'Linux'
        run: |
          ldd ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so
          readelf -d ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so  | grep R*PATH
      - name: Check linking and RPATH (macOS)
        if: runner.os == 'macOS'
        run: |
          otool -L ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so
          otool -l ./venv-soma/lib/python*/site-packages/tiledbsoma/pytiledbsoma.*.so
      - name: Install runtime dependencies
        run: ./venv-soma/bin/python -m pip install --prefer-binary `grep -v '^\[' apis/python/src/tiledbsoma.egg-info/requires.txt`
      - name: Runtime test
        run: ./venv-soma/bin/python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"

  # Build a wheel from a source tarball (confirms all required files are
  # distributed in the sdist). This is in preparation for the official building of
  # the PyPI wheels in python-packaging.yml.
  # https://github.com/single-cell-data/TileDB-SOMA/pull/2506
  #
  #
  #  Differences to python-packaging.yml:
  #
  #  * Uses transparent python commands instead of the opaque action
  #    `pypa/cibuildwheel`, and therefore easier to debug
  #  * Only builds two wheels total (python 3.11 on Ubuntu and macOS), so it is
  #    much faster. It's not creating the wheels for distribution, but instead just
  #    providing a quick check that all the required files are distributed in the
  #    source tarball
  #  * Runs whenever an installation-related file is modified instead of only
  #    after a release
  #
  # In summary, the goal is to identify any potential problems with building
  # the PyPI wheels when a PR is submitted, and not at release time.
  sdist:
    runs-on: ${{ matrix.os }}
    name: "Wheel from sdist (${{ matrix.os }})"
    strategy:
      fail-fast: false
      matrix:
        os: ["ubuntu-22.04", "macos-12"]
    steps:
      - uses: actions/checkout@v4
        with:
          path: TileDB-SOMA
          fetch-depth: 0 # for setuptools-scm
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: python -m pip install --prefer-binary pybind11 wheel
      - name: Build source tarball (sdist)
        run: |
          cd TileDB-SOMA/apis/python
          python setup.py sdist
      - name: Extract source tarball
        run: |
          tar --list -f TileDB-SOMA/apis/python/dist/tiledbsoma-*.tar.gz
          tar -xzf TileDB-SOMA/apis/python/dist/tiledbsoma-*.tar.gz
      - name: Build wheel
        run: |
          cd tiledbsoma-*/
          python setup.py bdist_wheel
      - name: Install wheel
        run: |
          python -m pip install --prefer-binary tiledbsoma-*/dist/tiledbsoma-*.whl
          python -c "import tiledbsoma; print(tiledbsoma.pytiledbsoma.version())"


TileDB-SOMA Python CI

# This is a reusable workflow
# (https://docs.github.com/en/actions/using-workflows/reusing-workflows#calling-a-reusable-workflow),
# called by python-ci-full.yml and python-ci-minimal.yml.

name: TileDB-SOMA Python CI

on:
  workflow_call:
    inputs:
      python_version:
        required: true
        type: string
      os:
        required: true
        type: string
      cc:
        required: false
        type: string
      cxx:
        required: false
        type: string
      report_codecov:
        required: true
        type: boolean
      run_lint:
        required: false
        type: boolean
        default: false

jobs:
  lint:
    if: inputs.run_lint
    runs-on: ${{ inputs.os }}
    steps:
    - name: Checkout TileDB-SOMA
      uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: ${{ inputs.python_version }}
        cache: pip
        cache-dependency-path: ./.github/workflows/python-ci-single.yml

    - name: Restore pre-commit cache
      uses: actions/cache@v3
      with:
        path: ~/.cache/pre-commit
        key: pre-commit-${{ inputs.os }}-${{ inputs.python_version }}-${{ hashFiles('.github/workflows/python-ci-single.yml') }}

    - name: Run pre-commit hooks on all files
      run: python -m pip -v install pre-commit && pre-commit run -a -v

    # Skip files in apis/r/src which are:
    # * nanoarrow.c/h
    # * Auto-generated by Rcpp
    # * Things which Dirk doesn't want to be format-checked
    - name: Check C++ Format
      shell: bash
      run: ./scripts/run-clang-format.sh . clang-format 0 $(find libtiledbsoma apis/python/src -name "*.cc" -or -name "*.cpp" -or -name "*.h" | grep -v external)

  build:
    runs-on: ${{ inputs.os }}
    steps:
    - name: Show matrix OS
      run: echo "inputs.os:" ${{ inputs.os }}

    - name: Linux CPU info
      if: ${{ inputs.os == 'ubuntu-22.04' }}
      run: cat /proc/cpuinfo

    - name: MacOS CPU info
      if: ${{ inputs.os == 'macos-12' }}
      run: sysctl -a | grep cpu
    - name: Select XCode version
      if: startsWith(inputs.os, 'macos')
      uses: maxim-lobanov/setup-xcode@v1
      with:
        # Pending https://github.com/actions/runner-images/issues/6350
        xcode-version: '13.4'

    - name: Checkout TileDB-SOMA
      uses: actions/checkout@v3
      with:
        fetch-depth: 0  # ensure we get all tags to inform package version determination

    - name: Set up Python ${{ inputs.python_version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ inputs.python_version }}
        cache: pip
        cache-dependency-path: ./apis/python/setup.py

# Experiment for MacOS CI false negatives ...
#    - name: Cache native libraries
#      uses: actions/cache@v3
#      with:
#        path: |
#          build
#          dist
#        key: libtiledbsoma-build-dist-${{ inputs.os }}-${{ inputs.python_version }}-${{ hashFiles('libtiledbsoma', 'scripts/bld') }}

    - name: Install tiledbsoma
      run: python -m pip -v install -e apis/python[dev] -C "--build-option=--no-tiledb-deprecated"
      env:
        CC: ${{ inputs.cc }}
        CXX: ${{ inputs.cxx }}

    - name: Show package versions
      run: python scripts/show-versions.py

    - name: Show XCode version
      run: clang --version

    - name: Obtain test data
      shell: bash
      run: |
        cd test
        rm -rf soco
        tar zxf soco.tgz
        cd ..

    - name: Run libtiledbsoma unit tests
      run: ctest --output-on-failure --test-dir build/libtiledbsoma -C Release --verbose
      env:
        TILEDB_SOMA_INIT_BUFFER_BYTES: 33554432 # accommodate tiny runners

    - name: Run pytests for Python
      shell: bash
      # Setting PYTHONPATH ensures the tests load the in-tree source code under apis/python/src
      # instead of the copy we `pip install`ed to site-packages above. That's needed for the code
      # coverage analysis to work.
      run: PYTHONPATH=$(pwd)/apis/python/src python -m pytest --cov=apis/python/src --cov-report=xml apis/python/tests -v --durations=20

    - name: Report coverage to Codecov
      if: inputs.report_codecov
      uses: codecov/codecov-action@v3
      with:
        flags: python
        # Although Codecov isn't supposed to require an auth token for public repos like this one,
        # the uploader can be unreliable without one; see
        #     https://github.com/codecov/codecov-action/issues/557#issuecomment-1216749652
        # As of this writing (8 Nov 2022) the CODECOV_TOKEN was generated by @aaronwolen in his
        # Codecov settings page for this repo, then filled into the GitHub Actions secrets.
        token: ${{ secrets.CODECOV_TOKEN }}


TileDB-SOMA python sdist & wheels

# Workflow to build distribution, and push to PyPI or TestPyPI

name: TileDB-SOMA python sdist & wheels

on:
  # Trigger publication to TestPyPI via user workflow request:
  #     gh workflow run python-packaging.yml --ref branch
  # Specify the branch or other ref as required, allowing testing
  # of PRs/branches.
  workflow_dispatch:
  # Trigger publication to PyPi via new release event.
  release:
    types: [published]
  # Schedule wheel-build and smoke-test on a regular schedule.
  #
  # This will not publish to either PyPI or TestPyPI (see the conditionals
  # guarding those steps below).
  schedule:
    - cron: "42 9 * * *"

jobs:
  sdist:
    name: Build source distribution
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout TileDB-SOMA
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # ensure we get all tags to inform package version determination
      - name: Build sdist
        run: python setup.py sdist
        working-directory: ./apis/python
      - name: Upload sdist artifact to GitHub Actions storage
        uses: actions/upload-artifact@v4
        with:
          name: sdist
          path: apis/python/dist/

  # This step builds wheels and uploads them to GitHub Actions storage.
  # See also https://github.com/single-cell-data/TileDB-SOMA/issues/700.
  # See also https://github.com/single-cell-data/TileDB-SOMA/wiki/PyPI-packaging-WIP
  # for important transitional context.
  wheels:
    # Note: tries all supported Python versions as specified in apis/python/setup.py
    name: Build ${{ matrix.python-version }}-${{ matrix.wheel-name }} wheel
    needs: sdist
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        python-version: [ '38', '39', '310', '311' ]
        cibw_build: [ manylinux_x86_64, macosx_x86_64, macosx_arm64 ]
        include:
          - cibw_build: manylinux_x86_64
            os: ubuntu-20.04
            wheel-name: manylinux2014
          - cibw_build: macosx_x86_64
            os: macos-12
            cibw_archs_macos: x86_64
            wheel-name: macos-x86_64
          - cibw_build: macosx_arm64
            os: macos-14  # Note: macos-14 is arm64 only
            cibw_archs_macos: arm64
            wheel-name: macos-arm64
    steps:
      - name: Download sdist artifact
        uses: actions/download-artifact@v4
        with:
          name: sdist
      - name: Rename sdist
        run: cp tiledbsoma-*.tar.gz tiledbsoma.tar.gz && ls -lh
      # This is crucial for ongoing debug (do not remove it) as this shows the
      # OS version as used by `pip install` to find wheel names. Importantly,
      # macos 12 and macos14 self-report as `macosx-10.9-universal2` via
      # `distutil.util.get_platform()`.
      - name: Show self-reported platform
        run: |
          echo "python --version"; python --version
          echo matrix.platform: ${{ matrix.platform }}
          echo matrix.arch: ${{ matrix.arch }}
          # This bit is crucial since it's used to match up to a component of the wheel-file name
          python -m pip install setuptools
          python -c 'from distutils import util; print("distutil.util.get_platform:", util.get_platform())'
          python -c 'import platform; print("platform.platform()", platform.platform())'
      - name: Build wheels
        uses: pypa/cibuildwheel@v2.18.1
        with:
          package-dir: tiledbsoma.tar.gz
          only: cp${{ matrix.python-version }}-${{ matrix.cibw_build }}
        env:
          CIBW_BUILD: ${{ matrix.cibw_build }}
          CIBW_BUILD_VERBOSITY: 1
          CIBW_BEFORE_BUILD: bash -x -c 'rm -rf tiledbsoma*/dist_links/dist/lib*'
          # ^ Delete lib folder that apis/python/setup.py:find_or_build() looks for in deciding to
          #   run CMake build or not. Otherwise it'll keep reusing the library file built in the
          #   first iteration of cibuildwheel's outer loop, resulting in wheels with the library
          #   built for the wrong python version.
          CIBW_ARCHS_MACOS: ${{ matrix.cibw_archs_macos }}
          CIBW_TEST_SKIP: "*_arm64"
          CMAKE_OSX_ARCHITECTURES: ${{ matrix.cibw_archs_macos }}
          MACOSX_DEPLOYMENT_TARGET: "11.0"
      - name: Upload wheel-${{ matrix.wheel-name }}-${{ matrix.python-version }} to GitHub Actions storage
        uses: actions/upload-artifact@v4
        with:
          name: wheel-${{ matrix.wheel-name }}-${{ matrix.python-version }}
          path: ./wheelhouse/*.whl

  # This step locally tries out the built wheels, without publishing to PyPI
  smoke-test:
    name: "Smoke test ${{ matrix.python.undotted-version }}-${{ matrix.wheel-name }} wheel"
    needs: wheels
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        python:
          - undotted-version: '310'
            dotted-version: '3.10'
          - undotted-version: '311'
            dotted-version: '3.11'
        wheel-name:
          - manylinux2014
          - macos-x86_64
          - macos-arm64
        include:
          - wheel-name: manylinux2014
            os: ubuntu-20.04
            arch: x86_64
            cc: gcc-11
            cxx: g++-11
          - wheel-name: macos-x86_64
            os: macos-12
            arch: x86_64
            cc: clang
            cxx: clang++
          - wheel-name: macos-arm64
            os: macos-14
            arch: arm64
            cc: clang
            cxx: clang++
      fail-fast: false
    steps:
      - name: Set up Python ${{ matrix.python.dotted-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python.dotted-version }}
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          name: wheel-${{ matrix.wheel-name }}-${{ matrix.python.undotted-version }}
      - name: Install wheel
        run: |
          set -x
          ls -lR
          WHL=$(find . -name 'tiledbsoma-*-cp${{ matrix.python.undotted-version }}-cp${{ matrix.python.undotted-version }}-*_${{ matrix.arch }}.whl')
          echo "WHL=$WHL"
          if [ -z "$WHL" ]; then echo "No wheel found"; exit 1; fi
          unzip -l $WHL
          pip install wheel
          pip install $WHL
          echo "WHL=$WHL" >> $GITHUB_ENV
      - name: Smoke test ${{ matrix.os }}
        run: python -c 'import tiledbsoma; print(tiledbsoma.pytiledbsoma.__file__); tiledbsoma.show_package_versions()'
        # TODO: more thorough local smoke test
      - name: Smoke test in docker
        if: ${{ matrix.os == 'ubuntu-20.04' }}
        run: |
          docker run -v $(pwd):/mnt python:${{ matrix.python.dotted-version }} bash -ec "
            apt-get -qq update && apt-get install -y python3-pip python3-wheel
            pip3 install /mnt/$WHL
            python3 -c 'import tiledbsoma; print(tiledbsoma.pytiledbsoma.__file__); tiledbsoma.show_package_versions()'
          "

  # Publish to TestPyPI upon user workflow request
  publish-to-test-pypi:
    name: Publish package to TestPyPI
    needs: smoke-test
    runs-on: ubuntu-20.04
    if: github.event_name == 'workflow_dispatch'
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v4
      - name: Create dist
        run: |
          set -x
          mkdir dist
          cp sdist/tiledbsoma-*.tar.gz wheel-*/*.whl dist
          ls -l dist
      - name: Publish packages to TestPyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        continue-on-error: true
        with:
          password: ${{ secrets.TEST_PYPI_TOKEN }}
          repository-url: https://test.pypi.org/legacy/
          packages_dir: dist
          verbose: true

  # Publish to PyPI upon release.
  publish-to-pypi:
    name: Publish package to PyPI
    needs: smoke-test
    runs-on: ubuntu-20.04
    if: github.event_name == 'release'
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v4
      - name: Create dist
        run: |
          set -x
          mkdir dist
          cp sdist/tiledbsoma-*.tar.gz wheel-*/*.whl dist
          ls -l dist
      - name: Publish packages to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_TOKEN }}
          packages_dir: dist
          verbose: true

  # File a bug report if anything fails, but don't file tickets for manual runs
  # -- only for scheduled ones.
  create_issue_on_fail:
    runs-on: ubuntu-latest
    needs: [smoke-test, publish-to-test-pypi, publish-to-pypi]
    if: (failure() || cancelled()) && github.event_name != 'workflow_dispatch'
    steps:
      - name: Checkout TileDB-SOMA `main`
        uses: actions/checkout@v2
      - name: Create Issue if Build Fails
        uses: JasonEtco/create-an-issue@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          filename: .github/workflows/daily-test-build-issue-template.md


TileDB-SOMA R CI

name: TileDB-SOMA R CI

on:
  pull_request:
    paths:
      - '**'
      - '!**.md'
      - '!apis/python/**'
      - '!docs/**'
      - '!.github/**'
      - '.github/workflows/r-ci.yml'
  push:
    branches:
      - main
      - 'release-*'
  workflow_dispatch:

env:
  COVERAGE_FLAGS: "r"
  COVERAGE_TOKEN: ${{ secrets.CODECOV_TOKEN }}
  _R_CHECK_TESTS_NLINES_: 0
  CATCHSEGV: "TRUE"
  R_REMOTES_UPGRADE: "never"
  TILEDB_SOMA_INIT_BUFFER_BYTES: 33554432 # accommodate tiny runners

jobs:
  ci:
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: linux
            os: ubuntu-latest
            covr: 'no'
          - name: macos
            os: macOS-latest
            covr: 'no'
          - name: coverage
            os: ubuntu-latest
            covr: 'yes'

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

    steps:
      - uses: actions/checkout@v3

      - name: Show matrix OS
        run: echo "matrix.os:" ${{ matrix.os }}

      - name: Linux CPU info
        if: ${{ matrix.os == 'ubuntu-latest' }}
        run: cat /proc/cpuinfo

      - name: MacOS CPU info
        if: ${{ matrix.os == 'macOS-latest' }}
        run: sysctl -a | grep cpu

      - name: Bootstrap
        run: cd apis/r && tools/r-ci.sh bootstrap

      - name: Set additional repositories (macOS)
        if: ${{ matrix.os != 'ubuntu-latest' }}
        run: echo 'options(repos = c("https://tiledb-inc.r-universe.dev", getOption("repos")), timeout = 300L)' | tee -a ~/.Rprofile

      - name: Set additional repositories (Linux)
        if: ${{ matrix.os == 'ubuntu-latest' }}
        run: |
          rversion <- paste(strsplit(as.character(getRversion()), split = '\\.')[[1L]][1:2], collapse = '.')
          codename <-  system('. /etc/os-release; echo ${VERSION_CODENAME}', intern = TRUE)
          repo <- "https://tiledb-inc.r-universe.dev"
          (opt <- sprintf('options(repos = c("%s/bin/linux/%s/%s", "%s", getOption("repos")), timeout = 300L)', repo, codename, rversion, repo))
          cat(opt, "\n", file = "~/.Rprofile", append = TRUE)
        shell: Rscript {0}

      - name: Install tiledb-r
        run: cd apis/r && Rscript tools/install-tiledb-r.R

      - name: Install BioConductor package SingleCellExperiment
        run: cd apis/r && tools/r-ci.sh install_bioc SingleCellExperiment

      # Uncomment these next two stanzas as needed whenever we've just released a new tiledb-r for
      # which source is available but CRAN releases (and hence update r2u binaries) are not yet:
      #
      # IMPORTANT: these two stanzas should remain uncommented _only_ during the propagation time
      # between (a) publication of source for a new TileDB-R _upon which_ TileDB-SOMA depends in its
      # apis/R/DESCRIPTION file and (b) appearance of binaries.
      #
      # Please see https://github.com/single-cell-data/TileDB-SOMA/wiki/Branches-and-releases which
      # is crucial for anyone doing releases of TileDB-SOMA.
      #
      # Please edit both files in the same way:
      # * r-ci.yml
      # * r-python-interop-testing.yml
      #
      # Do not remove these comments until such time as we have eliminated our dependency on
      # the TileDB-R package.

      #- name: Install r-universe build of tiledb-r (macOS)
      #  if: ${{ matrix.os == 'macOS-latest' }}
      #  run: cd apis/r && Rscript -e "install.packages('tiledb', repos = c('https://eddelbuettel.r-universe.dev', 'https://cloud.r-project.org'))"

      #- name: Install r-universe build of tiledb-r (linux)
      #  if: ${{ matrix.os != 'macOS-latest' }}
      #  run: cd apis/r && Rscript -e "options(bspm.version.check=TRUE); install.packages('tiledb', repos = c('https://eddelbuettel.r-universe.dev/bin/linux/jammy/4.3/', 'https://cloud.r-project.org'))"

      - name: Dependencies
        run: cd apis/r && Rscript -e "remotes::install_deps(dependencies = TRUE, upgrade = FALSE)"

      # - name: Install dataset packages from source (macOS)
      #   if: ${{ matrix.os == 'macOS-latest' }}
      #   run: cd apis/r && _CI_PKG_TYPE_=both _CI_USE_BIOC_=true Rscript tools/install_missing_deps.R

      # - name: CMake
      #   uses: lukka/get-cmake@latest

      #- name: MkVars
      #  run: mkdir ~/.R && echo "CXX17FLAGS=-Wno-deprecated-declarations -Wno-deprecated" > ~/.R/Makevars

      #- name: Build and install libtiledbsoma
      #  run: sudo scripts/bld --prefix=/usr/local

      #- name: Call ldconfig
      #  if: ${{ matrix.os == 'ubuntu-latest' }}
      #  run: sudo ldconfig
      #
      # - name: Update Packages
      #   run: Rscript -e 'update.packages(ask=FALSE)'

      - name: Build Package
        run: cd apis/r && R CMD build --no-build-vignettes --no-manual .

      - name: Install Package
        run: cd apis/r && R CMD INSTALL $(ls -1tr *.tar.gz | tail -1)

      # - name: Diagnostics
      #   run: Rscript -e 'print(Sys.info())'

      # - name: Downgrade TileDB-R if needed
      #   run: cd apis/r && Rscript tools/controlled_downgrade.R

      #- name: Test
      #  if: ${{ matrix.covr == 'no' }}
      #  run: |
      #    cd apis/r
      #    Rscript -e "install.packages('devtools')" \
      #      -e "devtools::install(upgrade = FALSE)" \
      #      -e "testthat::test_local('tests/testthat', load_package = 'installed')"

      - name: Test
        if: ${{ matrix.covr == 'no' }}
        run: cd apis/r/tests && Rscript testthat.R

      - name: Coverage
        if: ${{ matrix.os == 'ubuntu-latest' && matrix.covr == 'yes' && github.event_name == 'workflow_dispatch' }}
        run: apis/r/tools/r-ci.sh coverage

      - name: View Logs
        run: apis/r/tools/r-ci.sh dump_logs
        if: failure()


TileDB-SOMA R-Python interop testing

name: TileDB-SOMA R-Python interop testing

on:
  pull_request:
    # TODO: leave this enabled for pre-merge signal for now. At some point we may want to go back to
    # only having this signal post-merge.
    #paths:
    #  - "apis/python/**"
    #  - "apis/r/**"
    #  - "apis/system/**"
  push:
    branches:
      - main
      - 'release-*'
  workflow_dispatch:

jobs:
  ci:
    strategy:
      matrix:
        include:
          - { os: ubuntu-latest }

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

    steps:
      - name: Checkout TileDB-SOMA
        uses: actions/checkout@v3
        with:
          fetch-depth: 0  # ensure we get all tags to inform package version determination

      - name: Bootstrap
        run: cd apis/r && tools/r-ci.sh bootstrap

      - name: Set additional repositories (Linux)
        if: ${{ matrix.os == 'ubuntu-latest' }}
        run: |
          rversion <- paste(strsplit(as.character(getRversion()), split = '\\.')[[1L]][1:2], collapse = '.')
          codename <-  system('. /etc/os-release; echo ${VERSION_CODENAME}', intern = TRUE)
          repo <- "https://tiledb-inc.r-universe.dev"
          (opt <- sprintf('options(repos = c("%s/bin/linux/%s/%s", "%s", getOption("repos")))', repo, codename, rversion, repo))
          cat(opt, "\n", file = "~/.Rprofile", append = TRUE)
        shell: Rscript {0}

      - name: Install tiledb-r
        run: cd apis/r && Rscript tools/install-tiledb-r.R

      - name: Dependencies
        run: cd apis/r && Rscript -e "remotes::install_deps(dependencies = TRUE, upgrade = FALSE)"

      - name: CMake
        uses: lukka/get-cmake@latest

      - name: MkVars
        run: mkdir ~/.R && echo "CXX17FLAGS=-Wno-deprecated-declarations -Wno-deprecated" > ~/.R/Makevars

      # Uncomment these next two stanzas as needed whenever we've just released a new tiledb-r for
      # which source is available but CRAN releases (and hence update r2u binaries) are not yet:
      #
      # IMPORTANT: these two stanzas should remain uncommented _only_ during the propagation time
      # between (a) publication of source for a new TileDB-R _upon which_ TileDB-SOMA depends in its
      # apis/R/DESCRIPTION file and (b) appearance of binaries.
      #
      # Please see https://github.com/single-cell-data/TileDB-SOMA/wiki/Branches-and-releases which
      # is crucial for anyone doing releases of TileDB-SOMA.
      #
      # Please edit both files in the same way:
      # * r-ci.yml
      # * r-python-interop-testing.yml
      #
      # Do not remove these comments until such time as we have eliminated our dependency on
      # the TileDB-R package.

      #- name: Install r-universe build of tiledb-r (macOS)
      #  if: ${{ matrix.os == 'macOS-latest' }}
      #  run: cd apis/r && Rscript -e "install.packages('tiledb', repos = c('https://eddelbuettel.r-universe.dev', 'https://cloud.r-project.org'))"

      #- name: Install r-universe build of tiledb-r (linux)
      #  if: ${{ matrix.os != 'macOS-latest' }}
      #  run: cd apis/r && Rscript -e "options(bspm.version.check=TRUE); install.packages('tiledb', repos = c('https://eddelbuettel.r-universe.dev/bin/linux/jammy/4.3/', 'https://cloud.r-project.org'))"

      - name: Build and install libtiledbsoma
        run: sudo scripts/bld --prefix=/usr/local --no-tiledb-deprecated=true && sudo ldconfig

      - name: Install R-tiledbsoma
        run: |
          cd apis/r
          R CMD build --no-build-vignettes --no-manual .
          FILE=$(ls -1t *.tar.gz | head -n 1)
          R CMD INSTALL $FILE

      - name: Show R package versions
        run: Rscript -e 'tiledbsoma::show_package_versions()'

      - name: Set up Python 3.11
        uses: actions/setup-python@v4
        with:
          python-version: "3.11"
          cache: pip
          cache-dependency-path: ./apis/python/setup.py

      - name: Install tiledbsoma
        run: python -m pip -v install -e apis/python[dev] -C "--build-option=--no-tiledb-deprecated"

      - name: Show Python package versions
        run: |
          python -c 'import tiledbsoma; tiledbsoma.show_package_versions()'
          python scripts/show-versions.py

      - name: Update Packages
        run: Rscript -e 'update.packages(ask=FALSE)'

      - name: Interop Tests
        run: python -m pytest apis/system/tests/
        env:
          TILEDB_SOMA_INIT_BUFFER_BYTES: 33554432 # accommodate tiny runners


r-valgrind

name: r-valgrind

on:
  # allows for 'as needed' manual trigger
  workflow_dispatch:
  # use a regular nighly build as well (time is UTC)
  schedule:
    - cron: "23 4 * * *"

jobs:
  r-valgrind:
    runs-on: ubuntu-latest
    container:
      image: rocker/r2u:latest
    steps:
      - uses: actions/checkout@v3

      - name: SessionInfo
        run: R -q -e 'sessionInfo()'

      - name: System Dependencies
        run: apt update -qq && apt upgrade --yes && apt install --yes --no-install-recommends valgrind cmake git

      - name: Set additional repositories (Linux)
        run: |
          rversion <- paste(strsplit(as.character(getRversion()), split = '\\.')[[1L]][1:2], collapse = '.')
          codename <-  system('. /etc/os-release; echo ${VERSION_CODENAME}', intern = TRUE)
          repo <- "https://tiledb-inc.r-universe.dev"
          (opt <- sprintf('options(repos = c("%s/bin/linux/%s/%s", "%s", getOption("repos")), timeout = 300L)', repo, codename, rversion, repo))
          cat(opt, "\n", file = "~/.Rprofile", append = TRUE)
        shell: Rscript {0}

      - name: Install tiledb-r
        run: cd apis/r && Rscript tools/install-tiledb-r.R

      - name: Package Dependencies
        run: cd apis/r && R -q -e 'remotes::install_deps(".", dependencies=TRUE, upgrade=FALSE)'

      - name: Build Package
        run: cd apis/r && R CMD build --no-build-vignettes --no-manual .

      - name: Check Package under valgrind
        # we unsetting environment variable CI for non-extended set of tests
        run: cd apis/r && CI="" VALGRIND_OPTS="-s --leak-check=full --max-threads=1024" R CMD check --use-valgrind --no-vignettes --no-manual $(ls -1tr *.tar.gz | tail -1)

      - name: Display Test Output
        run: cd apis/r/tiledbsoma.Rcheck/tests && cat testthat.Rout


C API

# Test Qibolab C API
name: C API

on:
  push:
  workflow_dispatch:

jobs:
  tests:
    strategy:
      matrix:
        os: [ubuntu-latest]
    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.10"
      - name: Prepare virtual environment
        run: |
          python -m venv env
      - name: Install dependencies
        run: |
          # build dependencies
          pip install cffi
          # runtime dependencies
          . env/bin/activate
          pip install cffi  # also a runtime dep
          pip install .
      - name: Build & install library
        working-directory: capi
        run: |
          cmake -S . -B build  -DCMAKE_INSTALL_PREFIX=$(realpath ../env)
          cmake --build build
          cmake --install build
      - name: Build & run example
        working-directory: capi/examples
        run: |
          . ../../env/bin/activate
          export PKG_CONFIG_PATH=${VIRTUAL_ENV}/lib/pkgconfig/:${PKG_CONFIG_PATH}:
          export LD_LIBRARY_PATH=${VIRTUAL_ENV}/lib/:${LD_LIBRARY_PATH}:
          make
          ./example