Skip to content

Commit

Permalink
[SE-5624] Use GitHub Actions and fix failing linter checks (#100)
Browse files Browse the repository at this point in the history
* fix: fix toxenv docs target
* refactor: use get_user_model over User model
* refactor: use f-string over format
* refactor: remove redundant u prefix
* chore: disable no-member errors
* refactor: fix long line lint issues
* refactor: use Python3 style super calls
* chore: various linter fixes
* chore: docstring style issue fixes
* refactor: fix import order and style
* ci: replace Travis CI with GitHub Actions
* chore: extend authors and sort file
* ci: allow mysql integration
* chore: update changelog
* chore(changelog): update changelog
* chore(dependencies): add wheel

Signed-off-by: Gabor Boros <[email protected]>
  • Loading branch information
gabor-boros committed Jun 17, 2022
1 parent 0c2e6a2 commit f09b732
Show file tree
Hide file tree
Showing 41 changed files with 451 additions and 272 deletions.
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
version: 2
updates:
- package-ecosystem: pip
directory: requirements/
schedule:
interval: weekly
75 changes: 75 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
name: Build

on: [push, release]

jobs:
build:
name: Test Python ${{ matrix.python-version }}
runs-on: ubuntu-latest

services:
mysql:
image: mysql:8
env:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 3306:3306

strategy:
fail-fast: false
matrix:
python-version: ["3.8"]
django-version: ["django32"]

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "setup.cfg"

- name: Install requirements
run: |
pip install -U pip
pip install -r requirements/github-actions.txt
- name: Cache tox dir
id: cache-tox
uses: actions/cache@v3
with:
path: .tox
key: ${{ runner.os }}-${{ matrix.python-version }}-tox-${{ hashFiles('requirements/dev.txt') }}

- name: Run quality checks
env:
TOXENV: quality
run: tox

- name: Run documentation checks
env:
TOXENV: docs
run: tox

- name: Run ${{ matrix.django-version }} tests
env:
TOXENV: ${{ matrix.django-version }}
run: tox

- name: Upload coverage report
if: ${{ matrix.python-version == '3.8' }}
run: codecov

- name: Deploy to PyPi
env:
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
TWINE_NON_INTERACTIVE: "true"
if: ${{ github.event_name == 'release' && matrix.python-version == '3.8' }}
run: |
python -m build -n -w -s
twine upload --verbose dist/*
62 changes: 62 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
name: CodeQL

on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: 28 8 * * 0

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [python]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
34 changes: 0 additions & 34 deletions .travis.yml

This file was deleted.

3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Gabor Boros <[email protected]>
J. Cliff Dyer <[email protected]>
Michael Cornwell <[email protected]>
Jillian Vogel <[email protected]>
Michael Cornwell <[email protected]>
Paulo Viadanna <[email protected]>
Sofiane Bebert <[email protected]>
10 changes: 9 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ Change Log
Unreleased
~~~~~~~~~~

[4.0.0] - 2022-06-17
~~~~~~~~~~~~~~~~~~~~

* Add Maple support.
* Drop support for Python 2.
* Drop support for Django 2.X
* Drop support for Django 2.X.
* Replace Travis CI with GitHub Actions.
* Fix docs quality checks.
* Fix pylint quality checks.
* Fix the build & release pipeline.

[3.2.0] - 2021-11-26
~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ upgrade: ## update the requirements/*.txt files with the latest packages satisfy
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/test.txt requirements/test.in
pip-compile --upgrade -o requirements/travis.txt requirements/travis.in
pip-compile --upgrade -o requirements/github-actions.txt requirements/github-actions.in
# Let tox control the Django version for tests
sed '/^django==/d' requirements/test.txt > requirements/test.tmp
mv requirements/test.tmp requirements/test.txt
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ How To Contribute

Contributions are very welcome.

Please read `How To Contribute <https://github.com/edx/edx-platform/blob/master/CONTRIBUTING.rst>`_ for details.
Please read our `Contributing Guideline <https://github.com/edx/edx-platform/blob/master/CONTRIBUTING.rst>`_ for details.

Reporting Security Issues
-------------------------
Expand Down
3 changes: 2 additions & 1 deletion completion_aggregator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
an app that aggregates block level completion data for different block types for Open edX..
An app that aggregates block level completion data for different block types for Open edX.
"""
# pylint: disable=django-not-configured

from __future__ import absolute_import, unicode_literals

Expand Down
10 changes: 5 additions & 5 deletions completion_aggregator/api/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ..models import Aggregator
from ..serializers import course_completion_serializer_factory, is_aggregation_name

User = get_user_model() # pylint: disable=invalid-name
User = get_user_model()


class UserEnrollments:
Expand Down Expand Up @@ -91,8 +91,8 @@ def get_authenticators(self): # pragma: no cover
Allow users authenticated via OAuth2 or normal session authentication.
"""
try:
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser
from openedx.core.lib.api.authentication import (OAuth2AuthenticationAllowInactiveUser,
SessionAuthenticationAllowInactiveUser)
except ImportError:
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser

Expand Down Expand Up @@ -144,8 +144,8 @@ def user(self):
if self.request.user.is_staff:
try:
user = User.objects.get(username=requested_username)
except User.DoesNotExist:
raise NotFound()
except User.DoesNotExist as exc:
raise NotFound() from exc
else:
if self.request.user.username.lower() == requested_username.lower():
user = self.request.user
Expand Down
4 changes: 2 additions & 2 deletions completion_aggregator/api/v0/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def get(self, request):
requested_fields=self.get_requested_fields(),
many=True
)
return paginator.get_paginated_response(serializer.data)
return paginator.get_paginated_response(serializer.data) # pylint: disable=no-member


class CompletionDetailView(CompletionViewMixin, APIView):
Expand Down Expand Up @@ -358,7 +358,7 @@ def get(self, request, course_key):
instance=completions,
requested_fields=requested_fields,
)
return Response(serializer.data)
return Response(serializer.data) # pylint: disable=no-member


class CompletionBlockUpdateView(CompletionViewMixin, APIView):
Expand Down
33 changes: 13 additions & 20 deletions completion_aggregator/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import re
from collections import defaultdict

import waffle
import waffle # pylint: disable=invalid-django-waffle-import
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey, UsageKey
from rest_framework.exceptions import NotFound, ParseError
Expand Down Expand Up @@ -203,7 +203,7 @@ def get(self, request):
requested_fields=self.get_requested_fields(),
many=True
)
return paginator.get_paginated_response(serializer.data)
return paginator.get_paginated_response(serializer.data) # pylint: disable=no-member


class CompletionDetailView(CompletionViewMixin, APIView):
Expand Down Expand Up @@ -364,8 +364,8 @@ def _parse_aggregator(self, course_key, params=None):
"""
try:
course_key = CourseKey.from_string(course_key)
except InvalidKeyError:
raise NotFound("Invalid course key: '{}'.".format(course_key))
except InvalidKeyError as exc:
raise NotFound(f"Invalid course key: '{course_key}'.") from exc
paginator = self.pagination_class()
requested_fields = self.get_requested_fields()

Expand All @@ -381,10 +381,7 @@ def _parse_aggregator(self, course_key, params=None):
else:
if not UserEnrollments(self.user).is_enrolled(course_key):
# Return 404 if effective user does not have an active enrollment in the requested course
raise NotFound(
"User '{user}' does not have an active enrollment in course '{course_key}'."
.format(user=self.user, course_key=course_key)
)
raise NotFound(f"User '{self.user}' does not have an active enrollment in course '{course_key}'.")
is_stale = StaleCompletion.objects.filter(
username=self.user.username,
course_key=course_key,
Expand All @@ -404,8 +401,8 @@ def _parse_aggregator(self, course_key, params=None):
if root_block:
try:
root_block = UsageKey.from_string(root_block).map_into_course(course_key)
except InvalidKeyError:
raise NotFound("Invalid block key: '{}'.".format(root_block))
except InvalidKeyError as exc:
raise NotFound(f"Invalid block key: '{root_block}'.") from exc

if is_stale and waffle.flag_is_active(self.request, WAFFLE_AGGREGATE_STALE_FROM_SCRATCH):
aggregator_queryset = []
Expand Down Expand Up @@ -434,7 +431,7 @@ def _parse_aggregator(self, course_key, params=None):
requested_fields=requested_fields,
many=True
)
return paginator.get_paginated_response(serializer.data)
return paginator.get_paginated_response(serializer.data) # pylint: disable=no-member

def get(self, request, course_key):
"""
Expand Down Expand Up @@ -539,12 +536,8 @@ def _parse_cohort_filter(self, cohort_filter):
if cohort_filter is not None:
try:
cohort_filter = int(cohort_filter)
except TypeError:
raise ParseError(
'could not parse cohort_filter={!r} as an integer'.format(
cohort_filter,
)
)
except TypeError as exc:
raise ParseError(f'could not parse cohort_filter={cohort_filter!r} as an integer') from exc
return cohort_filter

def get(self, request, course_key):
Expand All @@ -553,8 +546,8 @@ def get(self, request, course_key):
"""
try:
course_key = CourseKey.from_string(course_key)
except InvalidKeyError:
raise NotFound("Invalid course key: '{}'.".format(course_key))
except InvalidKeyError as exc:
raise NotFound(f"Invalid course key: '{course_key}'.") from exc
requested_fields = self.get_requested_fields()
roles_to_exclude = self.request.query_params.get('exclude_roles', '').split(',')
cohort_filter = self._parse_cohort_filter(
Expand All @@ -581,4 +574,4 @@ def get(self, request, course_key):
requested_fields=requested_fields,
)

return JsonResponse({'results': [serializer.data]}, status=200)
return JsonResponse({'results': [serializer.data]}, status=200) # pylint: disable=no-member
8 changes: 5 additions & 3 deletions completion_aggregator/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def get_modulestore():
"""
Return an instance of the modulestore.
"""
from xmodule.modulestore.django import modulestore # pylint: disable=import-error
from xmodule.modulestore.django import modulestore # pylint: disable=import-error
return modulestore()


Expand All @@ -65,8 +65,10 @@ def init_course_blocks(user, root_block_key):
.block_type
"""
# pragma: no-cover
from lms.djangoapps.course_blocks.api import get_course_block_access_transformers, get_course_blocks # pylint: disable=import-error
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers # pylint: disable=import-error
# pylint: disable=import-error
from lms.djangoapps.course_blocks.api import get_course_block_access_transformers, get_course_blocks
# pylint: disable=import-error
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers

transformers = BlockStructureTransformers(
get_course_block_access_transformers(user) + [AggregatorAnnotationTransformer()]
Expand Down
Loading

0 comments on commit f09b732

Please sign in to comment.