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
11 changes: 11 additions & 0 deletions .actrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Runner image configuration - use maintained catthehacker images
-P ubuntu-latest=catthehacker/ubuntu:act-22.04

# Container architecture (explicit for M1/M2 Macs)
--container-architecture=linux/amd64

# Container daemon socket (will be overridden by Makefile)
--container-daemon-socket=-

# Verbose output by default
--verbose
44 changes: 44 additions & 0 deletions .github/workflows/ci-debug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI Debug (Local Testing)

# This workflow is designed for fast local iteration with act
# It runs a subset of checks for quick feedback
#
# Usage: make ci-debug
#
# Customize the steps below for the specific tests you're working on

on:
workflow_dispatch:
push:
branches:
- '**'

jobs:
quick-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Install uv
run: pip install uv

- name: Install dependencies
run: |
uv venv
uv sync --all-extras

# Customize these steps based on what you're debugging
- name: Run Linter
run: uv run -m ruff check src

- name: Run Type Checker
run: uv run ty check src

# Add more steps as needed for debugging
# - name: Run Specific Test
# run: uv run -m pytest tests/test_specific.py -v
8 changes: 3 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ jobs:

- name: Install dependencies
run: |
uv pip compile pyproject.toml -o requirements.txt
uv pip compile pyproject.toml --extra dev -o requirements-dev.txt
uv venv
uv pip sync requirements.txt requirements-dev.txt
uv sync --all-extras

- name: Determine module name
id: module
Expand All @@ -43,8 +41,8 @@ jobs:
- name: Run Tests
run: uv run -m pytest tests --cov=${{ steps.module.outputs.name }} --cov-report=term-missing --cov-report=xml

