Repository: learningequality/ricecooker (language: python)

Issue:
Migrate CI tests to Github Actions
### Description

Travis has not run on this repository for over 3 months, we should migrate the CI steps to Github Actions and cleanup any residual Travis related code.



Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 3588c679..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-# Config file for automatic testing at travis-ci.org
-# This file will be regenerated if you run travis_pypi_setup.py
-
-language: python
-
-sudo: required
-
-dist: xenial
-
-python:
-  - 3.7
-  - 3.6
-  - 3.5
-
-before_install:
-  - sudo apt-get -y -qq update
-  - sudo apt-get install -y ffmpeg
-  - sudo apt-get install -y poppler-utils
-
-# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
-install: pip install -U setuptools && pip install -U tox-travis
-
-# command to run tests, e.g. python setup.py test
-script: tox
diff --git a/README.md b/README.md
index 1cd885d5..7793bd22 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 ricecooker
 ==========
 [![PyPI pyversions](https://img.shields.io/pypi/pyversions/ricecooker.svg)](https://pypi.python.org/pypi/ricecooker/)
-[![build](https://travis-ci.com/learningequality/ricecooker.svg?branch=master)](https://travis-ci.com/github/learningequality/ricecooker) 
+[![build](https://github.com/learningequality/ricecooker/actions/workflows/pythontest.yml/badge.svg?branch=master)](https://github.com/learningequality/ricecooker/actions)
 [![docs](https://readthedocs.org/projects/ricecooker/badge/?version=latest&style=flat)](https://ricecooker.readthedocs.io/) 
 
 
diff --git a/tox.ini b/tox.ini
index b39d2428..ce1f4404 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,11 +1,11 @@
 [tox]
-envlist = py35, py36, py37, flake8
+envlist = py{3.5,3.6,3.7}
 
 [travis]
 python =
-    3.5: py35
-    3.6: py36
-    3.7: py37
+    3.5: py3.5
+    3.6: py3.6
+    3.7: py3.7
 
 
 [testenv]
@@ -16,8 +16,3 @@ setenv =
 commands =
     pip install -U pip
     py.test --basetemp={envtmpdir}
-
-[testenv:flake8]
-basepython=python
-deps=flake8
-commands=flake8 ricecooker
diff --git a/travis_pypi_setup.py b/travis_pypi_setup.py
deleted file mode 100644
index d16515ab..00000000
--- a/travis_pypi_setup.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""Update encrypted deploy password in Travis config file
-"""
-
-
-from __future__ import print_function
-import base64
-import json
-import os
-from getpass import getpass
-import yaml
-from cryptography.hazmat.primitives.serialization import load_pem_public_key
-from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
-
-
-try:
-    from urllib import urlopen
-except:
-    from urllib.request import urlopen
-
-
-GITHUB_REPO = 'jayoshih/ricecooker'
-TRAVIS_CONFIG_FILE = os.path.join(
-    os.path.dirname(os.path.abspath(__file__)), '.travis.yml')
-
-
-def load_key(pubkey):
-    """Load public RSA key, with work-around for keys using
-    incorrect header/footer format.
-
-    Read more about RSA encryption with cryptography:
-    https://cryptography.io/latest/hazmat/primitives/asymmetric/rsa/
-    """
-    try:
-        return load_pem_public_key(pubkey.encode(), default_backend())
-    except ValueError:
-        # workaround for https://github.com/travis-ci/travis-api/issues/196
-        pubkey = pubkey.replace('BEGIN RSA', 'BEGIN').replace('END RSA', 'END')
-        return load_pem_public_key(pubkey.encode(), default_backend())
-
-
-def encrypt(pubkey, password):
-    """Encrypt password using given RSA public key and encode it with base64.
-
-    The encrypted password can only be decrypted by someone with the
-    private key (in this case, only Travis).
-    """
-    key = load_key(pubkey)
-    encrypted_password = key.encrypt(password, PKCS1v15())
-    return base64.b64encode(encrypted_password)
-
-
-def fetch_public_key(repo):
-    """Download RSA public key Travis will use for this repo.
-
-    Travis API docs: http://docs.travis-ci.com/api/#repository-keys
-    """
-    keyurl = 'https://api.travis-ci.org/repos/{0}/key'.format(repo)
-    data = json.loads(urlopen(keyurl).read().decode())
-    if 'key' not in data:
-        errmsg = "Could not find public key for repo: {}.\n".format(repo)
-        errmsg += "Have you already added your GitHub repo to Travis?"
-        raise ValueError(errmsg)
-    return data['key']
-
-
-def prepend_line(filepath, line):
-    """Rewrite a file adding a line to its beginning.
-    """
-    with open(filepath) as f:
-        lines = f.readlines()
-
-    lines.insert(0, line)
-
-    with open(filepath, 'w') as f:
-        f.writelines(lines)
-
-
-def load_yaml_config(filepath):
-    with open(filepath) as f:
-        return yaml.load(f)
-
-
-def save_yaml_config(filepath, config):
-    with open(filepath, 'w') as f:
-        yaml.dump(config, f, default_flow_style=False)
-
-
-def update_travis_deploy_password(encrypted_password):
-    """Update the deploy section of the .travis.yml file
-    to use the given encrypted password.
-    """
-    config = load_yaml_config(TRAVIS_CONFIG_FILE)
-
-    config['deploy']['password'] = dict(secure=encrypted_password)
-
-    save_yaml_config(TRAVIS_CONFIG_FILE, config)
-
-    line = ('# This file was autogenerated and will overwrite'
-            ' each time you run travis_pypi_setup.py\n')
-    prepend_line(TRAVIS_CONFIG_FILE, line)
-
-
-def main(args):
-    public_key = fetch_public_key(args.repo)
-    password = args.password or getpass('PyPI password: ')
-    update_travis_deploy_password(encrypt(public_key, password.encode()))
-    print("Wrote encrypted password to .travis.yml -- you're ready to deploy")
-
-
-if '__main__' == __name__:
-    import argparse
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument('--repo', default=GITHUB_REPO,
-                        help='GitHub repo (default: %s)' % GITHUB_REPO)
-    parser.add_argument('--password',
-                        help='PyPI password (will prompt if not provided)')
-
-    args = parser.parse_args()
-    main(args)


Test patch:
diff --git a/.github/workflows/pythontest.yml b/.github/workflows/pythontest.yml
new file mode 100644
index 00000000..53adb2aa
--- /dev/null
+++ b/.github/workflows/pythontest.yml
@@ -0,0 +1,49 @@
+name: Python tests
+
+on: [push, pull_request]
+
+jobs:
+  pre_job:
+    name: Path match check
+    runs-on: ubuntu-latest
+    # Map a step output to a job output
+    outputs:
+      should_skip: ${{ steps.skip_check.outputs.should_skip }}
+    steps:
+      - id: skip_check
+        uses: fkirc/skip-duplicate-actions@master
+        with:
+          github_token: ${{ github.token }}
+          paths: '["**.py", ".github/workflows/pythontest.yml"]'
+  unit_test:
+    name: Python unit tests
+    needs: pre_job
+    if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
+    runs-on: ubuntu-18.04
+    strategy:
+      max-parallel: 5
+      matrix:
+        python-version: [3.5, 3.6, 3.7]
+
+    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 system dependencies
+      run: |
+        sudo apt-get -y -qq update
+        sudo apt-get install -y ffmpeg
+        sudo apt-get install -y poppler-utils
+    - name: Install tox
+      run: |
+        python -m pip install --upgrade pip
+        pip install tox
+    - name: tox env cache
+      uses: actions/cache@v2
+      with:
+        path: ${{ github.workspace }}/.tox/py${{ matrix.python-version }}
+        key: ${{ runner.os }}-tox-py${{ matrix.python-version }}-${{ hashFiles('requirements/*.txt') }}
+    - name: Test with tox
+      run: tox -e py${{ matrix.python-version }}