Repository: hyperspy/hyperspy_gui_traitsui (language: python)

Issue:
Add appveyor CI
Same as https://github.com/hyperspy/hyperspy_gui_ipywidgets/issues/15
Add github workflow for release
This workflow do the following:
- Create release on tag
- update version from the tag
- build sdist and bdist
- run test suite with this release package
- upload tarball and wheel as github artifact
- upload to pypi (only from `hyperspy/hyperspy_gui_traitsui` repository)

One missing thing is to set the `secrets.pypi_password` in the settings of the repository. @francisco-dlp, it you can set it the `secrets.pypi_password` as describe in https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#saving-credentials-on-github, I think it would be good to do a release to test it - particularly since https://github.com/hyperspy/hyperspy_gui_traitsui/pull/30 can be annoying for users.


Discussion / hints:

Example of build: https://github.com/ericpre/hyperspy_gui_traitsui/actions/runs/223486677
Some more changes:
- add a script to set the release and development version. This script can also process changelog, useful for hyperspy, but not used here. I think it would be good to move this script to `hyperspy/ci-scripts` and clone it in the github workflow.
- add `RELEASING_GUIDE.md` 
Looking forward to having proper releases of the GUI packages again (as they are stuck on v1.1.1)
:-)
@jlaehne, there is a tag for `v1.3.1` now. Is it good enough, or is a Github release required?

I will revisit this PR for the next release.
@ericpre, the important thing is that there is a v.x.x.x.zip file available, which there now is for v.1.3.1 

So I can update the AUR package tomorrow (at the moment it was downloading master.zip, but with every merge the SHA-key changes and would have to be changed).
Would it be better to use the source distribution from pypi? The sha256 is also available from pypi, so you will not need to get it manually.

