Repository: appsembler/course-access-groups (language: python)

Issue:
convert to Github Actions
There's a `.travis.yml`, but it's not currently hooked up. We should port to Github Actions and ensure that tests are run on every PR.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..c6e52b5
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,32 @@
+name: ci
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: [3.5]
+        tox-env:
+          - py3-django2
+          - py3-django2-check
+          - docs
+          - quality
+    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: |
+         pip install tox
+     - name: Test with tox
+       run: tox -e ${{ matrix.tox-env }}
+     - name: codecov
+       uses: codecov/codecov-action@v1
+       if: ${{ matrix.tox-env == 'py3-django2' }}
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 0000000..37f76ca
--- /dev/null
+++ b/.github/workflows/python-publish.yml
@@ -0,0 +1,33 @@
+# This workflow 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:
+  pull_request:
+  release:
+    types: [published]
+
+jobs:
+  package:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python
+      uses: actions/setup-python@v2
+      with:
+        python-version: '3.x'
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install build
+    - name: Build package
+      run: python -m build
+    - name: Publish package
+      uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
+      with:
+        user: __token__
+        password: ${{ secrets.PYPI_API_TOKEN }}
+      if: ${{ startsWith(github.ref, 'refs/tags') }}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 4b59542..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# Config file for automatic testing at travis-ci.org
-
-language: python
-
-python:
-  - 3.5
-
-env:
-  - TOXENV=py3-django2
-  - TOXENV=py3-django2-check
-  - TOXENV=docs
-  - TOXENV=flake8
-
-cache:
-  - pip
-
-before_install:
-  - pip install pip==10.0.1
-
-install:
-  - pip install -r requirements/travis.txt
-
-script:
-  - tox
-
-after_success:
-  - codecov
-
-deploy:
-  provider: pypi
-  user: appsembler
-  password:
-    secure: PmktUfLAp7tOuDJbfkG8KuUC3enOR/biOqil7gGZKCgMHJ9JFbAlhmFMOXCy/t5PNqYW1Md6wvebnvbtDL3TDIdAGINif0iA6hxOFJnGM/4nHvIHfs7HkbsuWiBDNQSxyhyvmFLBosX4SQtWQguxngQIVK82jvL38HQAY+ys3gIuJ/T5TtkRwRdoxMqV4gqafCSypfMH1H6pnT/NNBvvOhxfdA2x5HGC81afBNeUWniZpuoN4/VC0PtdCLosA/FyqB99AbqqPaCVbci4uajSo+3Q0yU1AWVAOpdwBpgDIeeMm5oTYNyYQjkOB7Lounn9AG6gRIYOm7L2ir023SphFURZd6lH8J3RlmG4rc3SC1vMYz5JVEkYUHCezbTJJNzsSwIw8aFJtoK/0EaYyQt6Iqk+360tA0AEGRBXKiKLI5b3ku8Niimhmhi735+1sYw71LFOzzFYxVjjjTg25VRxj5Td2qDaT2xBmEOcDnySEznw7q96dDGINBNcbduEVEPhf2JLDB3v+J9WOHeuP66rIX5e5tzAe9O6aDWMuyJsnzseZ9BELyTUugOd8zzanl+RwdRGt14r4Di5hAL61X9Rs2YS7/qBzbkM7Mbw84FaxWA9x0dLx0DjTxRTxy36FAbzAW23fOgmnCIPkNn+MWswN96OdtFZiQoO9WTnEMTv3r8=
-  distributions: sdist bdist_wheel
-  on:
-    tags: true
-  skip_existing: true
diff --git a/Makefile b/Makefile
index 18eb158..81e95b3 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,6 @@ upgrade: ## update the requirements/*.txt files with the latest packages satisfy
 	pip-compile --upgrade -o requirements/test.txt requirements/test.in
 	pip-compile --upgrade -o requirements/doc.txt requirements/doc.in
 	pip-compile --upgrade -o requirements/quality.txt requirements/quality.in
