Skip to content
Merged
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
74 changes: 30 additions & 44 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
poetry-version: ["1.7.1"]
python-version: ["3.12"]
uv-version: ["0.8.14"]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}

Expand All @@ -21,34 +21,33 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: ${{ matrix.uv-version }}

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.38.0

- name: Install poetry
uses: abatilo/actions-poetry@v2
with:
poetry-version: ${{ matrix.poetry-version }}

- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local

- uses: actions/cache@v4
name: Define a cache for the virtual environment based on the dependencies lock file
name: Cache uv dependencies
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}
path: |
~/.cache/uv
.venv
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
restore-keys: |
${{ runner.os }}-uv-

- name: Install the project dependencies
run: poetry install
- name: Install dependencies
run: uv sync --all-groups

- uses: pre-commit/action@v3.0.1

- name: Run the automated tests(using pytest)
run: poetry run pytest ./src/test -sv --durations=0
run: uv run pytest ./src/test -sv --durations=0

- uses: pyupio/safety-action@v1
if: runner.os == 'Linux'
Expand All @@ -57,31 +56,18 @@ jobs:
api-key: ${{ secrets.SAFETY_API_KEY }}
args: --detailed-output # To always see detailed output from this action

- name: Gather updatable dependencies
id: gather_updatable_dependencies
run: |
UPDATE_DETAILS="library, current_version -> latest_version:\n"

# Directly reading from poetry show --outdated without a pipe
while IFS= read -r line; do
# Parse the line into variables
IFS=' ' read -r library current_version latest_version extra_info <<< "$line"
# Append the details to UPDATE_DETAILS
UPDATE_DETAILS="${UPDATE_DETAILS}${library}, ${current_version} -> ${latest_version}\n"
done < <(poetry show --outdated) # Using process substitution to feed poetry show output into the while loop

UPDATE_DETAILS="${UPDATE_DETAILS:0:-2}"
{
echo "UPDATE_DETAILS<<\n"
echo "${UPDATE_DETAILS}"
echo "\n"
} >> "$GITHUB_OUTPUT"

- name: Print updatable dependencies
if: ${{ steps.gather_updatable_dependencies.outputs.UPDATE_DETAILS != 0 }}
env:
UPDATE_DETAILS: ${{ steps.gather_updatable_dependencies.outputs.UPDATE_DETAILS }}
- name: Check for dependency updates
id: check_updates
run: |
echo -e "$UPDATE_DETAILS"
echo "Checking for dependency updates..."
echo "Current dependency constraints:"
grep -A 10 "^dependencies" pyproject.toml || true
echo ""
echo "Current dev dependencies:"
grep -A 10 "^\[dependency-groups\]" pyproject.toml || true
echo ""
echo "💡 To upgrade dependencies within constraints, run: uv sync --upgrade"
echo "💡 To check for newer versions, manually review PyPI for each package"
echo "💡 Remember to update ~= constraints in pyproject.toml for new minor versions"

# ref: https://github.com/marketplace/actions/python-poetry-action
# ref: https://github.com/astral-sh/setup-uv
75 changes: 50 additions & 25 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,57 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
# Standard pre-commit hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- id: check-toml
- id: debug-statements

- repo: local
# Ruff for Python linting and formatting
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.12.11
hooks:
- id: ruff-linter
name: ruff-linter
entry: task linter
files: ./src
language: system
always_run: true
- id: ruff-formatter
name: ruff-formatter
entry: task formatter
files: ./src
language: system
always_run: true
- id: mypy-checker
name: mypy-checker
entry: task checker
files: ./src
# Run the linter.
- id: ruff-check
args: [--fix]
# Run the formatter.
- id: ruff-format

# UV for dependency management
- repo: https://github.com/astral-sh/uv-pre-commit
# uv version.
rev: 0.8.14
hooks:
# Make sure uv.lock is up to date
- id: uv-lock
name: "uv - lock dependencies"
description: "Update uv.lock if pyproject.toml dependencies changed"

# Local hooks for custom checks
- repo: local
hooks:
# Check for dependency updates (informational only)
- id: check-dependency-updates
name: "Check for dependency updates"
entry: bash
language: system
always_run: true
args:
- -c
- |
echo "🔍 Checking for dependency updates..."
echo "Current dependency constraints:"
grep -A 10 "^dependencies" pyproject.toml || true
echo ""
echo "💡 To upgrade dependencies within constraints, run: uv sync --upgrade"
echo "💡 To check for newer versions, run: uv tree --outdated (when available)"
echo "💡 Remember to update ~= constraints in pyproject.toml for new minor versions"
files: ^pyproject\.toml$
pass_filenames: false
always_run: false
29 changes: 28 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,34 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## Current version [0.0.3] - 2024-11-16
## Current version [0.2.0] - 2025-08-31

