Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
23 changes: 11 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,28 @@ jobs:
pypi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install poetry
run: pipx install poetry
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install deps
run: poetry install
- name: Set version
run: poetry version "${{ github.ref_name }}"
python-version: "3.12"
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v7
- name: Release package
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
run: poetry publish --build
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
uv version "${{ github.ref_name }}"
uv build
uv publish
docker:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Set up Docker
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,16 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Install deps
run: |
pip install -U pip
pip install poetry==1.8.2
poetry install
env:
POETRY_VIRTUALENVS_CREATE: "False"
- name: Set up UV
uses: astral-sh/setup-uv@v6
- name: Setup GIT
run: |
git config --global user.name "fastapi_template"
git config --global user.email "[email protected]"
- name: Run tests
run: pytest -vv -n auto
run: uv run pytest -vv -n auto
31 changes: 17 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.11.4-alpine
FROM ghcr.io/astral-sh/uv:0.9.12-python3.13-alpine

RUN apk add --no-cache \
RUN apk update && apk add --no-cache \
curl \
# For building dependencies. \
gcc \
Expand All @@ -16,23 +16,27 @@ RUN apk add --no-cache \
ncurses \
bash

RUN adduser --disabled-password fastapi_template
RUN adduser -u 1000 --disabled-password fastapi_template
RUN mkdir /projects /src
RUN chown -R fastapi_template:fastapi_template /projects /src
USER fastapi_template

WORKDIR /src
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_PROJECT_ENVIRONMENT=/usr/local
ENV UV_PYTHON_DOWNLOADS=never
ENV UV_NO_MANAGED_PYTHON=1

ENV PATH ${PATH}:/home/fastapi_template/.local/bin
WORKDIR /src
COPY . .

RUN pip install poetry==1.5.1
ENV PATH="${PATH}:/usr/local/bin"

COPY . /src/
RUN pip install .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-dev

USER root
RUN rm -rfv /src
RUN apk del curl

RUN chown -R fastapi_template:fastapi_template /projects /src /usr/local/lib/

USER fastapi_template

RUN git config --global user.name "Fastapi Template"
Expand All @@ -41,5 +45,4 @@ RUN git config --global user.email "[email protected]"
VOLUME /projects
WORKDIR /projects

ENTRYPOINT ["/home/fastapi_template/.local/bin/fastapi_template"]

ENTRYPOINT ["python", "-m", "fastapi_template"]
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@

## Usage

