From 82238c865c24a793fc638a9a861025d8c935cd62 Mon Sep 17 00:00:00 2001 From: Zachary Spar <41600414+zachspar@users.noreply.github.com> Date: Tue, 5 Dec 2023 20:37:25 -0500 Subject: [PATCH] Test & Deploy Automation (#4) * gh workflow * include tox in test deps * update ci * tweak ci env vars * tweak creds path * tweak ci * add strategy * fix ci bug * new lint job * update black * update black args * add Build-Deploy job to ci --- .github/workflows/test_build_deploy.yml | 69 +++++++++++++++++++++++++ pyproject.toml | 1 + sample_app.py | 25 ++++++++- tests/views/test_create_api_view.py | 2 +- tests/views/test_delete_api_view.py | 2 +- tests/views/test_retrieve_api_view.py | 2 +- tests/views/test_update_api_view.py | 2 +- tox.ini | 6 +-- 8 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/test_build_deploy.yml diff --git a/.github/workflows/test_build_deploy.yml b/.github/workflows/test_build_deploy.yml new file mode 100644 index 0000000..32cbfc2 --- /dev/null +++ b/.github/workflows/test_build_deploy.yml @@ -0,0 +1,69 @@ +name: Test, Build & Deploy FireFrame +on: + push: + branches: + - main + pull_request: + branches: + - main +env: + PROJECT_ID: ${{ secrets.FIREBASE_TEST_PROJECT_ID }} +jobs: + Lint: + runs-on: ubuntu-latest + steps: + - uses: 'actions/checkout@v4' + - uses: 'psf/black@stable' + with: + version: '23.11.0' + src: './' + options: '--line-length 120 --check' + Test: + needs: Lint + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11'] + steps: + - uses: 'actions/checkout@v4' + - uses: 'google-github-actions/auth@v2' + with: + credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' + - run: | + gcloud config set project $PROJECT_ID + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -e .[test] + - name: Run tests + env: + GOOGLE_CLOUD_PROJECT: ${{ secrets.FIREBASE_TEST_PROJECT_ID }} + run: | + export GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_GHA_CREDS_PATH + pytest -n 4 + Build-Deploy: + needs: [Lint, Test] + runs-on: ubuntu-latest + if: github.event_name == 'release' + steps: + - uses: 'actions/checkout@v4' + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m 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 }} diff --git a/pyproject.toml b/pyproject.toml index 301967d..f31e28e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dev = [ test = [ "httpx==0.25.2", "pytest==7.4.3", + "pytest-xdist==3.5.0", ] [project.scripts] diff --git a/sample_app.py b/sample_app.py index 5f23928..e4c5890 100644 --- a/sample_app.py +++ b/sample_app.py @@ -1,5 +1,6 @@ """A sample FireFrame API.""" from fireframe.core.api import FireFrameAPI +from fireframe.core.views import BaseListAPIView from fireframe.core.viewsets import crud_viewset from fireframe.core.models import Model from fireframe.core.serializers import ModelSerializer @@ -60,8 +61,30 @@ class Meta: fields = ["name", "price", "is_offer", "stock"] +class ItemListView(BaseListAPIView): + """ + Item list view. + + Inherits from FireFrame's BaseListAPIView. + """ + + serializer_class = ItemSerializer + + +class UserListView(BaseListAPIView): + """ + User list view. + + Inherits from FireFrame's BaseListAPIView. + """ + + serializer_class = UserSerializer + + app = FireFrameAPI(title="Sample FireFrame App", version="0.0.0") -# routes from mixin +# include routes from viewsets and views app.include_router(crud_viewset(UserSerializer), tags=["Users"], prefix="/users") +app.include_router(UserListView(), tags=["Users"], prefix="/users") app.include_router(crud_viewset(ItemSerializer), tags=["Items"], prefix="/items") +app.include_router(ItemListView(), tags=["Items"], prefix="/items") diff --git a/tests/views/test_create_api_view.py b/tests/views/test_create_api_view.py index 24e97e0..9909fb1 100644 --- a/tests/views/test_create_api_view.py +++ b/tests/views/test_create_api_view.py @@ -7,7 +7,7 @@ from fireframe.core.api import FireFrameAPI from fireframe.core.serializers import ModelSerializer from fireframe.core.views import BaseCreateAPIView -from ._fixtures import test_model_primitive_2 +from ._fixtures import test_model_primitive_2, test_thread class TestCreateAPIView: diff --git a/tests/views/test_delete_api_view.py b/tests/views/test_delete_api_view.py index f844b84..19afb9e 100644 --- a/tests/views/test_delete_api_view.py +++ b/tests/views/test_delete_api_view.py @@ -8,7 +8,7 @@ from fireframe.core.api import FireFrameAPI from fireframe.core.serializers import ModelSerializer from fireframe.core.views import BaseDestroyAPIView -from ._fixtures import test_model_primitive_1 +from ._fixtures import test_model_primitive_1, test_thread class TestDestroyAPIView: diff --git a/tests/views/test_retrieve_api_view.py b/tests/views/test_retrieve_api_view.py index cafbcab..8c642fd 100644 --- a/tests/views/test_retrieve_api_view.py +++ b/tests/views/test_retrieve_api_view.py @@ -7,7 +7,7 @@ from fireframe.core.api import FireFrameAPI from fireframe.core.serializers import ModelSerializer from fireframe.core.views import BaseRetrieveAPIView -from ._fixtures import test_model_primitive_1 +from ._fixtures import test_model_primitive_1, test_thread class TestRetrieveAPIView: diff --git a/tests/views/test_update_api_view.py b/tests/views/test_update_api_view.py index 2421f35..5f5c653 100644 --- a/tests/views/test_update_api_view.py +++ b/tests/views/test_update_api_view.py @@ -6,7 +6,7 @@ from fireframe.core.api import FireFrameAPI from fireframe.core.serializers import ModelSerializer from fireframe.core.views import BaseUpdateAPIView -from ._fixtures import test_model_primitive_1 +from ._fixtures import test_model_primitive_1, test_thread class TestUpdateAPIView: diff --git a/tox.ini b/tox.ini index a7a98a8..5c8889d 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,6 @@ envlist = py38,py39,py310,py311 [testenv] -deps = pytest # PYPI package providing pytest -extras = test # Install test dependencies -commands = pytest {posargs} # substitute with tox' positional arguments +deps = pytest # PYPI package providing pytest +extras = test # Install test dependencies +commands = pytest -n 4 {posargs} # Substitute with tox positional arguments