Repository: alfaro96/scikit-lr (language: python)

Issue:
[MNT] Add windows-latest to continuous integration and deployment
#### What does this implement?

This PR adds `windows-latest` to the continuous integration and the continuous deployment for covering most of the platforms.

[MNT] Move wheel builder to cibuildwheel
#### What does this implement?

This PR moves the wheel builder to the `cibuildwheel` package.


Discussion / hints:

Fix patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index cf07346..8390e92 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -6,8 +6,8 @@ labels: bug
 ---
 
 <!--
-Before submitting a bug, make sure the issue has not been
-already addressed by searching through the past issues.
+Before submitting a bug, please make sure the issue has not
+been already addressed by searching through the past issues.
 -->
 
 #### Description
@@ -19,9 +19,9 @@ A clear and concise description of what the bug is.
 #### Code to reproduce the problem
 
 <!--
-Add a minimal example that we can reproduce the error by running the code.
-Be as succinct as possible, do not depend on external data. In short, we are
-going to copy-paste your code and we expect to get the same result as you.
+Please add a minimal example that we can reproduce the error by running the
+code. Be as succinct as possible, do not depend on external data. In short,
+we are going to copy-paste your code and we expect to get the same results.
 -->
 
 ```
@@ -31,13 +31,13 @@ Sample code to reproduce the problem
 #### Expected behaviour
 
 <!--
-Paste or describe the expected behaviour.
+Please paste or describe the expected behaviour.
 -->
 
 #### Actual behaviour
 
 <!--
-Paste or specifically describe the actual output or traceback.
+Please paste or describe the actual output or traceback.
 -->
 
 #### Specifications
@@ -53,3 +53,5 @@ import sklearn; print("scikit-learn", sklearn.__version__)
 import imblearn; print("imbalanced-learn", imblearn.__version__)
 import sklr; print("scikit-lr", sklr.__version__)
 -->
+
+<!-- Thanks for contributing! -->
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 39a1623..cd82262 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -6,7 +6,7 @@ labels: feature
 ---
 
 <!--
-If you want to propose a new algorithm, be sure that the standards are followed.
+If you want to propose a new algorithm, be sure that the inclusion criteria are met.
 -->
 
 #### Describe the workflow you want to enable
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index b2631c5..b40da53 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,11 +1,11 @@
-<!--- Standard template for submitting pull requests -->
+<!--- Thanks for contributing a pull request! -->
 
-#### Reference issues
+#### Reference issues and pull requests
 
 <!--
-Please, use keywords to create a link to the issues you resolved,
-so that they will automatically be closed when your pull request
-is merged. For more information about automatically closing issues,
+Please use keywords to create a link to the issues or pull requests
+you resolved, so that they will automatically be closed when your
+pull request is merged. For more information about closing issues,
 see: https://github.com/blog/1506-closing-issues-via-pull-requests
 -->
 
@@ -14,13 +14,11 @@ see: https://github.com/blog/1506-closing-issues-via-pull-requests
 #### Any other comments?
 
 <!--
-Please, be aware that we are a loose team of volunteers so patience
+Please be aware that we are a loose team of volunteers so patience
 is necessary, and assistance handling other issues is very welcome.
 We value all user contributions, no matter how minor they are. If we
 are slow to review, either the pull request needs some benchmarking,
 tinkering, convincing, etc. or more likely the reviewers are simply
 busy. In either case, we ask for your understanding during the review
 process.
-
-Thanks for contributing!
 -->
diff --git a/.github/tools/cron/install.sh b/.github/tools/cron/install.sh
deleted file mode 100755
index 4172710..0000000
--- a/.github/tools/cron/install.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-set -e
-
-echo "Upgrading pip and setuptools."
-pip install --upgrade pip setuptools
-
-echo "Installing numpy, scipy and scikit-learn."
-dev_anaconda_url=https://pypi.anaconda.org/scipy-wheels-nightly/simple
-pip install --pre --upgrade --timeout=60 --extra-index $dev_anaconda_url numpy scipy scikit-learn
-
-# Cython nightly builds should be still fetched from the Rackspace container
-echo "Installing cython."
-dev_rackspace_url=https://7933911d6844c6c53a7d-47bd50c35cd79bd838daf386af554a83.ssl.cf2.rackcdn.com
-pip install --pre --upgrade --timeout=60 -f $dev_rackspace_url cython
-
-echo "Installing pytest."
-pip install pytest==4.6.4 pytest-cov
-
-echo "Installing codecov."
-pip install --upgrade codecov
-
-python setup.py develop
diff --git a/.github/tools/deployment/before_install.sh b/.github/tools/deployment/before_install.sh
deleted file mode 100644
index 63cb7b4..0000000
--- a/.github/tools/deployment/before_install.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# Set the platform variables used in multibuild scripts
-if [ $(uname) == "Darwin" ]; then
-    echo "::set-env name=TRAVIS_OS_NAME::osx"
-    echo "::set-env name=MACOSX_DEPLOYMENT_TARGET::10.9"
-else
-    echo "::set-env name=TRAVIS_OS_NAME::linux"
-fi
-
-# Store the original Python path to be able to create
-# a testing environment using the same Python version
-echo "::set-env name=PYTHON_EXE::`which python`"
-
-# Add Conda directory to PATH environment variable
-echo "::add-path::$CONDA/bin"
-sudo chown -R $USER $CONDA
diff --git a/.github/tools/deployment/build_source.sh b/.github/tools/deployment/build_source.sh
new file mode 100644
index 0000000..7477fcb
--- /dev/null
+++ b/.github/tools/deployment/build_source.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+set -e
+
+python -m venv build_env
+source build_env/bin/activate
+
+pip install numpy scipy cython
+pip install twine
+
+python setup.py sdist
+
+# Check the rendering of the source distribution
+twine check dist/*.tar.gz
diff --git a/.github/tools/deployment/build_wheel.sh b/.github/tools/deployment/build_wheel.sh
deleted file mode 100644
index b66a226..0000000
--- a/.github/tools/deployment/build_wheel.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-set -e
-
-pip install virtualenv
-
-source multibuild/common_utils.sh
-source multibuild/travis_steps.sh
-source extra_functions.sh
-
-# Setup build dependencies
-before_install
-
-clean_code $REPO_DIR $BUILD_COMMIT
-build_wheel $REPO_DIR $PLAT
diff --git a/.github/tools/deployment/config.sh b/.github/tools/deployment/config.sh
deleted file mode 100644
index ab21d81..0000000
--- a/.github/tools/deployment/config.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-# Define custom utilities
-
-function pre_build
-{
-    # Stuff to do before starting building the wheels
-    :
-}
-
-function run_tests
-{
-    # Run tests on installed distribution from an empty directory
-    pytest -l -v --pyargs sklr
-}
diff --git a/.github/tools/deployment/extra_functions.sh b/.github/tools/deployment/extra_functions.sh
deleted file mode 100644
index 68c7cd4..0000000
--- a/.github/tools/deployment/extra_functions.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-# Define extra functions
-
-function setup_test_venv
-{
-    # Test in a new empty virtual environment
-    if [ $(uname) == "Darwin" ]; then
-        $PYTHON_EXE -m venv test_venv
-        source test_venv/bin/activate
-
-        PYTHON_EXE=`which python`
-        PIP_CMD="$PYTHON_EXE -mpip"
-        python -m pip install --upgrade pip wheel
-    fi
-}
-
-function teardown_test_venv
-{
-    if [ $(uname) == "Darwin" ]; then
-        source venv/bin/activate
-    fi
-}
diff --git a/.github/tools/deployment/upload_anaconda.sh b/.github/tools/deployment/upload_anaconda.sh
new file mode 100644
index 0000000..fa78dc0
--- /dev/null
+++ b/.github/tools/deployment/upload_anaconda.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+conda install -y anaconda-client
+
+anaconda -t $ANACONDA_TOKEN upload --force -u alfaro96 dist/artifact/*
+echo "Index: https://pypi.anaconda.org/alfaro96/simple"
diff --git a/.github/tools/deployment/upload_wheel.sh b/.github/tools/deployment/upload_wheel.sh
deleted file mode 100644
index 7ad0c61..0000000
--- a/.github/tools/deployment/upload_wheel.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-conda install -q -y anaconda-client
-
-ls wheelhouse/*.whl
-
-# Force a replacement if the remote file already exists
-anaconda -t $CONDA_TOKEN upload --force -u alfaro96 wheelhouse/*.whl
diff --git a/.github/tools/integration/install.sh b/.github/tools/integration/install.sh
index 4ae3371..b421d64 100644
--- a/.github/tools/integration/install.sh
+++ b/.github/tools/integration/install.sh
@@ -5,13 +5,19 @@ set -e
 echo "Upgrading pip and setuptools."
 pip install --upgrade pip setuptools
 
-echo "Installing numpy, scipy, cython and scikit-learn."
-pip install numpy==$NUMPY_VERSION scipy==$SCIPY_VERSION cython==$CYTHON_VERSION scikit-learn==$SCIKIT_LEARN_VERSION
+echo "Installing numpy and scipy."
+pip install numpy==$NUMPY_MIN_VERSION scipy==$SCIPY_MIN_VERSION
+
+echo "Installing cython."
+pip install cython==$CYTHON_MIN_VERSION
+
+echo "Installing scikit-learn."
+pip install scikit-learn==$SCIKIT_LEARN_MIN_VERSION
 
 echo "Installing pytest."
-pip install pytest==4.6.4 pytest-cov
+pip install pytest==$PYTEST_MIN_VERSION pytest-xdist
 
 echo "Installing codecov."
-pip install --upgrade codecov
+pip install codecov pytest-cov
 
-python setup.py develop
+pip install --editable .
diff --git a/.github/tools/linting/check.sh b/.github/tools/linting/check.sh
new file mode 100644
index 0000000..0f68ef8
--- /dev/null
+++ b/.github/tools/linting/check.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -e
+
+echo "Running flake8."
+flake8 sklr
diff --git a/.github/tools/nightly/install.sh b/.github/tools/nightly/install.sh
new file mode 100755
index 0000000..2359053
--- /dev/null
+++ b/.github/tools/nightly/install.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+set -e
+
+echo "Upgrading pip and setuptools."
+pip install --upgrade pip setuptools
+
+echo "Installing numpy, scipy and scikit-learn."
+dev_anaconda_url=https://pypi.anaconda.org/scipy-wheels-nightly/simple
+pip install --pre --extra-index $dev_anaconda_url numpy scipy scikit-learn
+
+echo "Installing cython."
+pip install --pre cython
+
+echo "Installing pytest."
+pip install pytest pytest-xdist
+
+echo "Installing codecov."
+pip install codecov pytest-cov
+
+pip install --editable .
diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml
index 26494c6..50be55a 100644
--- a/.github/workflows/deployment.yml
+++ b/.github/workflows/deployment.yml
@@ -1,79 +1,119 @@
+# Workflow to build and test the wheels and the source distribution
 name: Continuous deployment wheels
 
 on:
+  schedule:
+    # Everyday at 3:42 UTC
+    - cron: "42 3 */1 * *"
   push:
     branches:
       - master
-    tags:
-      - "[0-9]+.[0-9]+.[0-9]+"
+      # Release branches
+      - "[0-9]+.[0-9]+.X"
   pull_request:
     branches:
       - master
       - "[0-9]+.[0-9]+.X"
+  # Manual trigger run
+  workflow_dispatch:
 
 jobs:
-  build:
+  build_wheels:
+    name: Build and test wheel for ${{ matrix.platform_id }} and cp-${{ matrix.python }}
     runs-on: ${{ matrix.os }}
 
     strategy:
+      # Prevent a failing job from failing a workflow run
+      fail-fast: false
       matrix:
-        os:
-          - ubuntu-latest
-          - macos-latest
-        python:
-          - 3.6
-          - 3.7
-          - 3.8
-
-    env:
-      REPO_DIR: scikit-lr
-      BUILD_COMMIT: ${{ github.sha }}
-      PLAT: x86_64
-      MB_PYTHON_VERSION: ${{ matrix.python }}
-      BUILD_DEPENDS: "numpy==1.17.3 cython==0.29.14 scipy==1.3.2 scikit-learn==0.22.0"
-      TEST_DEPENDS: pytest==4.6.4
+        os: [ubuntu-latest, windows-latest, macos-latest]
+        python: [37, 38, 39]
+        bitness: [32, 64]
+        include:
+          # Run 32-bit and 64-bit versions in parallel
+          - os: ubuntu-latest
+            bitness: 32
+            platform_id: manylinux_i686
+          - os: ubuntu-latest
+            bitness: 64
+            platform_id: manylinux_x86_64
+          - os: windows-latest
+            bitness: 32
+            platform_id: win32
+          - os: windows-latest
+            bitness: 64
+            platform_id: win_amd64
+          - os: macos-latest
+            bitness: 64
+            platform_id: macosx_x86_64
+        exclude:
+          - os: macos-latest
+            bitness: 32
 
     steps:
       - name: Checkout scikit-lr
         uses: actions/checkout@v2
+
+      - name: Setup Python
+        uses: actions/setup-python@v2
+
+      - name: Build and test wheel
+        uses: pypa/cibuildwheel@v1.12.0
+        env:
+          CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }}
+          CIBW_MANYLINUX_X86_64_IMAGE: manylinux1
+          CIBW_MANYLINUX_I686_IMAGE: manylinux1
+          CIBW_TEST_COMMAND: bash {project}/.github/tools/deployment/test_wheel.sh
+          CIBW_TEST_REQUIRES: pytest
+          CIBW_BUILD_VERBOSITY: 1
+
+      - name: Store wheel
+        uses: actions/upload-artifact@v2
         with:
-          path: scikit-lr
+          path: wheelhouse/*.whl
+
+  build_sdist:
+    name: Build and test source distribution
+    runs-on: ubuntu-latest
 
-      - name: Checkout multibuild
+    steps:
+      - name: Checkout scikit-lr
         uses: actions/checkout@v2
-        with:
-          repository: matthew-brett/multibuild
-          ref: devel
-          path: multibuild
 
       - name: Setup Python
         uses: actions/setup-python@v2
+
+      - name: Build source distribution
+        run: bash $GITHUB_WORKSPACE/.github/tools/deployment/build_source.sh
+
+      - name: Test source distribution
+        run: bash $GITHUB_WORKSPACE/.github/tools/deployment/test_source.sh
+
+      - name: Store source distribution
+        uses: actions/upload-artifact@v2
         with:
-          python-version: ${{ matrix.python }}
+          path: dist/*.tar.gz
 
-      - name: Copy files
-        env:
-          FILES_PATH: ${{ github.workspace }}/scikit-lr/.github/tools/deployment
-        run: |
-          cp $FILES_PATH/extra_functions.sh $GITHUB_WORKSPACE
-          cp $FILES_PATH/before_install.sh $GITHUB_WORKSPACE
-          cp $FILES_PATH/config.sh $GITHUB_WORKSPACE
-          cp $FILES_PATH/build_wheel.sh $GITHUB_WORKSPACE
-          cp $FILES_PATH/test_wheel.sh $GITHUB_WORKSPACE
-          cp $FILES_PATH/upload_wheel.sh $GITHUB_WORKSPACE
+  upload_anaconda:
+    name: Upload artifacts
+    runs-on: ubuntu-latest
+    needs: [build_wheels, build_sdist]
+    # Prevent uploading artifacts on pull requests
+    if: github.event_name != 'pull_request'
 
-      - name: Define variables
-        run: source before_install.sh
+    steps:
+      - name: Checkout scikit-lr
+        uses: actions/checkout@v2
 
-      - name: Build wheel
-        run: bash build_wheel.sh
+      - name: Download artifacts
+        uses: actions/download-artifact@v2
+        with:
+          path: dist
 
-      - name: Test wheel
-        run: bash test_wheel.sh
+      - name: Setup Python
+        uses: actions/setup-python@v2
 
-      - name: Upload wheel
+      - name: Upload artifacts
+        run: bash $GITHUB_WORKSPACE/build_tools/github/upload_anaconda.sh
         env:
-          CONDA_TOKEN: ${{ secrets.CONDA_TOKEN }}
-        # The wheels should not be uploaded on PRs
-        if: ${{ github.event_name != 'pull_request' }}
-        run: bash upload_wheel.sh
+          ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 5aceb7f..9aaf477 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -1,9 +1,11 @@
+# Workflow to build and test the library
 name: Continuous integration tests
 
 on:
   push:
     branches:
       - master
+      # Release branches
       - "[0-9]+.[0-9]+.X"
   pull_request:
     branches:
@@ -12,23 +14,23 @@ on:
 
 jobs:
   test:
+    name: Build and test library for ${{ matrix.os }} and cp-${{ matrix.python }}
     runs-on: ${{ matrix.os }}
 
     strategy:
+      # Prevent a failing job from failing a workflow run
+      fail-fast: false
       matrix:
-        os:
-          - ubuntu-latest
-          - macos-latest
-        python:
-          - 3.6
-          - 3.7
-          - 3.8
-
-    env:
-        NUMPY_VERSION: 1.17.3
-        SCIPY_VERSION: 1.3.2
-        CYTHON_VERSION: 0.29.14
-        SCIKIT_LEARN_VERSION: 0.23.0
+        os: [ubuntu-latest, windows-latest, macos-latest]
+        python: [37, 38, 39]
+        include:
+          # Set the version identifier
+          - python: 37
+            python-version: 3.7
+          - python: 38
+            python-version: 3.8
+          - python: 39
+            python-version: 3.9
 
     steps:
       - name: Checkout scikit-lr
@@ -37,15 +39,22 @@ jobs:
       - name: Setup Python
         uses: actions/setup-python@v2
         with:
-          python-version: ${{ matrix.python }}
+          python-version: ${{ matrix.python-version }}
 
       - name: Install dependencies
-        run: source $GITHUB_WORKSPACE/.github/tools/integration/install.sh
+        run: bash $GITHUB_WORKSPACE/.github/tools/integration/install.sh
+        env:
+          NUMPY_MIN_VERSION: 1.14.6
+          SCIPY_MIN_VERSION: 1.1.0
+          CYTHON_MIN_VERSION: 0.28.5
+          PYTEST_MIN_VERSION: 5.0.1
+          PYTEST_COV_MIN_VERSION: 2.9.0
+          SCIKIT_LEARN_MIN_VERSION: 0.24.0
 
-      - name: Execute code tests
+      - name: Test library
         run: bash $GITHUB_WORKSPACE/.github/tools/integration/test_script.sh
 
-      - name: Execute documentation tests
+      - name: Test documentation
         run: bash $GITHUB_WORKSPACE/.github/tools/integration/test_docs.sh
 
       - name: Upload code coverage
diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml
index b5f8bf0..8720834 100644
--- a/.github/workflows/linting.yml
+++ b/.github/workflows/linting.yml
@@ -1,9 +1,11 @@
-name: Linting tests
+# Workflow to check linting violations
+name: Linting check
 
 on:
   push:
     branches:
       - master
+      # Release branches
       - "[0-9]+.[0-9]+.X"
   pull_request:
     branches:
@@ -11,22 +13,18 @@ on:
       - "[0-9]+.[0-9]+.X"
 
 jobs:
-  test:
+  check:
     runs-on: ubuntu-latest
 
     steps:
-      # Checkout using the first version because, in the second
-      # version, the workflow payload contains a wrong revision
       - name: Checkout scikit-lr
         uses: actions/checkout@v1
 
       - name: Setup Python
         uses: actions/setup-python@v2
-        with:
-          python-version: 3.8
 
       - name: Install dependencies
-        run: source $GITHUB_WORKSPACE/.github/tools/linting/install.sh
+        run: bash $GITHUB_WORKSPACE/.github/tools/linting/install.sh
 
-      - name: Test linting
-        run: bash $GITHUB_WORKSPACE/.github/tools/linting/test.sh
+      - name: Check linting
+        run: bash $GITHUB_WORKSPACE/.github/tools/linting/check.sh
diff --git a/.github/workflows/cron.yml b/.github/workflows/nightly.yml
similarity index 56%
rename from .github/workflows/cron.yml
rename to .github/workflows/nightly.yml
index bf9c2fd..67163c3 100644
--- a/.github/workflows/cron.yml
+++ b/.github/workflows/nightly.yml
@@ -1,7 +1,9 @@
+# Workflow to nightly build and test the library
 name: Nightly tests
 
 on:
   schedule:
+    # Everyday at 3:42 UTC
     - cron: "42 3 */1 * *"
 
 jobs:
@@ -14,17 +16,15 @@ jobs:
 
       - name: Setup Python
         uses: actions/setup-python@v2
-        with:
-          python-version: 3.8
 
       - name: Install dependencies
-        run: source $GITHUB_WORKSPACE/.github/tools/cron/install.sh
+        run: bash $GITHUB_WORKSPACE/.github/tools/nightly/install.sh
 
-      - name: Execute code tests
-        run: bash $GITHUB_WORKSPACE/.github/tools/cron/test_script.sh
+      - name: Test library
+        run: bash $GITHUB_WORKSPACE/.github/tools/nightly/test_script.sh
 
-      - name: Execute documentation tests
-        run: bash $GITHUB_WORKSPACE/.github/tools/cron/test_docs.sh
+      - name: Test documentation
+        run: bash $GITHUB_WORKSPACE/.github/tools/nightly/test_docs.sh
 
       - name: Upload code coverage
         uses: codecov/codecov-action@v1


Test patch:
diff --git a/.github/tools/cron/test_docs.sh b/.github/tools/cron/test_docs.sh
deleted file mode 100644
index 93be0ba..0000000
--- a/.github/tools/cron/test_docs.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# pytest $(find docs -name "*.rst" | sort)
diff --git a/.github/tools/cron/test_script.sh b/.github/tools/cron/test_script.sh
deleted file mode 100755
index 27b72ab..0000000
--- a/.github/tools/cron/test_script.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-set -e
-
-TEST_CMD="pytest --showlocals --durations=20 --pyargs"
-TEST_CMD="$TEST_CMD --cov=sklr"
-TEST_CMD="$TEST_CMD --cov-report=xml"
-TEST_CMD="$TEST_CMD -Werror::DeprecationWarning"
-TEST_CMD="$TEST_CMD -Werror::FutureWarning"
-
-$TEST_CMD sklr
diff --git a/.github/tools/deployment/test_source.sh b/.github/tools/deployment/test_source.sh
new file mode 100644
index 0000000..ac95369
--- /dev/null
+++ b/.github/tools/deployment/test_source.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+python -m venv test_env
+source test_env/bin/activate
+
+pip install dist/*.tar.gz
+pip install pytest
+
+# Run the tests on the installed source distribution
+mkdir tmp_for_test
+cp setup.cfg tmp_for_test
+cd tmp_for_test
+
+pytest --pyargs sklr
diff --git a/.github/tools/deployment/test_wheel.sh b/.github/tools/deployment/test_wheel.sh
index e6eed7c..56c9546 100644
--- a/.github/tools/deployment/test_wheel.sh
+++ b/.github/tools/deployment/test_wheel.sh
@@ -2,10 +2,4 @@
 
 set -e
 
-source multibuild/common_utils.sh
-source multibuild/travis_steps.sh
-source extra_functions.sh
-
-setup_test_venv
-install_run $PLAT
-teardown_test_venv
+pytest --pyargs sklr
diff --git a/.github/tools/integration/test_docs.sh b/.github/tools/integration/test_docs.sh
index 93be0ba..dcedbcc 100644
--- a/.github/tools/integration/test_docs.sh
+++ b/.github/tools/integration/test_docs.sh
@@ -2,4 +2,4 @@
 
 set -e
 
-# pytest $(find docs -name "*.rst" | sort)
+make test-docs
diff --git a/.github/tools/integration/test_script.sh b/.github/tools/integration/test_script.sh
index 842aa98..ed1382c 100644
--- a/.github/tools/integration/test_script.sh
+++ b/.github/tools/integration/test_script.sh
@@ -3,7 +3,12 @@
 set -e
 
 TEST_CMD="pytest --showlocals --durations=20 --pyargs"
-TEST_CMD="$TEST_CMD --cov=sklr"
-TEST_CMD="$TEST_CMD --cov-report=xml"
+TEST_CMD="$TEST_CMD --cov=sklr --cov-report=xml"
+TEST_CMD="$TEST_CMD -n2"
+
+# Run the tests on the installed development version
+mkdir tmp_for_test
+cp setup.cfg tmp_for_test
+cd tmp_for_test
 
 $TEST_CMD sklr
diff --git a/.github/tools/linting/test.sh b/.github/tools/linting/test.sh
deleted file mode 100644
index 5915c1a..0000000
--- a/.github/tools/linting/test.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/bash
-
-PROJECT=alfaro96/scikit-lr
-PROJECT_URL=https://github.com/$PROJECT.git
-
-set -e
-
-# Find the remote with the project name (upstream in most cases)
-REMOTE=$(git remote -v | grep $PROJECT | cut -f1 | head -1 || echo "")
-echo "Remotes"
-git remote --verbose
-
-# Get the local branch reference and the remote upstream reference
-LOCAL_BRANCH_REF=$(git rev-parse --abbrev-ref HEAD)
-REMOTE_MASTER_REF="$REMOTE/master"
-echo "Last two commits in $LOCAL_BRANCH_REF"
-git --no-pager log -2 $LOCAL_BRANCH_REF
-
-# Make sure that $REMOTE_MASTER_REF is a valid reference
-echo "Fetching $REMOTE_MASTER_REF"
-git fetch $REMOTE master:refs/remotes/$REMOTE_MASTER_REF
-
-# Find the short hash of the latest commits
-LOCAL_BRANCH_SHORT_HASH=$(git rev-parse --short $LOCAL_BRANCH_REF)
-REMOTE_MASTER_SHORT_HASH=$(git rev-parse --short $REMOTE_MASTER_REF)
-
-# Find the common ancestor between $LOCAL_BRANCH_REF and $REMOTE/master
-COMMIT=$(git merge-base $LOCAL_BRANCH_REF $REMOTE_MASTER_REF) || \
-    echo "No common ancestor found."
-
-if [ -z "$COMMIT" ]; then
-    exit 1
-fi
-
-# Obtain the short hash of the common commit ancestor
-COMMIT_SHORT_HASH=$(git rev-parse --short $COMMIT)
-echo "Common ancestor is $COMMIT_SHORT_HASH."
-git --no-pager show --no-patch $COMMIT_SHORT_HASH
-
-# Find the commit range between the common ancestor and the local commit
-COMMIT_RANGE="$COMMIT_SHORT_HASH..$LOCAL_BRANCH_SHORT_HASH"
-
-# Find the modified files in the local commit with respect to
-# the common ancestor and exit in case that there is no match
-MODIFIED_FILES="$(git diff --name-only $COMMIT_RANGE || \
-    echo "no_match")"
-
-if [[ "$MODIFIED_FILES" == "no_match" ]]; then
-    echo "No files has been modified."
-else
-    git diff --unified=0 $COMMIT_RANGE -- $MODIFIED_FILES | \
-    flake8 --diff --show-source "$*"
-fi
-
-echo "No problem detected by flake8."
diff --git a/.github/tools/nightly/test_docs.sh b/.github/tools/nightly/test_docs.sh
new file mode 100644
index 0000000..dcedbcc
--- /dev/null
+++ b/.github/tools/nightly/test_docs.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -e
+
+make test-docs
diff --git a/.github/tools/nightly/test_script.sh b/.github/tools/nightly/test_script.sh
new file mode 100755
index 0000000..3bd0859
--- /dev/null
+++ b/.github/tools/nightly/test_script.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -e
+
+TEST_CMD="pytest --showlocals --durations=20 --pyargs"
+TEST_CMD="$TEST_CMD --cov=sklr --cov-report=xml"
+TEST_CMD="$TEST_CMD -Werror::DeprecationWarning -Werror::FutureWarning"
+TEST_CMD="$TEST_CMD -n2"
+
+# Run the tests on the installed development version
+mkdir tmp_for_test
+cp setup.cfg tmp_for_test
+cd tmp_for_test
+
+$TEST_CMD sklr