⚠️ [Git](https://git-scm.com/downloads), [Python](https://www.python.org/) and [Poetry](https://python-poetry.org/) must be installed and accessible ⚠️

Poetry version must be greater or equal than 1.1.8. Otherwise it won't be able to install SQLAlchemy.
⚠️ [Git](https://git-scm.com/downloads), [Python](https://www.python.org/) and [UV](https://docs.astral.sh/uv/) must be installed and accessible ⚠️

<div align="center">
<a href="https://asciinema.org/a/ig0oi0fOq1hxqnW5X49XaaHIT" target="_blank"><img src="https://asciinema.org/a/ig0oi0fOq1hxqnW5X49XaaHIT.svg" /></a>
Expand All @@ -29,7 +27,7 @@ docker-compose up --build

If you want to install it from sources, try this:
```shell
python3 -m pip install poetry
python3 -m pip install uv
python3 -m pip install .
python3 -m fastapi_template
```
Expand Down
2 changes: 1 addition & 1 deletion fastapi_template/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ def run_command(callback: Callable[[BuilderContext], None]) -> None:
for menu in menus:
cmd.params.extend(menu.get_cli_options())
required_commands = {
"poetry": "https://python-poetry.org/docs/#installation",
"uv": "https://docs.astral.sh/uv/",
"git": "https://git-scm.com/",
}
for prog, link in required_commands.items():
Expand Down
6 changes: 3 additions & 3 deletions fastapi_template/template/hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ def init_repo():
cprint("Git repository initialized.", "green")
subprocess.run(["git", "add", "."], stdout=subprocess.PIPE)
cprint("Added files to index.", "green")
subprocess.run(["poetry", "install", "-n"])
subprocess.run(["poetry", "run", "pre-commit", "install"])
subprocess.run(["uv", "sync"])
subprocess.run(["uv", "run", "pre-commit", "install"])
cprint("pre-commit installed.", "green")
subprocess.run(["poetry", "run", "pre-commit", "run", "-a"])
subprocess.run(["uv", "run", "pre-commit", "run", "-a"])
subprocess.run(["git", "add", "."], stdout=subprocess.PIPE)
subprocess.run(["git", "commit", "-m", "Initial commit"], stdout=subprocess.PIPE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ stages:

.test-template:
stage: test
image: python:3.11.4-slim-bullseye
image: ghcr.io/astral-sh/uv:0.9.12-python3.13-bookworm-slim
tags:
- kubernetes-runner
- docker-runner
except:
- tags
before_script:
- apt update && apt install -y git
- pip install poetry==1.8.2
- poetry config virtualenvs.create false
- poetry install
- uv sync

black:
extends:
- .test-template
script:
- pre-commit run black -a
- pre-commit run ruff-format -a

ruff:
extends:
Expand All @@ -31,5 +29,5 @@ mypy:
extends:
- .test-template
script:
- pre-commit run ruff -a
- pre-commit run mypy -a

Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@ repos:
- repo: local
hooks:

- id: black
name: Format with Black
entry: poetry run black
- id: ruff-format
name: Format with Ruff
entry: uv run ruff format
language: system
types: [python]
pass_filenames: false
always_run: true

- id: ruff
name: Check with Ruff
entry: poetry run ruff
entry: uv run ruff
language: system
pass_filenames: false
always_run: true
args: ["check", "{{cookiecutter.project_name}}", "tests", "--fix"]

- id: mypy
name: Validate types with MyPy
entry: poetry run mypy
entry: uv run mypy
language: system
types: [python]
pass_filenames: false
args:
- "{{cookiecutter.project_name}}"
- "tests"
49 changes: 28 additions & 21 deletions fastapi_template/template/{{cookiecutter.project_name}}/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
FROM python:3.11.4-slim-bullseye AS prod
FROM ghcr.io/astral-sh/uv:0.9.12-bookworm AS uv

# -----------------------------------
# STAGE 1: prod stage
# Only install main dependencies
# -----------------------------------
FROM python:3.13-slim-bookworm AS prod

{%- if cookiecutter.db_info.name == "mysql" %}
RUN apt-get update && apt-get install -y \
Expand All @@ -15,33 +21,34 @@ RUN apt-get update && apt-get install -y \
&& rm -rf /var/lib/apt/lists/*
{%- endif %}

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_PROJECT_ENVIRONMENT=/usr/local
ENV UV_PYTHON_DOWNLOADS=never
ENV UV_NO_MANAGED_PYTHON=1

RUN pip install poetry==1.8.2

# Configuring poetry
RUN poetry config virtualenvs.create false
RUN poetry config cache-dir /tmp/poetry_cache

# Copying requirements of a project
COPY pyproject.toml poetry.lock /app/src/
WORKDIR /app/src

# Installing requirements
RUN --mount=type=cache,target=/tmp/poetry_cache poetry install --only main
RUN --mount=from=uv,source=/uv,target=/bin/uv \
--mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project --no-dev

{%- if cookiecutter.db_info.name == "mysql" or cookiecutter.db_info.name == "postgresql" %}
# Removing gcc
RUN apt-get purge -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
{%- endif %}
COPY . .

# Copying actuall application
COPY . /app/src/
RUN --mount=type=cache,target=/tmp/poetry_cache poetry install --only main
RUN --mount=from=uv,source=/uv,target=/bin/uv \
--mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-dev --managed-python

CMD ["/usr/local/bin/python", "-m", "{{cookiecutter.project_name}}"]

# -----------------------------------
# STAGE 3: development build
# Includes dev dependencies
# -----------------------------------
FROM prod AS dev

RUN --mount=type=cache,target=/tmp/poetry_cache poetry install
RUN --mount=from=uv,source=/uv,target=/bin/uv \
--mount=type=cache,target=/root/.cache/uv \
uv sync --locked --managed-python --all-groups
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

This project was generated using fastapi_template.

## Poetry
## UV

This project uses poetry. It's a modern dependency management
This project uses uv. It's a modern dependency management
tool.

To run the project use this set of commands:

```bash
poetry install
poetry run python -m {{cookiecutter.project_name}}
uv sync --locked
uv run -m {{cookiecutter.project_name}}
```

This will start the server on the configured host.

You can find swagger documentation at `/api/docs`.

You can read more about poetry here: https://python-poetry.org/
You can read more about uv here: https://docs.astral.sh/ruff/

## Docker

Expand All @@ -37,7 +37,7 @@ docker-compose -f docker-compose.yml -f deploy/docker-compose.dev.yml --project-

This command exposes the web application on port 8000, mounts current directory and enables autoreload.

But you have to rebuild image every time you modify `poetry.lock` or `pyproject.toml` with this command:
But you have to rebuild image every time you modify `uv.lock` or `pyproject.toml` with this command:

```bash
docker-compose build
Expand Down Expand Up @@ -122,7 +122,6 @@ pre-commit is very useful to check your code before publishing it.
It's configured using .pre-commit-config.yaml file.

By default it runs:
* black (formats your code);
* mypy (validates types);
* ruff (spots possible bugs);

Expand Down
Loading
Loading