Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
git submodule update --remote
- run:
name: Install deps
command: make dev-install
command: make install
- run:
name: Linting
command: make format-check
Expand Down
61 changes: 46 additions & 15 deletions .github/workflows/database.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: Database
# These workflows are intended to check that various actions related to the database
# (such as building, exporting, and importing) work as expected.

on:
pull_request:
Expand All @@ -9,6 +11,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Lint
run: |
set -e
Expand All @@ -22,6 +26,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Generate OpenAPI schema
run: |
make install
Expand All @@ -33,6 +39,8 @@ jobs:
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Start pokeapi
run: |
make install
Expand All @@ -46,27 +54,50 @@ jobs:
run: curl -Ss http://localhost:8000/api/v2/pokemon/1/ | grep -q 'bulbasaur'
postgres:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: pokeapi
POSTGRES_PASSWORD: pokeapi
POSTGRES_DB: pokeapi
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
- name: Build
run: |
docker compose -f docker-compose.yml -f docker-compose-dev.yml up -d
make docker-migrate
make docker-build-db
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: make install
- name: Run migrations
run: uv run manage.py migrate --settings=config.local
- name: Build database
run: uv run manage.py shell --settings=config.local -c "from data.v2.build import build_all; build_all(); exit()"
- name: Dump DB
run: docker compose exec -T -u postgres db sh -c "cd /tmp && pg_dump -h localhost -Fc -U ash -N 'hdb_*' pokeapi > pokeapi.dump"
- name: Copy dump
run: docker compose cp db:/tmp/pokeapi.dump ./
- name: Down services
run: docker compose -f docker-compose.yml -f docker-compose-dev.yml down -v
- name: Start services
run: docker compose -f docker-compose.yml -f docker-compose-dev.yml up -d
run: pg_dump -h localhost -U pokeapi -Fc -N 'hdb_*' pokeapi > pokeapi.dump
env:
PGPASSWORD: pokeapi
- name: Drop and recreate database
run: |
psql -h localhost -U pokeapi -d postgres -c "DROP DATABASE pokeapi;"
psql -h localhost -U pokeapi -d postgres -c "CREATE DATABASE pokeapi;"
env:
PGPASSWORD: pokeapi
- name: Import database
run: pg_restore -h localhost -U pokeapi -d pokeapi pokeapi.dump
env:
PGPASSWORD: pokeapi
- name: Start server
run: |
docker compose cp ./pokeapi.dump db:/tmp/
docker compose exec -T -u postgres db sh -c "cd /tmp && pg_restore -h localhost -U ash -d pokeapi pokeapi.dump"
nohup uv run manage.py runserver 0.0.0.0:8000 --settings=config.local &
sleep 5
- name: Test data
run: curl -Ss http://localhost/api/v2/pokemon/1/ | grep -q 'bulbasaur'
run: curl -Ss http://localhost:8000/api/v2/pokemon/1/ | grep -q 'bulbasaur'
2 changes: 2 additions & 0 deletions .github/workflows/docker-build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/docker-k8s.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: Container
# These workflows are intended to check that the Docker and Kubernetes
# configurations work as expected in a local development environment.

on:
pull_request:
Expand All @@ -11,6 +13,8 @@ jobs:
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
Expand Down Expand Up @@ -112,4 +116,4 @@ jobs:
- name: Assert containers running
run: |
last_command=$(docker ps | grep 'pokeapi-' | wc -l)
test "$last_command" -eq 5
test "$last_command" -eq 5
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Start pokeapi (docker)
run: |
docker compose -f docker-compose.yml -f docker-compose-dev.yml up -d
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
43 changes: 18 additions & 25 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,59 @@ docker_config = --settings=config.docker-compose
gql_compose_config = -f docker-compose.yml -f Resources/compose/docker-compose-prod-graphql.yml
gqlv1beta_compose_config = -f docker-compose.yml -f Resources/compose/docker-compose-prod-graphql.yml -f Resources/compose/docker-compose-prod-graphql-v1beta.yml

# Auto-detect Python and pip commands
PYTHON := $(shell which python3 2>/dev/null || which python 2>/dev/null || echo python3)
PIP := $(shell which pip3 2>/dev/null || which pip 2>/dev/null || echo pip3)

.PHONY: help
.SILENT:

help:
@grep -E '^[a-zA-Z_-]+:.*?# .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?# "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

install: # Install base requirements to run project
$(PIP) install -r requirements.txt

dev-install: # Install developer requirements + base requirements
$(PIP) install -r test-requirements.txt
uv sync