- name: Run MyPy
run: uv run -m mypy ${{ steps.module.outputs.name }}
- name: Run ty
run: uv run ty check ${{ steps.module.outputs.name }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ CLAUDE.md
# Documentation build artifacts
site/
.cache/

# AI/planning artifacts
.ai/**

# act (GitHub Actions local runner)
.actrc.local
.secrets
.env.act
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ repos:
language: system
always_run: true
pass_filenames: false
- id: mypy
name: Run MyPy
entry: make mypy
- id: ty
name: Run ty
entry: make ty
language: system
always_run: true
pass_filenames: false
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Integration with uv for dependency management
- Modern Python development tools:
- ruff for linting and formatting
- mypy for type checking
- ty for type checking
- pytest with coverage reporting
- GitHub Actions workflow for automated testing
- Docker development environment improvements
- Local CI testing with act for running GitHub Actions workflows locally
- Fast debug workflow for iterative development
- Make targets: `act-install`, `ci-list`, `ci-local`, `ci-local-docs`, `ci-debug`, `ci-clean`

### Changed
- Switched from pip/venv to uv for environment management
- Updated example code to pass mypy type checking
- Updated example code to pass ty type checking
- Modernized project structure and development workflow
- Updated Python version to 3.12

Expand All @@ -27,7 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Outdated Docker configuration elements

### Fixed
- Type hints in example code to pass mypy checks
- Type hints in example code to pass ty checks
- Docker environment management
- Development workflow and quality checks

Expand Down
124 changes: 117 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: compile-deps setup clean-pyc clean-test clean-venv clean test mypy lint format check clean-example docs-install docs-build docs-serve docs-check docs-clean dev-env refresh-containers rebuild-images build-image push-image
.PHONY: compile-deps setup clean-pyc clean-test clean-venv clean test ty lint format check clean-example docs-install docs-build docs-serve docs-check docs-clean dev-env refresh-containers rebuild-images build-image push-image

# Module name - will be updated by init script
MODULE_NAME := src
Expand All @@ -14,9 +14,8 @@ PYTHON_VERSION ?= 3.12
ensure-uv: # Install uv if not present
@which uv > /dev/null || (curl -LsSf https://astral.sh/uv/install.sh | sh)

setup: ensure-uv compile-deps ensure-scripts # Install dependencies
UV_PYTHON_VERSION=$(PYTHON_VERSION) uv venv
UV_PYTHON_VERSION=$(PYTHON_VERSION) uv pip sync requirements.txt requirements-dev.txt
setup: ensure-uv ensure-scripts # Install dependencies
UV_PYTHON_VERSION=$(PYTHON_VERSION) uv sync --all-extras
$(MAKE) install-hooks

install-hooks: # Install pre-commit hooks if in a git repo with hooks configured
Expand Down Expand Up @@ -51,16 +50,127 @@ clean: clean-pyc clean-test clean-venv
test: setup # Run pytest with coverage
uv run -m pytest tests --cov=$(MODULE_NAME) --cov-report=term-missing

mypy: setup # Run type checking
uv run -m mypy $(MODULE_NAME)
ty: setup # Run type checking
uv run ty check $(MODULE_NAME)

lint: setup # Run ruff linter with auto-fix
uv run -m ruff check --fix $(MODULE_NAME)

format: setup # Run ruff formatter
uv run -m ruff format $(MODULE_NAME)

check: setup lint format test mypy # Run all quality checks
check: setup lint format test ty # Run all quality checks

# Local CI Testing with act
###########################

# Detect docker socket (Colima, Docker, or Podman)
define docker_socket
$(shell \
if [ -S $$HOME/.colima/default/docker.sock ]; then \
echo "$$HOME/.colima/default/docker.sock"; \
elif [ -S /var/run/docker.sock ]; then \
echo "/var/run/docker.sock"; \
elif [ -S $$HOME/.docker/run/docker.sock ]; then \
echo "$$HOME/.docker/run/docker.sock"; \
elif [ -S /run/user/$$(id -u)/podman/podman.sock ]; then \
echo "/run/user/$$(id -u)/podman/podman.sock"; \
else \
echo "/var/run/docker.sock"; \
fi \
)
endef

DOCKER_SOCKET := $(docker_socket)
ACT_IMAGE := catthehacker/ubuntu:act-22.04
ACT_ARCH := linux/amd64

act-check: # Check if act is installed, install if missing
@if ! which act > /dev/null 2>&1; then \
echo "⚠️ act is not installed. Installing automatically..."; \
$(MAKE) act-install; \
fi

docker-check: # Check if Docker/Podman/Colima is running
@if ! DOCKER_HOST="unix://$(DOCKER_SOCKET)" docker ps >/dev/null 2>&1; then \
echo "❌ Cannot connect to Docker daemon"; \
echo ""; \
echo "Please start your container runtime first:"; \
echo " • Docker Desktop: Open Docker Desktop app"; \
echo " • Colima: run 'colima start'"; \
echo " • Podman: run 'podman machine start'"; \
echo " • Docker (Linux): run 'sudo systemctl start docker'"; \
echo ""; \
echo "Attempted socket: $(DOCKER_SOCKET)"; \
exit 1; \
fi
@echo "✓ Docker is running (socket: $(DOCKER_SOCKET))"

act-install: ## Install act for local CI testing
@echo "Installing act (GitHub Actions local runner)..."
@if which act > /dev/null 2>&1; then \
echo "✅ act is already installed: $$(which act)"; \
act --version; \
elif which brew > /dev/null 2>&1; then \
echo "📦 Installing act via Homebrew..."; \
brew install act; \
else \
echo "📦 Installing act via install script..."; \
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash; \
fi
@echo ""
@echo "✅ act installed successfully!"
@echo "💡 Run 'make ci-list' to see available workflows"
@echo "💡 Run 'make ci-local' to run CI checks locally"

ci-list: act-check docker-check ## List available GitHub Actions workflows and jobs
@echo "📋 Available workflows and jobs:"
@DOCKER_HOST="unix://$(DOCKER_SOCKET)" act -l

ci-local: act-check docker-check ## Run CI checks locally (tests workflow)
@echo "🔬 Running local CI checks..."
@echo "Using Docker socket: $(DOCKER_SOCKET)"
@echo "Container architecture: $(ACT_ARCH)"
@echo "Image: $(ACT_IMAGE)"
@echo ""
@JOB=$${JOB:-checks}; \
DOCKER_HOST="unix://$(DOCKER_SOCKET)" act pull_request \
-W .github/workflows/tests.yml \
-j $$JOB \
--container-daemon-socket - \
--container-architecture $(ACT_ARCH) \
-P ubuntu-latest=$(ACT_IMAGE)
@echo ""
@echo "✅ Local CI checks complete!"

ci-local-docs: act-check docker-check ## Run documentation build check locally
@echo "📚 Running local documentation build check..."
@DOCKER_HOST="unix://$(DOCKER_SOCKET)" act pull_request \
-W .github/workflows/docs.yml \
-j build-check \
--container-daemon-socket - \
--container-architecture $(ACT_ARCH) \
-P ubuntu-latest=$(ACT_IMAGE)
@echo ""
@echo "✅ Documentation build check complete!"

ci-debug: act-check docker-check ## Fast local test debugging (uses ci-debug.yml workflow)
@echo "🔧 Running CI debug workflow for fast iteration"
@echo "💡 Edit .github/workflows/ci-debug.yml to customize which tests run"
@echo ""
@DOCKER_HOST="unix://$(DOCKER_SOCKET)" act workflow_dispatch \
-W .github/workflows/ci-debug.yml \
--container-daemon-socket - \
--container-architecture $(ACT_ARCH) \
-P ubuntu-latest=$(ACT_IMAGE)
@echo ""
@echo "✅ Debug workflow complete!"

ci-clean: ## Clean up act cache and containers
@echo "🧹 Cleaning up act cache and containers..."
@-docker ps -a | grep "act-" | awk '{print $$1}' | xargs docker rm -f 2>/dev/null || true
@-docker images | grep "act-" | awk '{print $$3}' | xargs docker rmi -f 2>/dev/null || true
@echo "✅ Cleanup complete!"

# Documentation
###############
Expand Down
68 changes: 64 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A modern Python project template with best practices for development and collabo
## Features
- 🚀 Fast dependency management with [uv](https://github.com/astral-sh/uv)
- ✨ Code formatting with [ruff](https://github.com/astral-sh/ruff)
- 🔍 Type checking with [mypy](https://github.com/python/mypy)
- 🔍 Type checking with [ty](https://astral.sh/blog/ty)
- 🧪 Testing with [pytest](https://github.com/pytest-dev/pytest)
- 🐳 Docker support for development and deployment
- 👷 CI/CD with GitHub Actions
Expand Down Expand Up @@ -48,7 +48,7 @@ This will:
- Configure pre-commit hooks (optional, enabled by default)

Pre-commit hooks will automatically run these checks before each commit:
- Type checking (mypy)
- Type checking (ty)
- Linting (ruff)
- Formatting (ruff)
- Tests (pytest)
Expand All @@ -69,13 +69,73 @@ make clean-example

### Quality Checks
```bash
make check # Run all checks (test, mypy, lint, format)
make check # Run all checks (test, ty, lint, format)
make test # Run tests with coverage
make mypy # Run type checking
make ty # Run type checking
make lint # Run linter
make format # Run code formatter
```

### Local CI Testing

Run GitHub Actions workflows locally before pushing using [act](https://github.com/nektos/act):

```bash
# Run full test suite locally (auto-installs act if needed)
make ci-local

# List available workflows
make ci-list

# Run specific job
JOB=checks make ci-local

# Run documentation build check
make ci-local-docs

# Fast debugging (customize .github/workflows/ci-debug.yml)
make ci-debug

# Clean up act containers
make ci-clean
```

**Note:** The first run will automatically install `act` if it's not present.

**Benefits:**
- 5-20 second feedback vs. 2-5 minutes on GitHub
- Test before commit/push
- No GitHub Actions minutes consumed
- Debug workflows locally

**Troubleshooting:**

*Linux: Docker permissions*
```bash
# Add your user to the docker group
sudo usermod -aG docker $USER

# Log out and back in for changes to take effect
# Or run: newgrp docker

# Verify it works
docker ps
```

*macOS: Colima disk lock errors*
```bash
# If you get "disk in use" or similar errors:
colima stop
colima delete
colima start
```

*General: Stale act containers*
```bash
# Clean up old containers and images
make ci-clean
```

### Example Code
The repository includes a simple example showing:
- Type hints
Expand Down
8 changes: 3 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ RUN apt-get update && apt-get install -y \
WORKDIR /workspace

# Copy essential files for dependency resolution to temp location
COPY pyproject.toml /tmp/
COPY pyproject.toml uv.lock /tmp/
COPY README.md /tmp/

RUN pip install -U pip uv \
&& cd /tmp \
&& uv pip compile pyproject.toml -o requirements.txt \
&& uv pip compile pyproject.toml --extra dev -o requirements-dev.txt \
&& uv pip sync --system requirements.txt requirements-dev.txt \
&& rm -rf /tmp/pyproject.toml /tmp/README.md
&& uv sync --system --all-extras \
&& rm -rf /tmp/pyproject.toml /tmp/uv.lock /tmp/README.md

CMD ["/bin/bash"]
Loading