# future.tests: Continuous Integration on GitHub Actions

We can use continuous integration (CI) services such as GitHub Actions and Travis CI to automatically validate future backends via the future.tests test suite.

Here is an example of a `.github/workflows/future.tests.yaml` file that configures GitHub Actions to check several backends via the future.tests test suite.

    on: [push, pull_request]

    name: future_tests

    jobs:
      future_tests:
        if: "! contains(github.event.head_commit.message, '[ci skip]')"

        timeout-minutes: 30

        runs-on: ubuntu-latest

        name: future.plan=${{ matrix.future.plan }}

        strategy:
          fail-fast: false
          matrix:
            future:
              - { plan: 'cluster'                             }
              - { plan: 'multicore'                           }
              - { plan: 'multisession'                        }
              - { plan: 'sequential'                          }
              - { plan: 'future.batchtools::batchtools_local' }
              - { plan: 'future.batchtools::batchtools_bash'  }
              - { plan: 'future.callr::callr'                 }
              - { plan: 'future.mirai::mirai_multisession'    }
              - { plan: 'future.mirai::mirai_cluster'         }

        env:
          GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
          R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
          ## R CMD check
          _R_CHECK_MATRIX_DATA_: true
          _R_CHECK_CRAN_INCOMING_: false
          ## Specific to futures
          R_FUTURE_RNG_ONMISUSE: error

        steps:
          - uses: actions/checkout@v4

          - uses: r-lib/actions/setup-pandoc@v2

          - uses: r-lib/actions/setup-r@v2
            with:
              use-public-rspm: true

          - uses: r-lib/actions/setup-r-dependencies@v2
            with:
              extra-packages: |
                any::rcmdcheck
                any::remotes
                any::sessioninfo
                any::covr
              needs: check

          - name: Install dependencies
            run: |
              remotes::install_deps(dependencies = TRUE)
              install.packages(".", repos=NULL, type="source")
            shell: Rscript {0}

          - name: Session info
            run: |
              options(width = 100)
              pkgs <- installed.packages()[, "Package"]
              sessioninfo::session_info(pkgs, include_base = TRUE)
            shell: Rscript {0}

          - name: Install 'future.tests' and any backend R packages
            run: |
              remotes::install_cran("future.tests")
              ## Identify and install future backend package in 'plan' variable, if any
              plan <- "${{ matrix.future.plan }}"
              pattern <- ".*(future[.][[:alnum:]]+)::[[:alnum:]]+.*"
              if (grepl(pattern, plan) && nzchar(pkg <- sub(pattern, "\\1", plan))) install.packages(pkg)
            shell: Rscript {0}

          - name: Session info
            run: |
              options(width = 100)
              pkgs <- installed.packages()[, "Package"]
              sessioninfo::session_info(pkgs, include_base = TRUE)
            shell: Rscript {0}

          - name: Check future backend '${{ matrix.future.plan }}'
            run: |
              R CMD build --no-build-vignettes --no-manual .
              R CMD INSTALL *.tar.gz
              Rscript -e future.tests::check --args --test-plan=${{ matrix.future.plan }}

          - name: Upload check results
            if: failure()
            uses: actions/upload-artifact@v4
            with:
              name: ${{ runner.os }}-r${{ matrix.future.plan }}-results
              path: check

For real-world examples, see the GitHub repositories of future, future.batchtools, future.callr, and future.mirai.