Skip to content

Commit

Permalink
rebuild project structure from scratch / move to poetry (#567)
Browse files Browse the repository at this point in the history
  • Loading branch information
hnthh authored Apr 18, 2024
1 parent a67e49f commit b034c74
Show file tree
Hide file tree
Showing 135 changed files with 1,293 additions and 1,073 deletions.
30 changes: 30 additions & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: build

runs:
using: composite

steps:
- name: install poetry
uses: snok/install-poetry@v1
with:
version: 1.8.2

- name: install python
id: setup-python
uses: actions/setup-python@v5
with:
cache: poetry
python-version-file: pyproject.toml

- name: make sure poetry lockfile is up to date
run: poetry check --lock
shell: bash

- name: save python version to the env
run: echo "python-version=${{ steps.setup-python.outputs.python-version }}" >> $GITHUB_ENV
shell: bash

- name: install deps
if: steps.setup-python.outputs.cache-hit != true
run: poetry install --no-interaction --no-root
shell: bash
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/{{cookiecutter.project_slug}}"
directory: "/{{ cookiecutter.name }}"
schedule:
interval: daily
time: "02:00"
Expand Down
101 changes: 87 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,97 @@
---
name: CI
on: push

on:
push:
branches:
- master
pull_request:

jobs:
build:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: checkout
uses: actions/checkout@v4

- name: Install gettext for correct manage.py compilemessages
run: sudo apt-get update && sudo apt-get --no-install-recommends install -y locales-all gettext
- name: build
uses: ./.github/actions/build

- uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'
- name: lint
run: make lint

- name: Install cookiecutter
run: pip install cookiecutter
bootstrap:
needs: lint
runs-on: ubuntu-latest
services:
postgres:
env:
POSTGRES_PASSWORD: secret
image: postgres:16.2-alpine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-retries 5
--health-timeout 5s
ports:
- 5432:5432

steps:
- name: checkout
uses: actions/checkout@v4

- name: Bootstrap the project
run: make test
- name: build
uses: ./.github/actions/build

- name: bootstrap
run: make bootstrap
env:
DATABASE_URL: postgres://postgres:secret@localhost:5432/postgres

- name: lint generated project (and its template)
run: poetry install && make lint
working-directory: testproject

build-docker-image:
needs: bootstrap
runs-on: ubuntu-latest
services:
postgres:
env:
POSTGRES_PASSWORD: secret
image: postgres:16.2-alpine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-retries 5
--health-timeout 5s
ports:
- 5432:5432

steps:
- name: checkout
uses: actions/checkout@v4

- name: build
uses: ./.github/actions/build

- name: bootstrap
run: make bootstrap
env:
DATABASE_URL: postgres://postgres:secret@localhost:5432/postgres

- name: setup qemu
uses: docker/setup-qemu-action@v2

- name: setup buildx
uses: docker/setup-buildx-action@v3

- name: make sure docker image is buildable
uses: docker/build-push-action@v5
with:
build-args: |
PYTHON_VERSION=${{ env.python-version }}
cache-from: type=gha
cache-to: type=gha,mode=max
context: testproject
push: false
12 changes: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
venv
testproject
.vscode
.git
.idea
.venv
.vscode

**/.DS_Store

{{ cookiecutter.name }}/poetry.lock

testproject
19 changes: 8 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
VENV=cd testproject/django/src && ../venv/bin/python
bootstrap:
rm -rf testproject

test: bootstrap
$(VENV) ./manage.py makemigrations --check
$(VENV) ./manage.py startapp test_app
poetry run cookiecutter --no-input ./

bootstrap:
rm -Rf testproject
mkdir -p testproject
cd testproject && cookiecutter --no-input ../
fmt:
poetry run toml-sort pyproject.toml

coverage:
$(VENV) -m pip install pytest-cov
$(VENV) -m pytest --cov-report=xml --cov=app --cov=users --cov=a12n --cov=sepulkas
lint:
poetry run toml-sort pyproject.toml --check
poetry run pymarkdown scan README.md
48 changes: 19 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,37 @@
# My personal (very) opinionated django template
# fands.dev django template

![Shields.io](https://img.shields.io/github/last-commit/fandsdev/django?style=flat-square) [![Maintainability](https://api.codeclimate.com/v1/badges/2b9800b10414a4ad2622/maintainability)](https://codeclimate.com/github/f213/django/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/2b9800b10414a4ad2622/test_coverage)](https://codeclimate.com/github/f213/django/test_coverage)
![Shields.io](https://img.shields.io/github/last-commit/fandsdev/django?style=flat-square)

![Easy peasy](https://user-images.githubusercontent.com/1592663/79918184-93bca100-8434-11ea-9902-0ff726a864a3.gif)


## What is in the box

* API-only django (checkout [this post](https://t.me/pmdaily/257) in Russian) based on Django REST Framework with JWT support
* [pip-tools](https://github.com/jazzband/pip-tools) with separate development-time dependencies
* Strict type checking with mypy, [django-stubs](https://github.com/typeddjango/django-stubs) and [djangorestframework-stubs](https://github.com/typeddjango/djangorestframework-stubs)
* flake8 with ton of plugins (contact me if you know more)
* [black](https://github.com/psf/black) as uncompromising code formatter
* Starter CI configuration on GitHub Actions
* pytest with useful stuff like freezegun, pytest-mock and super convinient [DRF test client](https://github.com/f213/django/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/src/app/tests/tests_health.py#L9)
* Custom [user model](https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#specifying-a-custom-user-model)
* [drf-spectacular](https://github.com/tfranzel/drf-spectacular) for API Schema generation
* [django-axes](https://github.com/jazzband/django-axes) for additional security
* [Whitenoise](http://whitenoise.evans.io) for effortless static files hosting
* cloudflare-ready with [django-ipware](https://github.com/un33k/django-ipware)
* API-only django (checkout [this post](https://t.me/pmdaily/257) in Russian) based on Django REST Framework with JWT support.
* [poetry](https://python-poetry.org) with separate development-time dependencies.
* Strict type checking with mypy, [django-stubs](https://github.com/typeddjango/django-stubs) and [djangorestframework-stubs](https://github.com/typeddjango/djangorestframework-stubs).
* tons of linters and formatters (contact me if something interesting not included, see `Makefile` `fmt`, `lint` commands).
* Starter CI configuration on GitHub Actions.
* `pytest` with useful stuff like `freezegun`, `pytest-mock` and super convinient [DRF test client](https://github.com/fandsdev/django/blob/master/%7B%7Bcookiecutter.name%7D%7D/src/app/tests_health.py#L9)
* Custom [user model](https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#specifying-a-custom-user-model).
* [drf-spectacular](https://github.com/tfranzel/drf-spectacular) for API Schema generation.
* [django-axes](https://github.com/jazzband/django-axes) for additional security.
* [Whitenoise](http://whitenoise.evans.io) for effortless static files hosting.
* cloudflare-ready with [django-ipware](https://github.com/un33k/django-ipware).
* Sentry. Set `SENTRY_DSN` env var if you need it.
* Postgres ready. Set `DATABASE_URL` env var to something like `DATABASE_URL=postgres://postgres@localhost:5432/postgres`

* Postgres.

## Optional next steps
You definetely should consider this steps after installation:
* Install [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) if you plan to grow beyond 500 unittests
* If you are into docker, check out this [docker-compose.yml](https://github.com/f213/django/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/docker-compose.yml) to run on your machine
## Installation

First, make sure you have `PostgreSQL` up and running (check the `{{ cookiecutter.name }}/src/app/.env.ci` `DATABASE_URL` and `{{ cookiecutter.name }}/docker-compose.yml` for configuration). After that:

## Installation
```bash
poetry install

```
$ pip install --upgrade cookiecutter
$ cookiecutter gh:fandsdev/django
poetry run cookiecutter gh:fandsdev/django
```

## FAQ

### I have got an error «'random_ascii_string' is undefined»

You should upgrade cookiecutter to the latest version: `pip install --upgrade cookiecutter`

### I wanna hack this!

Thank you so much! Check out our [build pipeline](https://github.com/fandsdev/django/blob/master/Makefile) and pick any free [issue](https://github.com/fandsdev/django/issues).
12 changes: 7 additions & 5 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"project_slug": "django",
"email": "",
"project_version": "0.0.0-dev",
"author": "Fedor Borshev",
"description": "",
"email": "[email protected]",
"name": "testproject",
"_copy_without_render": [
"*.py-tpl",
".github/workflows/ci.yml"
".github/actions/build/action.yml",
".github/workflows/ci.yml",
"src/.django-app-template"
]
}
32 changes: 7 additions & 25 deletions hooks/post_gen_project.sh
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
#!/bin/bash -e

echo -ne "Running with "
cp src/app/.env.ci src/app/.env

python --version
poetry install

echo Creating and populating virtualenv..
poetry run python src/manage.py collectstatic
poetry run python src/manage.py startapp some_app
poetry run python src/manage.py makemigrations -n "initial"

python -m venv venv
. venv/bin/activate
poetry run isort src/users/migrations/0001_initial.py

pip install --upgrade pip pip-tools wheel
make
poetry run python src/manage.py migrate

cd src

echo Collecting static assets...
./manage.py collectstatic

echo Running initial migrations...
./manage.py migrate

cd ../
echo Apply formatting..
make fmt

echo Running flake8..
make lint

echo Running pytest...
make test

echo Done
Loading

0 comments on commit b034c74

Please sign in to comment.