-	pip-compile --upgrade -o requirements/travis.txt requirements/travis.in
 	pip-compile --upgrade -o requirements/dev.txt requirements/dev.in
 	# Let tox control the Django version for tests
 	sed '/^[dD]jango==/d' requirements/test.txt > requirements/test.tmp
diff --git a/README.rst b/README.rst
index e612708..771428e 100644
--- a/README.rst
+++ b/README.rst
@@ -1,7 +1,7 @@
 Course Access Groups
 ====================
 
-|pypi-badge| |travis-badge| |codecov-badge| |doc-badge| |pyversions-badge|
+|pypi-badge| |codecov-badge| |doc-badge| |pyversions-badge|
 |license-badge|
 
 
@@ -87,10 +87,6 @@ refer to this `list of resources`_ if you need any assistance.
     :target: https://pypi.python.org/pypi/course-access-groups/
     :alt: PyPI
 
-.. |travis-badge| image:: https://travis-ci.org/appsembler/course-access-groups.svg?branch=master
-    :target: https://travis-ci.org/appsembler/course-access-groups
-    :alt: Travis
-
 .. |codecov-badge| image:: http://codecov.io/github/appsembler/course-access-groups/coverage.svg?branch=master
     :target: http://codecov.io/github/appsembler/course-access-groups?branch=master
     :alt: Codecov