Fix patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..5d98b21
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,94 @@
+name: Release
+# This workflow builds the wheels "on tag".
+# If run from the hyperspy/hyperspy_gui_traitsui repository, the wheels will be
+# uploaded to pypi; otherwise, the wheels will be available as a github artifact.
+# This workflow overwrite the version in `hyperspy_gui_traitsui/version.py`
+# with the tag
+on:
+  push:
+    # Sequence of patterns matched against refs/tags
+    tags:
+    - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
+
+jobs:
+  create_release:
+    name: Create Release
+    runs-on: ubuntu-latest
+    outputs: 
+      upload_url: ${{ steps.create_release.outputs.upload_url }}
+      VERSION: ${{ env.VERSION }}
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v2
+      - name: Create Release
+        id: create_release
+        uses: actions/create-release@v1
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions
+        with:
+          tag_name: ${{ github.ref }}
+          release_name: Release ${{ github.ref }}
+          draft: false
+          prerelease: false
+      - name: Get version (on tag)
+        if: startsWith(github.ref, 'refs/tags/')
+        run: |
+          echo "VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV
+
+  build_wheels_linux:
+    name: Wheels on ubuntu-latest
+    needs: create_release
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Set up Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.8
+
+      - name: Install release dependencies
+        run: |
+          python -m pip install twine wheel
+
+      - name: Overwrite `version.py` with tag
+        if: startsWith(github.ref, 'refs/tags/')
+        env: 
+          version_file: hyperspy_gui_traitsui/version.py
+          VERSION: ${{ needs.create_release.outputs.VERSION }}
+        run: |
+          echo '__version__ = "${{ env.VERSION }}"' > ${{ env.version_file }}
+
+      - name: Build source distribution
+        run: |
+          python setup.py sdist bdist_wheel
+
+      - name: Display content dist folder
+        run: |
+          ls dist/
+
+      - name: Install and test distribution
+        env:
+          MPLBACKEND: agg
+        run: |
+          pip install --find-links dist hyperspy_gui_traitsui[tests]
+          pytest --pyargs hyperspy_gui_traitsui
+
+      - uses: actions/upload-artifact@v2
+        with:
+          path: |
+            ./dist/*.whl
+            ./dist/*.tar.gz
+
+      - name: Publish wheels to PyPI
+        if: github.repository_owner == 'hyperspy'
+        env:
+          # Github secret set in the hyperspy/hyperspy_gui_traitsui repository
+          # Not available from fork or pull request
+          # Secrets are not passed to workflows that are triggered by a pull request from a fork
+          TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
+          TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
+        run: |
+          twine upload dist/*.whl --verbose 
+          twine upload dist/*.tar.gz --verbose 
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 4cfaf89..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-language: python
-python:
-    - "nightly"
-    - 3.6
-    - 3.7
-    - 3.8
-sudo: false
-install:
-    - pip install --upgrade pip
-    - pip install https://github.com/hyperspy/hyperspy/archive/RELEASE_next_minor.zip
-    - pip install .
-    - export MPLBACKEND=agg
-script:
-    - python -m unittest hyperspy_gui_traitsui.test_import
-matrix:
-    allow_failures:
-        - python: "nightly"
diff --git a/README.md b/README.md
index 3803afc..9a5b830 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-[![Build Status](https://travis-ci.org/hyperspy/hyperspy_gui_traitsui.svg?branch=master)](https://travis-ci.org/hyperspy/hyperspy_gui_traitsui)
-![PyPI](https://img.shields.io/pypi/v/hyperspy_gui_traitsui.svg)
+![Tests](https://github.com/hyperspy/hyperspy_gui_traitsui/workflows/Tests/badge.svg)
 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hyperspy_gui_traitsui.svg)
-
+![PyPI](https://img.shields.io/pypi/v/hyperspy_gui_traitsui.svg)
+[![Anaconda Cloud](https://anaconda.org/conda-forge/hyperspy-gui-traitsui/badges/version.svg)](https://anaconda.org/conda-forge/hyperspy-gui-traitsui)
 
 **hyperspy_gui_traitsui** provides traitsui graphic user interface (GUI) elements for hyperspy.
 
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index e3a2099..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[bdist_wheel]
-# This flag says that the code is written to work on both Python 2 and Python
-universal=1
diff --git a/setup.py b/setup.py
index 978fcb0..47e03fe 100644
--- a/setup.py
+++ b/setup.py
@@ -80,6 +80,9 @@
     # requirements files see:
     # https://packaging.python.org/en/latest/requirements.html
     install_requires=['hyperspy>=1.6', 'traitsui>=6.0'],
+    extras_require={
+        'tests': ['pytest'],
+        'coverage':["pytest-cov", "codecov"]},
     entry_points={'hyperspy.extensions': 'hyperspy-gui-traitsui = hyperspy_gui_traitsui'},
     package_data={  # Optional
         'hyperspy_gui_traitsui': ['hyperspy_extension.yaml'], },


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..ac0b785
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,50 @@
+name: Tests
+
+on: [push, pull_request]
+
+jobs:
+  run_test_site:
+    name: py${{ matrix.PYTHON_VERSION }}${{ matrix.LABEL }}
+    runs-on: ubuntu-latest
+    timeout-minutes: 30
+    env:
+      MPLBACKEND: agg
+      PIP_ARGS: --upgrade --use-feature=2020-resolver -e
+      PYTEST_ARGS: --pyargs hyperspy_gui_traitsui
+      PYTEST_ARGS_COVERAGE: 
+    strategy:
+      fail-fast: false
+      matrix:
+        PYTHON_VERSION: [3.6, 3.7]
+        PIP_SELECTOR: ['[tests]']
+        include:
+          - PYTHON_VERSION: 3.8
+            PIP_SELECTOR: '[tests, coverage]'
+            PYTEST_ARGS_COVERAGE: --cov=. --cov-report=xml
+            LABEL: /coverage
+    steps:
+      - uses: actions/checkout@v2
+
+      - uses: actions/setup-python@v2
+        name: Install Python
+        with:
+          python-version: ${{ matrix.PYTHON_VERSION }}
+
+      - name: Display version
+        run: |
+          python --version
+          pip --version
+
+      - name: Install
+        shell: bash
+        run: |
+          pip install ${{ env.PIP_ARGS }} .'${{ matrix.PIP_SELECTOR }}'
+          pip install https://github.com/hyperspy/hyperspy/archive/RELEASE_next_minor.zip
+
+      - name: Run test suite
+        run: |
+          pytest ${{ env.PYTEST_ARGS }} ${{ matrix.PYTEST_ARGS_COVERAGE }}
+
+      - name: Upload coverage to Codecov
+        if: ${{ always() }} && ${{ matrix.PYTEST_ARGS_COVERAGE }} 
+        uses: codecov/codecov-action@v1