setup: # Set up the project database
$(PYTHON) manage.py migrate ${local_config}
uv run manage.py migrate ${local_config}

build-db: # Build database
echo "from data.v2.build import build_all; build_all()" | $(PYTHON) manage.py shell ${local_config}
echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell ${local_config}

wipe-sqlite-db: # Delete's the project database
rm -rf db.sqlite3

serve: # Run the project locally
$(PYTHON) manage.py runserver ${local_config}
uv run manage.py runserver ${local_config}

test: # Run tests
$(PYTHON) manage.py test ${local_config}
uv run manage.py test ${local_config}

clean: # Remove any pyc files
find . -type f -name '*.pyc' -delete

migrate: # Run any outstanding migrations
$(PYTHON) manage.py migrate ${local_config}
uv run manage.py migrate ${local_config}

make-migrations: # Create migrations files if schema has changed
$(PYTHON) manage.py makemigrations ${local_config}
uv run manage.py makemigrations ${local_config}

shell: # Load a shell
$(PYTHON) manage.py shell ${local_config}
uv run manage.py shell ${local_config}

openapi-generate:
$(PYTHON) manage.py spectacular --color --file openapi.yml ${local_config}
uv run manage.py spectacular --color --file openapi.yml ${local_config}

docker-up: # (Docker) Create services/volumes/networks
docker compose up -d

docker-migrate: # (Docker) Run any pending migrations
docker compose exec -T app python manage.py migrate ${docker_config}
docker compose --verbose exec -T app uv run manage.py migrate ${docker_config}

docker-build-db: # (Docker) Build the database
docker compose exec -T app sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell ${docker_config}'
docker compose exec -T app sh -c 'echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell ${docker_config}'

docker-make-migrations: # (Docker) Create migrations files if schema has changed
docker compose exec -T app sh -c 'python manage.py makemigrations ${docker_config}'
docker compose exec -T app sh -c 'uv run manage.py makemigrations ${docker_config}'

docker-flush-db: # (Docker) Removes all the data present in the database but preserves tables and migrations
docker compose exec -T app sh -c 'python manage.py flush --no-input ${docker_config}'
docker compose exec -T app sh -c 'uv run manage.py flush --no-input ${docker_config}'

docker-destroy-db: # (Docker) Removes the volume where the database is installed on, alongside to the container itself
docker rm -f pokeapi_db_1
Expand All @@ -79,18 +72,18 @@ docker-down: # (Docker) Stop and removes containers and networks
docker compose down

docker-test: # (Docker) Run tests
docker compose exec -T app python manage.py test ${local_config}
docker compose exec -T app uv run manage.py test ${local_config}

docker-prod:
docker compose -f docker-compose.yml -f docker-compose.override.yml -f Resources/compose/docker-compose-prod-graphql.yml up -d

docker-setup: docker-up docker-migrate docker-build-db # (Docker) Start services, prepare the latest DB schema, populate the DB

format: # Format the source code
black . --extend-exclude '.+/scripts/.+'
uv run ruff check . --fix --extend-exclude '.+/scripts/.+'

format-check: # Check the source code has been formatted
black . --check --extend-exclude '.+/scripts/.+'
uv run ruff check . --extend-exclude '.+/scripts/.+'

pull:
git checkout master
Expand Down Expand Up @@ -137,10 +130,10 @@ kustomize-ga-apply: # (Kustomize) Run kubectl apply -k on the connected k8s clu
kubectl apply -k Resources/k8s/kustomize/ga/

k8s-migrate: # (k8s) Run any pending migrations
kubectl exec --namespace pokeapi deployment/pokeapi -- python manage.py migrate ${docker_config}
kubectl exec --namespace pokeapi deployment/pokeapi -- uv run manage.py migrate ${docker_config}

k8s-build-db: # (k8s) Build the database
kubectl exec --namespace pokeapi deployment/pokeapi -- sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell ${docker_config}'
kubectl exec --namespace pokeapi deployment/pokeapi -- sh -c 'echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell ${docker_config}'