diff --git a/course_access_groups/__init__.py b/course_access_groups/__init__.py
index eaad5ab..f5ac474 100644
--- a/course_access_groups/__init__.py
+++ b/course_access_groups/__init__.py
@@ -3,6 +3,6 @@
 """
 
 
-__version__ = '0.4.0'
+__version__ = '0.5.dev1'
 
 default_app_config = 'course_access_groups.apps.CourseAccessGroupsConfig'
diff --git a/course_access_groups/apps.py b/course_access_groups/apps.py
index 15f0a3c..50ffe04 100644
--- a/course_access_groups/apps.py
+++ b/course_access_groups/apps.py
@@ -5,7 +5,6 @@
 
 
 from django.apps import AppConfig
-
 from openedx.core.djangoapps.plugins.constants import PluginSignals, PluginURLs, ProjectType
 
 
diff --git a/mocks/openedx/core/djangoapps/content/course_overviews/admin.py b/mocks/openedx/core/djangoapps/content/course_overviews/admin.py
index 0273017..31d26d7 100644
--- a/mocks/openedx/core/djangoapps/content/course_overviews/admin.py
+++ b/mocks/openedx/core/djangoapps/content/course_overviews/admin.py
@@ -1,5 +1,4 @@
 from django.contrib import admin
-
 from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 
 
diff --git a/requirements/dev.in b/requirements/dev.in
deleted file mode 100644
index fa27299..0000000
--- a/requirements/dev.in
+++ /dev/null
@@ -1,9 +0,0 @@
-# Additional requirements for development of this application
--c constraints.txt
-
--r pip-tools.txt          # pip-tools and its dependencies, for managing requirements files
--r quality.txt            # Core and quality check dependencies
--r travis.txt             # tox and related dependencies
-
-diff-cover                # Changeset diff test coverage
-edx-i18n-tools            # For i18n_tool dummy
diff --git a/requirements/dev.txt b/requirements/dev.txt
deleted file mode 100644
index 61bd7ce..0000000
--- a/requirements/dev.txt
+++ /dev/null
@@ -1,152 +0,0 @@
-#
-# This file is autogenerated by pip-compile
-# To update, run:
-#
-#    make upgrade
-#
-appdirs==1.4.4
-    # via
-    #   -r travis.txt
-    #   virtualenv
-certifi==2020.12.5
-    # via
-    #   -r travis.txt
-    #   requests
-chardet==4.0.0
-    # via
-    #   -r travis.txt
-    #   diff-cover
-    #   requests
-click==7.1.2
-    # via
-    #   -r pip-tools.txt
-    #   pip-tools
-codecov==2.1.11
-    # via -r travis.txt
-coverage==5.4
-    # via
-    #   -r travis.txt
-    #   codecov
-diff-cover==4.2.1
-    # via -r dev.in
-distlib==0.3.1
-    # via
-    #   -r travis.txt
-    #   virtualenv
-django==2.2.24
-    # via
-    #   -c constraints.txt
-    #   edx-i18n-tools
-edx-i18n-tools==0.5.3
-    # via -r dev.in
-filelock==3.0.12
-    # via
-    #   -r travis.txt
-    #   tox
-    #   virtualenv
-flake8==3.8.4
-    # via -r quality.txt
-idna==2.10
-    # via
-    #   -r travis.txt
-    #   requests
-importlib-metadata==2.1.1
-    # via
-    #   -r quality.txt
-    #   -r travis.txt
-    #   inflect
-importlib-resources==3.2.1
-    # via -r travis.txt
-inflect==3.0.2
-    # via jinja2-pluralize
-isort==4.3.21
-    # via -r quality.txt
-jinja2-pluralize==0.3.0
-    # via diff-cover
-jinja2==2.11.3
-    # via
-    #   diff-cover
-    #   jinja2-pluralize
-markupsafe==1.1.1
-    # via jinja2
-mccabe==0.6.1
-    # via
-    #   -r quality.txt
-    #   flake8
-packaging==20.9
-    # via
-    #   -r travis.txt
-    #   tox
-path.py==12.5.0
-    # via edx-i18n-tools
-path==13.1.0
-    # via path.py
-pip-tools==5.5.0
-    # via -r pip-tools.txt
-pluggy==0.13.1
-    # via
-    #   -r travis.txt
-    #   diff-cover
-    #   tox
-polib==1.1.0
-    # via edx-i18n-tools
-py==1.10.0
-    # via
-    #   -r travis.txt
-    #   tox
-pycodestyle==2.6.0
-    # via
-    #   -r quality.txt
-    #   flake8
-pyflakes==2.2.0
-    # via
-    #   -r quality.txt
-    #   flake8
-pygments==2.7.4
-    # via diff-cover
-pyparsing==2.4.7
-    # via
-    #   -r travis.txt
-    #   packaging
-pytz==2020.5
-    # via django
-pyyaml==5.3.1
-    # via edx-i18n-tools
-requests==2.25.1
-    # via
-    #   -r travis.txt
-    #   codecov
-six==1.15.0
-    # via
-    #   -r travis.txt
-    #   edx-i18n-tools
-    #   tox
-    #   virtualenv
-sqlparse==0.4.1
-    # via django
-toml==0.10.2
-    # via
-    #   -r travis.txt
-    #   tox
-tox-battery==0.6.1
-    # via -r travis.txt
-tox==3.21.3
-    # via
-    #   -r travis.txt
-    #   tox-battery
-urllib3==1.26.3
-    # via
-    #   -r travis.txt
-    #   requests
-virtualenv==20.4.1
-    # via
-    #   -r travis.txt
-    #   tox
-zipp==1.2.0
-    # via
-    #   -r quality.txt
-    #   -r travis.txt
-    #   importlib-metadata
-
-# The following packages are considered to be unsafe in a requirements file:
-# pip
diff --git a/requirements/quality.in b/requirements/quality.in
deleted file mode 100644
index 66e72ad..0000000
--- a/requirements/quality.in
+++ /dev/null
@@ -1,5 +0,0 @@
-# Requirements for code quality checks
--c constraints.txt
-
-isort                     # to standardize order of imports
-flake8                    # Code quality checks
diff --git a/requirements/quality.txt b/requirements/quality.txt
deleted file mode 100644
index c2446da..0000000
--- a/requirements/quality.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# This file is autogenerated by pip-compile
-# To update, run:
-#
-#    make upgrade
-#
-flake8==3.8.4
-    # via -r requirements/quality.in
-importlib-metadata==2.1.1
-    # via flake8
-isort==4.3.21
-    # via -r requirements/quality.in
-mccabe==0.6.1
-    # via flake8
-pycodestyle==2.6.0
-    # via flake8
-pyflakes==2.2.0
-    # via flake8
-zipp==1.2.0
-    # via importlib-metadata
diff --git a/requirements/travis.in b/requirements/travis.in
deleted file mode 100644
index 58bb23f..0000000
--- a/requirements/travis.in
+++ /dev/null
@@ -1,6 +0,0 @@
-# Requirements for running tests in Travis
--c constraints.txt
-
-codecov                   # Code coverage reporting
-tox                       # Virtualenv management for tests
-tox-battery               # Makes tox aware of requirements file changes
diff --git a/requirements/travis.txt b/requirements/travis.txt
deleted file mode 100644
index 6f64618..0000000
--- a/requirements/travis.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# This file is autogenerated by pip-compile
-# To update, run:
-#
-#    make upgrade
-#
-appdirs==1.4.4
-    # via virtualenv
-certifi==2020.12.5
-    # via requests
-chardet==4.0.0
-    # via requests
-codecov==2.1.11
-    # via -r requirements/travis.in
-coverage==5.4
-    # via codecov
-distlib==0.3.1
-    # via virtualenv
-filelock==3.0.12
-    # via
-    #   tox
-    #   virtualenv
-idna==2.10
-    # via requests
-importlib-metadata==2.1.1
-    # via
-    #   pluggy
-    #   tox
-    #   virtualenv
-importlib-resources==3.2.1
-    # via virtualenv
-packaging==20.9
-    # via tox
-pluggy==0.13.1
-    # via tox
-py==1.10.0
-    # via tox
-pyparsing==2.4.7
-    # via packaging
-requests==2.25.1
-    # via codecov
-six==1.15.0
-    # via
-    #   tox
-    #   virtualenv
-toml==0.10.2
-    # via tox
-tox-battery==0.6.1
-    # via -r requirements/travis.in
-tox==3.21.3
-    # via
-    #   -r requirements/travis.in
-    #   tox-battery
-urllib3==1.26.3
-    # via requests
-virtualenv==20.4.1
-    # via tox
-zipp==1.2.0
-    # via
-    #   importlib-metadata
-    #   importlib-resources
diff --git a/tox.ini b/tox.ini
index 53769e9..a089bee 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,11 +1,11 @@
 [tox]
-envlist = py3-django2{,-check},docs,flake8
+envlist = py3-django2{,-check},docs,quality
 
 [doc8]
 max-line-length = 120
 
 [flake8]
-exclude = .git,__pycache__,docs/,build,dist,migrations
+exclude = .git,.tox/,__pycache__,docs/,build,dist,migrations
 max-line-length = 120
 per-file-ignores =
     # imported but unused
@@ -39,17 +39,12 @@ commands =
     python setup.py check --restructuredtext --strict
 
 [testenv:quality]
-setenv =
-    CAG_MODULES = course_access_groups manage.py mocks setup.py test_settings.py test_utils tests
 whitelist_externals =
     make
-    rm
-    touch
 deps =
-    -r{toxinidir}/requirements/quality.txt
+    flake8
 commands =
-    flake8 {env:CAG_MODULES}
-    isort --check-only --diff --recursive {env:CAG_MODULES}
+    flake8 course_access_groups manage.py mocks setup.py test_settings.py test_utils tests
     make selfcheck
 
 [testenv:pii_check]


Test patch:
diff --git a/test_utils/__init__.py b/test_utils/__init__.py
index 2fedb95..9806f6f 100644
--- a/test_utils/__init__.py
+++ b/test_utils/__init__.py
@@ -8,9 +8,9 @@
 
 
 from django.views import View
+from mock import patch
 
 import course_access_groups.views
-from mock import patch
 
 
 def patch_site_configs(values):
diff --git a/test_utils/factories.py b/test_utils/factories.py
index 78fa35c..6d5a1f4 100644
--- a/test_utils/factories.py
+++ b/test_utils/factories.py
@@ -1,16 +1,16 @@
 # -*- coding: utf-8 -*-
 
 
+import factory
 from django.contrib.auth import get_user_model
 from django.contrib.sites.models import Site
+from factory.django import DjangoModelFactory
 from opaque_keys.edx.keys import CourseKey
+from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 from organizations.models import Organization, OrganizationCourse, UserOrganizationMapping
+from student.models import UserProfile
 
-import factory
 from course_access_groups.models import CourseAccessGroup, GroupCourse, Membership, MembershipRule, PublicCourse
-from factory.django import DjangoModelFactory
-from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
-from student.models import UserProfile
 
 
 class UserProfileFactory(DjangoModelFactory):
diff --git a/tests/conftest.py b/tests/conftest.py
index 4f3dd9a..5f24c9b 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -4,6 +4,7 @@
 
 
 import pytest
+
 from test_utils.factories import UserFactory
 
 
diff --git a/tests/test_acl_backend.py b/tests/test_acl_backend.py
index f58a9fb..e63e5b4 100644
--- a/tests/test_acl_backend.py
+++ b/tests/test_acl_backend.py
@@ -4,10 +4,10 @@
 """
 
 
