| name | django-verification |
| description | Verification loop for Django projects: migrations, linting, tests with coverage, security scans, and deployment readiness checks before release or PR. |
Django æ€èšŒã«ãŒã
PRåã倧ããªå€æŽåŸããããã€åã«å®è¡ããŠãDjangoã¢ããªã±ãŒã·ã§ã³ã®å質ãšã»ãã¥ãªãã£ã確ä¿ããŸãã
ãã§ãŒãº1: ç°å¢ãã§ãã¯
python --version
which python
pip list --outdated
python -c "import os; import environ; print('DJANGO_SECRET_KEY set' if os.environ.get('DJANGO_SECRET_KEY') else 'MISSING: DJANGO_SECRET_KEY')"
ç°å¢ã誀ã£ãŠæ§æãããŠããå Žåã¯ã忢ããŠä¿®æ£ããŸãã
ãã§ãŒãº2: ã³ãŒãå質ãšãã©ãŒããã
mypy . --config-file pyproject.toml
ruff check . --fix
black . --check
black .
isort . --check-only
isort .
python manage.py check --deploy
äžè¬çãªåé¡:
- ãããªãã¯é¢æ°ã®åãã³ãã®æ¬ èœ
- PEP 8ãã©ãŒãããéå
- ãœãŒããããŠããªãã€ã³ããŒã
- æ¬çªæ§æã«æ®ããããããã°èšå®
ãã§ãŒãº3: ãã€ã°ã¬ãŒã·ã§ã³
python manage.py showmigrations
python manage.py makemigrations --check
python manage.py migrate --plan
python manage.py migrate
python manage.py makemigrations --merge
ã¬ããŒã:
- ä¿çäžã®ãã€ã°ã¬ãŒã·ã§ã³æ°
- ãã€ã°ã¬ãŒã·ã§ã³ã®ç«¶å
- ãã€ã°ã¬ãŒã·ã§ã³ã®ãªãã¢ãã«ã®å€æŽ
ãã§ãŒãº4: ãã¹ã + ã«ãã¬ããž
pytest --cov=apps --cov-report=html --cov-report=term-missing --reuse-db
pytest apps/users/tests/
pytest -m "not slow"
pytest -m integration
open htmlcov/index.html
ã¬ããŒã:
- åèšãã¹ã: XæåãY倱æãZã¹ããã
- å
šäœã«ãã¬ããž: XX%
- ã¢ããªããšã®ã«ãã¬ããžå
èš³
ã«ãã¬ããžç®æš:
| ã³ã³ããŒãã³ã | ç®æš |
|---|
| ã¢ãã« | 90%+ |
| ã·ãªã¢ã©ã€ã¶ãŒ | 85%+ |
| ãã¥ãŒ | 80%+ |
| ãµãŒãã¹ | 90%+ |
| å
šäœ | 80%+ |
ãã§ãŒãº5: ã»ãã¥ãªãã£ã¹ãã£ã³
pip-audit
safety check --full-report
python manage.py check --deploy
bandit -r . -f json -o bandit-report.json
gitleaks detect --source . --verbose
python -c "from django.core.exceptions import ImproperlyConfigured; from django.conf import settings; settings.DEBUG"
ã¬ããŒã:
- èŠã€ãã£ãè匱ãªäŸåé¢ä¿
- ã»ãã¥ãªãã£æ§æã®åé¡
- ããŒãã³ãŒããããã·ãŒã¯ã¬ãããæ€åº
- DEBUGã¢ãŒãã®ã¹ããŒã¿ã¹ïŒæ¬çªç°å¢ã§ã¯Falseã§ããã¹ãïŒ
ãã§ãŒãº6: Django管çã³ãã³ã
python manage.py check
python manage.py collectstatic --noinput --clear
echo "from apps.users.models import User; User.objects.create_superuser('admin@example.com', 'admin')" | python manage.py shell
python manage.py check --database default
python -c "from django.core.cache import cache; cache.set('test', 'value', 10); print(cache.get('test'))"
ãã§ãŒãº7: ããã©ãŒãã³ã¹ãã§ãã¯
django-admin debugsqlshell
python manage.py shell << EOF
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT table_name, index_name FROM information_schema.statistics WHERE table_schema = 'public'")
print(cursor.fetchall())
EOF
ã¬ããŒã:
- ããŒãžãããã®ã¯ãšãªæ°ïŒå
žåçãªããŒãžã§50æªæºã§ããã¹ãïŒ
- æ¬ èœããŠããããŒã¿ããŒã¹ã€ã³ããã¯ã¹
- éè€ã¯ãšãªãæ€åº
ãã§ãŒãº8: éçã¢ã»ãã
npm audit
npm audit fix
npm run build
ls -la staticfiles/
python manage.py findstatic css/style.css
ãã§ãŒãº9: æ§æã¬ãã¥ãŒ
python manage.py shell << EOF
from django.conf import settings
import os
checks = {
'DEBUG is False': not settings.DEBUG,
'SECRET_KEY set': bool(settings.SECRET_KEY and len(settings.SECRET_KEY) > 30),
'ALLOWED_HOSTS set': len(settings.ALLOWED_HOSTS) > 0,
'HTTPS enabled': getattr(settings, 'SECURE_SSL_REDIRECT', False),
'HSTS enabled': getattr(settings, 'SECURE_HSTS_SECONDS', 0) > 0,
'Database configured': settings.DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3',
}
for check, result in checks.items():
status = 'â' if result else 'â'
print(f"{status} {check}")
EOF
ãã§ãŒãº10: ãã°èšå®
python manage.py shell << EOF
import logging
logger = logging.getLogger('django')
logger.warning('Test warning message')
logger.error('Test error message')
EOF
tail -f /var/log/django/django.log
ãã§ãŒãº11: APIããã¥ã¡ã³ãïŒDRFã®å ŽåïŒ
python manage.py generateschema --format openapi-json > schema.json
python -c "import json; json.load(open('schema.json'))"
ãã§ãŒãº12: å·®åã¬ãã¥ãŒ
git diff --stat
git diff
git diff --name-only
git diff | grep -i "todo\|fixme\|hack\|xxx"
git diff | grep "print("
git diff | grep "DEBUG = True"
git diff | grep "import pdb"
ãã§ãã¯ãªã¹ã:
- ãããã°ã¹ããŒãã¡ã³ãïŒprintãpdbãbreakpoint()ïŒãªã
- éèŠãªã³ãŒãã«TODO/FIXMEã³ã¡ã³ããªã
- ããŒãã³ãŒããããã·ãŒã¯ã¬ãããè³æ Œæ
å ±ãªã
- ã¢ãã«å€æŽã®ããã®ããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ãå«ãŸããŠãã
- æ§æã®å€æŽãææžåãããŠãã
- å€éšåŒã³åºãã®ãšã©ãŒãã³ããªã³ã°ãååš
- å¿
èŠãªå Žæã§ãã©ã³ã¶ã¯ã·ã§ã³ç®¡ç
åºåãã³ãã¬ãŒã
DJANGO æ€èšŒã¬ããŒã
==========================
ãã§ãŒãº1: ç°å¢ãã§ãã¯
â Python 3.11.5
â ä»®æ³ç°å¢ãã¢ã¯ãã£ã
â ãã¹ãŠã®ç°å¢å€æ°ãèšå®æžã¿
ãã§ãŒãº2: ã³ãŒãå質
â mypy: åãšã©ãŒãªã
â ruff: 3ã€ã®åé¡ãèŠã€ãããŸããïŒèªåä¿®æ£æžã¿ïŒ
â black: ãã©ãŒãããåé¡ãªã
â isort: ã€ã³ããŒããé©åã«ãœãŒãæžã¿
â manage.py check: åé¡ãªã
ãã§ãŒãº3: ãã€ã°ã¬ãŒã·ã§ã³
â æªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ãªã
â ãã€ã°ã¬ãŒã·ã§ã³ã®ç«¶åãªã
â ãã¹ãŠã®ã¢ãã«ã«ãã€ã°ã¬ãŒã·ã§ã³ãã
ãã§ãŒãº4: ãã¹ã + ã«ãã¬ããž
ãã¹ã: 247æåã0倱æã5ã¹ããã
ã«ãã¬ããž:
å
šäœ: 87%
users: 92%
products: 89%
orders: 85%
payments: 91%
ãã§ãŒãº5: ã»ãã¥ãªãã£ã¹ãã£ã³
â pip-audit: 2ã€ã®è匱æ§ãèŠã€ãããŸããïŒä¿®æ£ãå¿
èŠïŒ
â safety check: åé¡ãªã
â bandit: ã»ãã¥ãªãã£åé¡ãªã
â ã·ãŒã¯ã¬ãããæ€åºããã
â DEBUG = False
ãã§ãŒãº6: Djangoã³ãã³ã
â collectstatic å®äº
â ããŒã¿ããŒã¹æŽåæ§OK
â ãã£ãã·ã¥ããã¯ãšã³ãå°éå¯èœ
ãã§ãŒãº7: ããã©ãŒãã³ã¹
â N+1ã¯ãšãªãæ€åºããã
â ããŒã¿ããŒã¹ã€ã³ããã¯ã¹ãæ§ææžã¿
â ã¯ãšãªæ°ã蚱容ç¯å²
ãã§ãŒãº8: éçã¢ã»ãã
â npm audit: è匱æ§ãªã
â ã¢ã»ãããæ£åžžã«ãã«ã
â éçãã¡ã€ã«ãåéæžã¿
ãã§ãŒãº9: æ§æ
â DEBUG = False
â SECRET_KEY æ§ææžã¿
â ALLOWED_HOSTS èšå®æžã¿
â HTTPS æå¹
â HSTS æå¹
â ããŒã¿ããŒã¹æ§ææžã¿
ãã§ãŒãº10: ãã°
â ãã°ãæ§ææžã¿
â ãã°ãã¡ã€ã«ãæžã蟌ã¿å¯èœ
ãã§ãŒãº11: APIããã¥ã¡ã³ã
â ã¹ããŒãçææžã¿
â Swagger UIã¢ã¯ã»ã¹å¯èœ
ãã§ãŒãº12: å·®åã¬ãã¥ãŒ
倿Žããããã¡ã€ã«: 12
+450ã-120è¡
â ãããã°ã¹ããŒãã¡ã³ããªã
â ããŒãã³ãŒããããã·ãŒã¯ã¬ãããªã
â ãã€ã°ã¬ãŒã·ã§ã³ãå«ãŸãã
æšå¥š: WARNING: ãããã€åã«pip-auditã®è匱æ§ãä¿®æ£ããŠãã ãã
次ã®ã¹ããã:
1. è匱ãªäŸåé¢ä¿ãæŽæ°
2. ã»ãã¥ãªãã£ã¹ãã£ã³ãåå®è¡
3. æçµãã¹ãã®ããã«ã¹ããŒãžã³ã°ã«ãããã€
ãããã€åãã§ãã¯ãªã¹ã
ç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³
GitHub Actionsã®äŸ
name: Django Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install ruff black mypy pytest pytest-django pytest-cov bandit safety pip-audit
- name: Code quality checks
run: |
ruff check .
black . --check
isort . --check-only
mypy .
- name: Security scan
run: |
bandit -r . -f json -o bandit-report.json
safety check --full-report
pip-audit
- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test
DJANGO_SECRET_KEY: test-secret-key
run: |
pytest --cov=apps --cov-report=xml --cov-report=term-missing
- name: Upload coverage
uses: codecov/codecov-action@v3
ã¯ã€ãã¯ãªãã¡ã¬ã³ã¹
| ãã§ã㯠| ã³ãã³ã |
|---|
| ç°å¢ | python --version |
| åãã§ã㯠| mypy . |
| ãªã³ãã£ã³ã° | ruff check . |
| ãã©ãŒããã | black . --check |
| ãã€ã°ã¬ãŒã·ã§ã³ | python manage.py makemigrations --check |
| ãã¹ã | pytest --cov=apps |
| ã»ãã¥ãªã㣠| pip-audit && bandit -r . |
| Djangoãã§ã㯠| python manage.py check --deploy |
| éçãã¡ã€ã«åé | python manage.py collectstatic --noinput |
| å·®åçµ±èš | git diff --stat |
èŠããŠãããŠãã ãã: èªååãããæ€èšŒã¯äžè¬çãªåé¡ãææããŸãããæåã§ã®ã³ãŒãã¬ãã¥ãŒãšã¹ããŒãžã³ã°ç°å¢ã§ã®ãã¹ãã«ä»£ãããã®ã§ã¯ãããŸããã