- Alembic (Database migration tool for usage with SQLAlchemy/Python): https://alembic.sqlalchemy.org/en/latest/
- Pydantic (Data validation library for Python): https://docs.pydantic.dev/latest/
- SQLAlchemy (Object Relational Mapper/ORM and Python SQL toolkit): https://www.sqlalchemy.org/
- Adminer (DB management tool that provides editor/ GUI for db): https://www.adminer.org/
- Redis (Data platform for caching and message broker): https://redis.io/docs/latest/
- Celery (Asynchronous task or job queue): https://docs.celeryq.dev/en/stable/getting-started/introduction.html
- Pytest (Python testing framework): https://docs.pytest.org/en/stable/
Integrations(any external service ie AWS, Auth0, etc) to be documented here
- Rename all instances of
database_name
andapp_name
to desired name - Before running, delete all
alembic/versions/X...
files (otherwise you will have to fix the alembic heads)-- these are just here for example - Delete any example.py files as needed. These are here to serve as a template for how files/code should be standardized
- Ensure you have Docker Desktop installed: https://www.docker.com/products/docker-desktop/
- You should have Python installed, current image is 3.12 (ideal to have same image as repo). https://mac.install.guide/python/brew
- TODO note: To ensure seamless set up, we can later introduce
pyenv
to manage virtual environments that match the repo
- TODO note: To ensure seamless set up, we can later introduce
- Your .env file should be located at
./config/.env
and have the following fields: (update these both in the ReadME and in the sample.env file as the project progresses)
ENVIRONMENT= #Set to "DEV" or something other than "PRODUCTION" to enable reloading
#Update these as appropriate for the project
VARIABLE_NAME = "example
etc
The easiest way to run app for development purposes is to run services in Docker while using VSCode in a virtual env. To do so, open up a terminal within your directory, and a shell for each of the following:
Ensure Docker desktop is open and run the following command: make
This will start each of the containers in Docker compose, and once healthy/running, you may open the Swagger docs at http://localhost:3000/docs
(See below for all commands included in MakeFile related to Adminer, requirements, etc)
App logs are included by default in the app container, but please see additional logging commands below
After Docker containers are running, you can create a virtual environment, install the requirements, and open VSCode as follows:
- Open a new terminal shell
- run
python3 -m venv env_name
Replaceenv_name
with whatever you want to call it - run
. env_name/bin/activate
Replaceenv_name
with name from step 2 - Naviate to project
cd /whatever/your/repo/path/is
- Run
pip3 install -r requirements.txt
- Run
code .
This will open VSCode from within the virtual environment, ensuring packages are recognized
Note: Once this is done for the first time, you can start with step 3 to activate the already created venv, and you only need to install requirements when there has been a change or addition Depending on your setup, you may also be able to navigate directly to your repo, and run step 5, which may trigger your .venv automatically
Any new packages should be added to the requirements.in
file, and then run the command make requirements
to generate a new requirements.txt file with appropriate versioning
When changes occur in the requirements.txt
file, you will need to run docker compose stop app worker worker-beat && make
for Docker, and re-run step 4 above for your virtual env
make requirements
: runs pip-compile to generate a new requirements.txt file based on packages listed in requirements.inmake linting
: runs Black for lintingmake pytest
: runs unit testsmake open-adminer
: opens Adminer GUI for DB managementmake logs-all
: runs logs for all docker containersmake logs-redis
: runs logs for redis containermake logs-worker
: runs logs for both worker containersmake stop
: stop containersmake remove
: remove Docker containers and volumes
Running the project via the make
command also runs PostGreSQL via Docker. As noted above, make open-adminer
will open a GUI to inspect and manage the database
The initial SQL script is found within support/docker/pg/init.sql
and this will need to be modified from the template for the actual database_name
(remove this note when template is utilized)
By default, the folder alembic/versions
should be included here. If it is not, be sure to run mkdir alembic/versions
so that migrations can be created
To create new migration: Run make migration name=name_of_your_migration
This will generate a new file inside alembic/versions
which must be edited before proceeding
To apply new migration: Run make migrate
This will apply the migration
Please note that if you create a migration locally while another dev also has one locally, the second person to merge will need to create a migration that resolves the "multiple heads" conflict.
To resolve head conflicts:
- Identify the conflict:
- After Pulling latest changes from the main branch, you can run the following command to check for multiple heads:
alembic heads
- After Pulling latest changes from the main branch, you can run the following command to check for multiple heads:
- Merge Heads
- If you see multiple heads, you need to merge them by creating a new migration that combines them by running
alembic merge <head1> <head2>
replace with actual head IDs
- If you see multiple heads, you need to merge them by creating a new migration that combines them by running
- Edit Merge Migration
- This will generate a new merge migration file in the
alembic/versions
directory. Open this file and ensure it correctly represents the desired state
- This will generate a new merge migration file in the
- Apply
- Apply merge migration by running
make migrate
- Apply merge migration by running
┌─■ README.md # You are here
├─■ Makefile # Commands
├─■ requirements.in # Add new packages here
├─■ requirements.txt # Output from requirements.in
├─■ Dockerfile
├─■ docker-compose.yaml
│
├─■ run_server # create .venv, install requirements and run server.py
├─■ server.py # main file
│
├─■ run_worker
├─■ run_beat # celery beat / cronjob
├─■ worker.py # worker entrypoint
├─┐tasks
│ ├─■ worker.py # celery instance
│ └─■ tasks.py # registered tasks
│
│
├─■ run_migration
├─■ alembic.init
├─┐alembic # responsible for db migrations
│ ├─■ env.py
│ ├─■ script.py.make
│ └─┐versions
│ └─■ *.py # migrations
│
├─┐source
│ ├─┐models # refers to the SQLAlchemy model, representing the database table and handles the ORM tasks
│ │ └─■ example.py
│ |
│ ├─┐schemas # refers to Pydantic models, handling the validation of incoming and outgoing data
│ │ └─■ example.py
│ |
│ └─┐integrations # transport layer which should not contain any business logic
│ | ├─■ db/
| | └─■ example.py # each db integration should only make use of the .save (add/update) and .filter (retrieving) functions to maintain simplicity
│ | └─■ redis/
│ |
│ ├─┐services # responsible for business logic and interacting with integrations
│ │ └─■ example.py
│ |
│ └─┐routes # presentation layer which provides interface to service layer. This should not contain any business logic
│ └─■ example.py
│
├─┐config
│ ├─■ settings.py
│ └─■ utils.py
│
├─┐tests
│ ├─■ example.py #add tests here
│
│
└─┐docs
├─┐ architecture
│ └─decisions
│ | └─■ * Add ADRs here