+import pytest
 from django.contrib.auth.models import AnonymousUser
 from organizations.models import OrganizationCourse, UserOrganizationMapping
 
-import pytest
 from course_access_groups.acl_backends import user_has_access
 from course_access_groups.openedx_modules import ACCESS_DENIED, ACCESS_GRANTED
 from test_utils import patch_site_configs
diff --git a/tests/test_api.py b/tests/test_api.py
index 1864458..7c2328a 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -6,7 +6,9 @@
 
 import json
 
+import pytest
 from django.contrib.auth import get_user_model
+from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 from organizations.models import Organization, OrganizationCourse, UserOrganizationMapping
 from rest_framework.status import (
     HTTP_200_OK,
@@ -16,9 +18,7 @@
     HTTP_404_NOT_FOUND
 )
 
-import pytest
 from course_access_groups.models import CourseAccessGroup, GroupCourse, Membership, MembershipRule, PublicCourse
-from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 from test_utils.factories import (
     CourseAccessGroupFactory,
     CourseOverviewFactory,
diff --git a/tests/test_api_permissions.py b/tests/test_api_permissions.py
index cf164c2..1a74d28 100644
--- a/tests/test_api_permissions.py
+++ b/tests/test_api_permissions.py
@@ -5,6 +5,7 @@
 
 
 import pytest
+
 from course_access_groups.permissions import CommonAuthMixin
 from course_access_groups.views import CourseAccessGroupViewSet
 from test_utils import get_api_view_classes
diff --git a/tests/test_feature_flag.py b/tests/test_feature_flag.py
index e0cb0d7..93135d0 100644
--- a/tests/test_feature_flag.py
+++ b/tests/test_feature_flag.py
@@ -5,6 +5,7 @@
 
 
 import pytest
+
 from course_access_groups.feature_flag import ConfigurationError, is_feature_enabled
 from test_utils import patch_site_configs
 
diff --git a/tests/test_models.py b/tests/test_models.py
index af2edb4..bde5c04 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -4,10 +4,10 @@
 """
 
 
+import pytest
 from django.core.exceptions import ValidationError
 from organizations.models import UserOrganizationMapping
 
-import pytest
 from course_access_groups.models import CourseAccessGroup, Membership, MembershipRule
 from course_access_groups.signals import on_learner_account_activated
 from test_utils.factories import CourseAccessGroupFactory, MembershipRuleFactory, UserFactory
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index ebd7993..980364d 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -4,14 +4,16 @@
 """
 
 
+import pytest
 from django.contrib.auth import get_user_model
 from django.contrib.sites import shortcuts as sites_shortcuts
 from django.contrib.sites.models import Site
+from mock import Mock, patch
+from openedx.core.lib.api.authentication import OAuth2Authentication
 from organizations.models import Organization, UserOrganizationMapping
 from rest_framework.authentication import TokenAuthentication
 from rest_framework.test import APIRequestFactory
 
-import pytest
 from course_access_groups.permissions import (
     CommonAuthMixin,
     IsSiteAdminUser,
@@ -19,8 +21,6 @@
     is_active_staff_or_superuser,
     is_course_with_public_access
 )
-from mock import Mock, patch
-from openedx.core.lib.api.authentication import OAuth2Authentication
 from test_utils.factories import (
     CourseOverviewFactory,
     OrganizationFactory,