k8s-delete: # (k8s) Delete pokeapi namespace
kubectl delete namespace pokeapi
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ A RESTful API for Pokémon - [pokeapi.co](https://pokeapi.co)

- Download this source code into a working directory, be sure to use the flag `--recurse-submodules` to clone also our submodules.

- Install the requirements using pip:
- Install [uv](https://docs.astral.sh/uv/getting-started/installation/) for Python environment management.

- Install the requirements using the Makefile commands:

```sh
make install
Expand Down Expand Up @@ -97,8 +99,8 @@ If you don't have `make` on your machine you can use the following commands

```sh
docker compose up -d
docker compose exec -T app python manage.py migrate --settings=config.docker-compose
docker compose exec -T app sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell --settings=config.docker-compose'
docker compose exec -T app uv run manage.py migrate --settings=config.docker-compose
docker compose exec -T app sh -c 'echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell --settings=config.docker-compose'
```

Browse [localhost/api/v2/](http://localhost/api/v2/) or [localhost/api/v2/pokemon/bulbasaur/](http://localhost/api/v2/pokemon/bulbasaur/) on port `80`.
Expand Down Expand Up @@ -149,8 +151,8 @@ Configure `kubectl` to point to a cluster and then run the following commands to
kubectl apply -k Resources/k8s/kustomize/base/
kubectl config set-context --current --namespace pokeapi # (Optional) Set pokeapi ns as the working ns
# Wait for the cluster to spin up
kubectl exec --namespace pokeapi deployment/pokeapi -- python manage.py migrate --settings=config.docker-compose # Migrate the DB
kubectl exec --namespace pokeapi deployment/pokeapi -- sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell --settings=config.docker-compose' # Build the db
kubectl exec --namespace pokeapi deployment/pokeapi -- uv run manage.py migrate --settings=config.docker-compose # Migrate the DB
kubectl exec --namespace pokeapi deployment/pokeapi -- sh -c 'echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell --settings=config.docker-compose' # Build the db
kubectl wait --namespace pokeapi --timeout=120s --for=condition=complete job/load-graphql # Wait for Graphql configuration job to finish
```

Expand Down
28 changes: 23 additions & 5 deletions Resources/docker/app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@ ENV PYTHONUNBUFFERED=1
RUN mkdir /code
WORKDIR /code

ADD requirements.txt /code/
# Install UV
RUN apk add --no-cache curl
RUN curl -LsSf https://astral.sh/uv/install.sh | sh

# Add UV to PATH for this stage
ENV PATH="/root/.local/bin:$PATH"

# Copy dependency files
ADD pyproject.toml uv.lock* /code/

# Install dependencies
RUN apk add --no-cache postgresql-libs libstdc++
RUN apk add --no-cache --virtual .build-deps gcc g++ musl-dev \
postgresql-dev binutils rust cargo && \
python3 -m pip install -r requirements.txt --no-cache-dir
uv sync --frozen

FROM python:3.13.7-alpine

Expand All @@ -19,15 +29,23 @@ ENV DJANGO_SETTINGS_MODULE='config.docker-compose'
RUN mkdir /code
WORKDIR /code

COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy UV and virtual environment from builder
COPY --from=builder /root/.local /root/.local
COPY --from=builder /code/.venv /code/.venv

# Add UV to PATH
ENV PATH="/root/.local/bin:$PATH"

# Install runtime dependencies
RUN apk add --no-cache postgresql-libs libstdc++

# Copy application code
ADD . /code/

RUN addgroup -g 1000 -S pokeapi && \
adduser -u 1000 -S pokeapi -G pokeapi
USER pokeapi

CMD ["gunicorn", "config.wsgi:application", "-c", "gunicorn.conf.py"]
CMD ["uv", "run", "gunicorn", "config.wsgi:application", "-c", "gunicorn.conf.py"]

EXPOSE 80
4 changes: 2 additions & 2 deletions Resources/docker/app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ Pokémon data isn't automatically present in this image. All Pokémon data is pe
When the container is up and running, run the following shell commands:

```sh
docker exec pokeapi python manage.py migrate --settings=config.docker-compose
docker exec pokeapi sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell --settings=config.docker-compose'
docker exec pokeapi uv run manage.py migrate --settings=config.docker-compose
docker exec pokeapi sh -c 'echo "from data.v2.build import build_all; build_all()" | uv run manage.py shell --settings=config.docker-compose'
```
1 change: 1 addition & 0 deletions Resources/scripts/data/gen8/ability_names.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import csv
import os

from read_swsh import TextFile

# data_path contains the countents of the `message` folder found in sword/shield's romfs:/bin/
Expand Down
1 change: 1 addition & 0 deletions Resources/scripts/data/gen8/move_names.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import csv
import os

from read_swsh import TextFile

# data_path contains the countents of the `message` folder found in sword/shield's romfs:/bin/
Expand Down
Loading