From 11c66d8aa75000ebe49a13310c3e7f7fd3e776b3 Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:39:14 +0000 Subject: [PATCH 1/8] Update gitignore --- .gitignore | 106 ----------------------------------------------------- 1 file changed, 106 deletions(-) diff --git a/.gitignore b/.gitignore index 78ef8b3..298076f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,109 +1,3 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - - # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] From 20ba7ba8d0c77899fdf41be62a37cc03be61efde Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:40:35 +0000 Subject: [PATCH 2/8] Setup docker for development --- .dockerignore | 16 +++++++++++++ Dockerfile | 36 ++++++++++++++++++++++++++++++ docker-compose.yml | 53 ++++++++++++++++++++++++++++++++++++++++++++ requirements.dev.txt | 3 +++ requirements.txt | 3 +++ 5 files changed, 111 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 requirements.dev.txt create mode 100644 requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..77b2e5d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +# Git +.git +.gitignore + +# Docker +.docker + +# Python +b2b/__pycache__/ +b2b/*/__pycache__/ +b2b/*/*/__pycache__/ +b2b/*/*/*/__pycache__/ +b2b/*/*/*/*/__pycache__/ +.env/ +.venv/ +venv/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6386475 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM python:3.10-alpine3.17 +LABEL maintainer="snnbotchway" + +ENV PYTHONUNBUFFERED 1 + +COPY ./requirements.txt /tmp/requirements.txt +COPY ./requirements.dev.txt /tmp/requirements.dev.txt +COPY ./b2b /b2b +WORKDIR /b2b +EXPOSE 8000 + +ARG DEV=false +RUN python -m venv /py && \ + /py/bin/pip install --upgrade pip && \ + apk add --update --no-cache postgresql-client && \ + apk add --update --no-cache --virtual .tmp-build-deps \ + build-base postgresql-dev musl-dev zlib zlib-dev && \ + /py/bin/pip install wheel && \ + /py/bin/pip install -r /tmp/requirements.txt && \ + if [ $DEV = "true" ]; \ + then /py/bin/pip install -r /tmp/requirements.dev.txt ; \ + fi && \ + rm -rf /tmp && \ + apk del .tmp-build-deps && \ + adduser \ + --disabled-password \ + --no-create-home \ + django-user && \ + mkdir -p /vol/web/static && \ + chown -R django-user:django-user /vol && \ + chmod -R 755 /vol + + +ENV PATH="/py/bin:$PATH" + +# USER django-user diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..080b8aa --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +version: "3.9" + +services: + b2b: + build: + context: . + args: + - DEV=true + ports: + - "8000:8000" + volumes: + - ./b2b:/b2b + - dev-static-data:/vol/web + command: > + sh -c "python manage.py wait_for_db && + python manage.py migrate && + python manage.py runserver 0.0.0.0:8000" + environment: + - DEBUG=${DEBUG} + - DATABASE_URL=${DATABASE_URL} + - SECRET_KEY=changeme + - EMAIL_HOST=smtp4dev + - EMAIL_HOST_USER= + - EMAIL_HOST_PASSWORD= + - EMAIL_PORT=25 + - DEFAULT_FROM_EMAIL=from@snnbotchway.com + depends_on: + - db + - smtp4dev + + db: + image: postgres:13-alpine + ports: + - 6432:5432 + volumes: + - dev-db-data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=devdb + - POSTGRES_USER=devuser + - POSTGRES_PASSWORD=changeme + + smtp4dev: + image: rnwood/smtp4dev + ports: + - "3001:80" + - "2525:25" + volumes: + - smtp4dev-data:/smtp4dev + +volumes: + dev-db-data: + dev-static-data: + smtp4dev-data: diff --git a/requirements.dev.txt b/requirements.dev.txt new file mode 100644 index 0000000..be18457 --- /dev/null +++ b/requirements.dev.txt @@ -0,0 +1,3 @@ +black>=23.1.0,<23.2 +pre-commit>=3.1.1,<3.2 +pytest-django>=4.5.2,<4.6 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0eca5c7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Django>=4.1.7,<4.2 +django-environ>=0.10.0,<0.11 +psycopg2>=2.9.5,<2.10 From d0fdc54d993d66523926a88b93e0e2616519c80f Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:45:37 +0000 Subject: [PATCH 3/8] Setup django project --- b2b/b2b/__init__.py | 1 + b2b/b2b/asgi.py | 16 +++ b2b/b2b/settings.py | 134 ++++++++++++++++++++ b2b/b2b/urls.py | 21 +++ b2b/b2b/wsgi.py | 16 +++ b2b/core/__init__.py | 1 + b2b/core/apps.py | 9 ++ b2b/core/management/commands/__init__.py | 5 + b2b/core/management/commands/wait_for_db.py | 24 ++++ b2b/core/migrations/0001_initial.py | 131 +++++++++++++++++++ b2b/core/migrations/__init__.py | 0 b2b/core/models.py | 8 ++ b2b/core/tests/__init__.py | 1 + b2b/core/tests/test_commands.py | 31 +++++ b2b/manage.py | 22 ++++ b2b/pytest.ini | 2 + 16 files changed, 422 insertions(+) create mode 100644 b2b/b2b/__init__.py create mode 100644 b2b/b2b/asgi.py create mode 100644 b2b/b2b/settings.py create mode 100644 b2b/b2b/urls.py create mode 100644 b2b/b2b/wsgi.py create mode 100644 b2b/core/__init__.py create mode 100644 b2b/core/apps.py create mode 100644 b2b/core/management/commands/__init__.py create mode 100644 b2b/core/management/commands/wait_for_db.py create mode 100644 b2b/core/migrations/0001_initial.py create mode 100644 b2b/core/migrations/__init__.py create mode 100644 b2b/core/models.py create mode 100644 b2b/core/tests/__init__.py create mode 100644 b2b/core/tests/test_commands.py create mode 100755 b2b/manage.py create mode 100644 b2b/pytest.ini diff --git a/b2b/b2b/__init__.py b/b2b/b2b/__init__.py new file mode 100644 index 0000000..59a52fe --- /dev/null +++ b/b2b/b2b/__init__.py @@ -0,0 +1 @@ +"""Configuration for the b2b project.""" diff --git a/b2b/b2b/asgi.py b/b2b/b2b/asgi.py new file mode 100644 index 0000000..4a752da --- /dev/null +++ b/b2b/b2b/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for b2b project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "b2b.settings") + +application = get_asgi_application() diff --git a/b2b/b2b/settings.py b/b2b/b2b/settings.py new file mode 100644 index 0000000..8ac00a7 --- /dev/null +++ b/b2b/b2b/settings.py @@ -0,0 +1,134 @@ +""" +Django settings for b2b project. + +Generated by 'django-admin startproject' using Django 4.1.7. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +import os +from typing import List + +import environ + +env = environ.Env( + # set casting, default value + DEBUG=(bool, False) +) + +# Set the project base directory +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Take environment variables from .env file +environ.Env.read_env(os.path.join(BASE_DIR, ".env")) + +# False if not in os.environ because of casting above +DEBUG = env("DEBUG") + +# Raises Django's ImproperlyConfigured +# exception if SECRET_KEY not in os.environ +SECRET_KEY = env("SECRET_KEY") + +ALLOWED_HOSTS: List[str] = [] + +# Application definition + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + # Local apps + "core.apps.CoreConfig", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "b2b.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "b2b.wsgi.application" + + +# Parse database connection url strings +# like psql://user:pass@127.0.0.1:8458/db +DATABASES = { + # read os.environ['DATABASE_URL'] and raises + # ImproperlyConfigured exception if not found + # + # The db() method is an alias for db_url(). + "default": env.db(), +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = "static/" + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +AUTH_USER_MODEL = "core.User" diff --git a/b2b/b2b/urls.py b/b2b/b2b/urls.py new file mode 100644 index 0000000..ddde8d3 --- /dev/null +++ b/b2b/b2b/urls.py @@ -0,0 +1,21 @@ +"""b2b URL Configuration. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path("admin/", admin.site.urls), +] diff --git a/b2b/b2b/wsgi.py b/b2b/b2b/wsgi.py new file mode 100644 index 0000000..e320364 --- /dev/null +++ b/b2b/b2b/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for b2b project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "b2b.settings") + +application = get_wsgi_application() diff --git a/b2b/core/__init__.py b/b2b/core/__init__.py new file mode 100644 index 0000000..d5ec2ab --- /dev/null +++ b/b2b/core/__init__.py @@ -0,0 +1 @@ +"""The core app.""" diff --git a/b2b/core/apps.py b/b2b/core/apps.py new file mode 100644 index 0000000..e0eb965 --- /dev/null +++ b/b2b/core/apps.py @@ -0,0 +1,9 @@ +"""Core app configuration.""" +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + """Core app config class.""" + + default_auto_field = "django.db.models.BigAutoField" + name = "core" diff --git a/b2b/core/management/commands/__init__.py b/b2b/core/management/commands/__init__.py new file mode 100644 index 0000000..552da4c --- /dev/null +++ b/b2b/core/management/commands/__init__.py @@ -0,0 +1,5 @@ +""" +This package contains custom management commands for the API. + +The management commands extend the functionality of Django's built-in management tools. +""" diff --git a/b2b/core/management/commands/wait_for_db.py b/b2b/core/management/commands/wait_for_db.py new file mode 100644 index 0000000..33799d8 --- /dev/null +++ b/b2b/core/management/commands/wait_for_db.py @@ -0,0 +1,24 @@ +"""Wait for database availability.""" +import time + +from django.core.management.base import BaseCommand +from django.db.utils import OperationalError +from psycopg2 import OperationalError as Psycopg2OpError + + +class Command(BaseCommand): + """Command to make Django wait for the database.""" + + def handle(self, *args, **options): + """Entry point for command.""" + self.stdout.write("Waiting for database...") + db_ready = False + while not db_ready: + try: + self.check(databases=["default"]) + db_ready = True + except (Psycopg2OpError, OperationalError): + self.stdout.write("Database unavailable, retrying...") + time.sleep(1) + + self.stdout.write(self.style.SUCCESS("Database connection SUCCESS!")) diff --git a/b2b/core/migrations/0001_initial.py b/b2b/core/migrations/0001_initial.py new file mode 100644 index 0000000..833e45b --- /dev/null +++ b/b2b/core/migrations/0001_initial.py @@ -0,0 +1,131 @@ +# Generated by Django 4.1.7 on 2023-03-11 10:27 + +import django.contrib.auth.models +import django.contrib.auth.validators +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ] + + operations = [ + migrations.CreateModel( + name="User", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={ + "unique": "A user with that username already exists." + }, + help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", + max_length=150, + unique=True, + validators=[ + django.contrib.auth.validators.UnicodeUsernameValidator() + ], + verbose_name="username", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=150, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), + ), + ( + "email", + models.EmailField( + blank=True, max_length=254, verbose_name="email address" + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), + ], + options={ + "verbose_name": "user", + "verbose_name_plural": "users", + "abstract": False, + }, + managers=[ + ("objects", django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/b2b/core/migrations/__init__.py b/b2b/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/b2b/core/models.py b/b2b/core/models.py new file mode 100644 index 0000000..ae77339 --- /dev/null +++ b/b2b/core/models.py @@ -0,0 +1,8 @@ +"""Models for the core app.""" +from django.contrib.auth.models import AbstractUser + + +class User(AbstractUser): + """User model definition.""" + + pass diff --git a/b2b/core/tests/__init__.py b/b2b/core/tests/__init__.py new file mode 100644 index 0000000..22562a6 --- /dev/null +++ b/b2b/core/tests/__init__.py @@ -0,0 +1 @@ +"""Core app tests.""" diff --git a/b2b/core/tests/test_commands.py b/b2b/core/tests/test_commands.py new file mode 100644 index 0000000..c4d93a1 --- /dev/null +++ b/b2b/core/tests/test_commands.py @@ -0,0 +1,31 @@ +from unittest.mock import patch + +from django.core.management import call_command +from django.db.utils import OperationalError +from django.test import SimpleTestCase +from psycopg2 import OperationalError as Psycopg2Error + + +@patch("core.management.commands.wait_for_db.Command.check") +class CommandTests(SimpleTestCase): + """Test commands.""" + + def test_wait_for_db_ready(self, patched_check): + """Test waiting for database if database ready.""" + patched_check.return_value = True + + call_command("wait_for_db") + + patched_check.assert_called_once_with(databases=["default"]) + + @patch("time.sleep") + def test_wait_for_db_delay(self, patched_sleep, patched_check): + """Test waiting for database when getting operational error.""" + patched_check.side_effect = ( + [Psycopg2Error] * 2 + [OperationalError] * 3 + [True] + ) + + call_command("wait_for_db") + + self.assertEqual(patched_check.call_count, 6) + patched_check.assert_called_with(databases=["default"]) diff --git a/b2b/manage.py b/b2b/manage.py new file mode 100755 index 0000000..956a8c9 --- /dev/null +++ b/b2b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "b2b.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() diff --git a/b2b/pytest.ini b/b2b/pytest.ini new file mode 100644 index 0000000..0d0c9d3 --- /dev/null +++ b/b2b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE = b2b.settings From 3e1089f3f66e5453c9bbc95f3e55ad48eb880708 Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:46:38 +0000 Subject: [PATCH 4/8] Add README.md end of line --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4bfb7ab..83a65e7 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# b2b-feedback \ No newline at end of file +# b2b-feedback From 6b9f1a30029da1b224157b2fa66a5db93618e02b Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:47:03 +0000 Subject: [PATCH 5/8] Add sample .env --- .env.sample | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .env.sample diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..cb508c1 --- /dev/null +++ b/.env.sample @@ -0,0 +1,8 @@ +# SECURITY WARNING: don't run with the debug turned on in production! +DEBUG=True + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY=secret + +# database connection url string +DATABASE_URL=postgresql://username:password@host:port/database From 11e85ee4bc73f3002653cb8f1697f6ea3ab06373 Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:47:32 +0000 Subject: [PATCH 6/8] Add github actions checks --- .github/workflows/checks.yml | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/checks.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..89989fc --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,50 @@ +--- +name: Checks + +on: + push: + branches: ["main", "develop"] + pull_request: + branches: ["main", "develop"] + +jobs: + check-hooks: + name: Pre-commit hooks + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install pre-commit + run: pip install pre-commit + + - name: Install pre-commit hooks + run: pre-commit install + + - name: Run pre-commit + run: pre-commit run --all-files + + test-and-migrations: + name: Tests and migrations + runs-on: ubuntu-latest + needs: check-hooks + env: + DEBUG: True + SECRET_KEY: change_me + + steps: + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Checkout + uses: actions/checkout@v3 + + - name: Test + run: docker compose run --rm b2b sh -c "python manage.py wait_for_db && pytest" + + - name: Uncreated migrations + run: docker compose run --rm b2b sh -c "python manage.py makemigrations --check --dry-run" From 3aa0a439483c3ecc81ef3df60067264dc7dafcf1 Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:47:47 +0000 Subject: [PATCH 7/8] Add pre-commit hooks --- .pre-commit-config.yaml | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..fe1f2f0 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,48 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - id: fix-byte-order-marker + + - repo: https://github.com/ambv/black + rev: 23.1.0 + hooks: + - id: black + + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + name: isort (python) + args: ["--profile", "black"] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.991 + hooks: + - id: mypy + name: Run type checks + args: + [ + "--ignore-missing-imports", + "--install-types", + "--non-interactive", + "--follow-imports=skip", + ] + exclude: (migrations|djoser) + + - repo: https://github.com/pycqa/pydocstyle + rev: 6.3.0 + hooks: + - id: pydocstyle + args: ["--add-ignore=D203"] + exclude: (migrations|djoser) + + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + exclude: (migrations|__pycache__|manage.py|settings.py) + args: [--max-line-length=88] From 54dd02e76d2873c7b648d9a53e0f779b31012183 Mon Sep 17 00:00:00 2001 From: snnbotchway Date: Sat, 11 Mar 2023 10:48:34 +0000 Subject: [PATCH 8/8] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83a65e7..7ce6257 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# b2b-feedback +# b2b-backend