### Changed
- **BREAKING**: Migrated from Poetry to [uv](https://docs.astral.sh/uv/) for Python package and dependency management
- **BREAKING**: Updated minimum Python version from 3.10 to 3.12
- Updated `pyproject.toml` to use modern PEP 621 format instead of Poetry-specific format
- Updated Docker configuration to use uv instead of Poetry
- Updated all task runner commands in `Taskfile.yml` to use `uv run` instead of `poetry run`
- Updated pre-commit configuration to use direct ruff and uv integrations
- Updated Python base image in Dockerfile from 3.10.6-slim to 3.12-slim
- Updated README.md documentation to reflect uv usage and simplified setup process
- Updated GitHub Actions CI workflow to use uv instead of Poetry and Python 3.12

### Added
- uv pre-commit hook for automatic dependency lock file updates
- Enhanced Docker build with better caching and optimization
- Dependency update checking in pre-commit hooks

### Removed
- Poetry dependency management (`poetry.lock` removed, replaced with `uv.lock`)
- Makefile (already deprecated in favor of `Taskfile.yml`)
- pyenv references from documentation (uv handles Python installation)

### Fixed
- Docker container now properly copies source code and sets up environment
- Improved development environment reproducibility with uv

## [0.0.3] - 2024-11-16
Added:
- Github Workflow: CI, runs for PR
- Add [pyupgrade](https://github.com/asottile/pyupgrade) for ruff
Expand Down
55 changes: 29 additions & 26 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
# Multi-stage build
FROM python:3.10.6-slim as base
FROM python:3.12-slim AS base

ARG UV_VERSION=0.8.14

ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
# Keeps Python from generating .pyc files in the container
PYTHONDONTWRITEBYTECODE=1 \
# Turns off buffering for easier container logging
PYTHONUNBUFFERED=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache
PYTHONUNBUFFERED=1

# WORKDIR /app

FROM base as builder
FROM base AS builder

ENV PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
POETRY_VERSION=1.7.1
ENV UV_VERSION=${UV_VERSION} \
UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy

# Install poetry
RUN pip install "poetry==$POETRY_VERSION"
# Disable Python downloads, because we want to use the system interpreter
# across both images. If using a managed Python version, it needs to be
# copied from the build image into the final image; see `standalone.Dockerfile`
# for an example.
ENV UV_PYTHON_DOWNLOADS=0

# Copy poetry dependency files to container
COPY pyproject.toml poetry.lock /
# Install uv
RUN pip install --no-cache-dir "uv==${UV_VERSION}"

ARG POETRY_INSTALL_OPTION="--only main"
# Install dependency
RUN poetry config virtualenvs.in-project true && \
poetry install -vvv --no-root ${POETRY_INSTALL_OPTION} && \
rm -rf $POETRY_CACHE_DIR
ARG DEPENDENCY_INSTALL_OPTION="--no-dev"
# Install Python dependencies
RUN --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 --frozen --no-install-project ${DEPENDENCY_INSTALL_OPTION}

FROM base as final
FROM base AS final

ENV VIRTUAL_ENV=/.venv \
ENV UV_VERSION=${UV_VERSION} \
VIRTUAL_ENV=/.venv \
PATH="/.venv/bin:${PATH}" \
PYTHONPATH="/app/src/"

Expand All @@ -41,11 +46,9 @@ WORKDIR /app
# Copy installed Python dependencies to final container
COPY --from=builder /.venv ${VIRTUAL_ENV}

# Keep the container running
CMD tail -f /dev/null

# Copy your code into container. e.g.:
# COPY /src /app
# Copy your code into container
COPY src/ /app/src/

# Replace your enterpoint here. e.g:
# ENTRYPOINT ["python", "-m", "main"]
# This is needed to for running locally
ARG INSTALL_UV=false
RUN bash -c "if [ $INSTALL_UV == 'true' ] ; then pip install 'uv==$UV_VERSION' ; fi"
32 changes: 0 additions & 32 deletions Makefile

This file was deleted.

Loading
Loading