From a3c7892c4dceb8b083d5e277e4c3e9da346c58ea Mon Sep 17 00:00:00 2001 From: Jon Zeolla Date: Thu, 18 Sep 2025 11:22:56 -0400 Subject: [PATCH 1/2] feat(devcontainers): add initial dev containers configs --- .../.devcontainer/README.md" | 53 ++++++++++++++++++ .../.devcontainer/devcontainer.json" | 53 ++++++++++++++++++ .../.devcontainer/docker-compose.yml" | 34 ++++++++++++ .../Taskfile.yml" | 55 +++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 "{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" create mode 100644 "{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/devcontainer.json" create mode 100644 "{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/docker-compose.yml" diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" new file mode 100644 index 0000000..475f2b5 --- /dev/null +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" @@ -0,0 +1,53 @@ +# Development Container Setup + +This project includes Dev Container support for VS Code and other compatible editors. + +## Quick Start + +### Option 1: Using VS Code Dev Containers Extension (Recommended) +1. Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +2. Open this project in VS Code +3. Click "Reopen in Container" when prompted, or use Command Palette: `Dev Containers: Reopen in Container` + +### Option 2: Attach to Running Container +1. Start the dev container: + ```bash + task dev-container + ``` +2. In VS Code, use Command Palette: `Dev Containers: Attach to Running Container` +3. Select the `{{ cookiecutter.project_slug }}-dev` container + +### Option 3: Manual Docker Commands +```bash +# Build and start the dev container +task dev-container + +# Access the container shell +docker exec -it {{ cookiecutter.project_slug }}-dev bash + +# Stop the container when done +task dev-container-stop +``` + +## Features + +The dev container includes: +- Python {{ cookiecutter.python_version }}+ with uv package manager +- All project dependencies (including dev dependencies) +- Git, GitHub CLI, Task, and pre-commit tools +- VS Code extensions for Python development +- Proper volume mounts for live code editing + +## Environment + +- `DEV_MODE=true` - Installs all development dependencies +- `PYTHONPATH=/workspace/src` - Ensures proper module imports +- Working directory: `/workspace` + +## Troubleshooting + +If you encounter issues: +1. Ensure Docker is running +2. Check that you have the latest Dev Containers extension +3. Try rebuilding the container: `Dev Containers: Rebuild Container` +4. For manual setup, ensure you run `task init` after container starts \ No newline at end of file diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/devcontainer.json" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/devcontainer.json" new file mode 100644 index 0000000..0bf52a0 --- /dev/null +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/devcontainer.json" @@ -0,0 +1,53 @@ +{ + "name": "{{ cookiecutter.project_name }}", + "dockerComposeFile": "docker-compose.yml", + "service": "dev", + "workspaceFolder": "/workspace", + "features": { + "ghcr.io/devcontainers/features/git:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers-contrib/features/task:1": {}, + "ghcr.io/devcontainers-contrib/features/pre-commit:2": {} + }, + "customizations": { + "vscode": { + "settings": { + "python.defaultInterpreterPath": "/app/.venv/bin/python", + "python.formatting.provider": "none", + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.ruff": "explicit", + "source.organizeImports.ruff": "explicit" + } + }, + "python.testing.pytestArgs": [ + "tests" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.linting.enabled": false, + "python.analysis.typeCheckingMode": "basic", + "editor.rulers": [120] + }, + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "charliermarsh.ruff", + "tamasfe.even-better-toml", + "redhat.vscode-yaml", + "ms-azuretools.vscode-docker", + "GitHub.vscode-pull-request-github", + "GitHub.copilot" + ] + } + }, + "postCreateCommand": "cd /workspace && task init", + "postStartCommand": "git config --global --add safe.directory /workspace", + "containerEnv": { + "DEV_MODE": "true", + "PYTHONPATH": "/workspace/src" + }, + "remoteUser": "root" +} \ No newline at end of file diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/docker-compose.yml" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/docker-compose.yml" new file mode 100644 index 0000000..022fa4e --- /dev/null +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/docker-compose.yml" @@ -0,0 +1,34 @@ +version: '3.8' + +services: + dev: + build: + context: .. + dockerfile: Dockerfile + target: builder + args: + PYTHON_VERSION: {{ cookiecutter.python_version }} + DEV_MODE: "true" + volumes: + # Mount the entire project directory + - ..:/workspace:cached + # Cache directories for faster rebuilds + - uv-cache:/root/.cache/uv + environment: + - DEV_MODE=true + - PYTHONPATH=/workspace/src + - UV_COMPILE_BYTECODE=1 + - UV_LINK_MODE=copy + working_dir: /workspace + # Overwrite the default command to keep container running + command: sleep infinity + # Network mode for easier debugging and service access + network_mode: host + # Add capabilities needed for debugging + cap_add: + - SYS_PTRACE + security_opt: + - seccomp:unconfined + +volumes: + uv-cache: \ No newline at end of file diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" index 4f0955e..a724ab8 100644 --- "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" @@ -184,6 +184,61 @@ tasks: # rebuild the builder instance, updating its BuildKit. There's no harm in running this even if we didn't do the `docker buildx rm` previously - task: init-docker-multiplatform + dev-container: + desc: Build and start development container + vars: + TIMESTAMP: + sh: '{{ '{{.RUN_SCRIPT}}' }} {{ '{{.SCRIPTS_DIR}}' }}/get_rfc3339_timestamp.py' + COMMIT_HASH: + sh: git rev-parse HEAD + DESCRIPTION: "{{ cookiecutter.project_short_description | replace('"', '\\"') | replace("'", "\\\\'") }}" + cmds: + # Stop any existing container + - docker stop {{ '{{.PROJECT_SLUG}}' }}-dev 2>/dev/null || true + - docker rm {{ '{{.PROJECT_SLUG}}' }}-dev 2>/dev/null || true + # Build the dev image + - | + docker buildx build \ + --platform {{ '{{.LOCAL_PLATFORM}}' }} \ + --load \ + --target builder \ + --build-arg PYTHON_VERSION="{{ '{{.PYTHON_VERSION}}' }}" \ + --build-arg DEV_MODE="true" \ + --build-arg NAME="{{ '{{.PROJECT_SLUG}}' }}" \ + --build-arg DESCRIPTION="{{ '{{.DESCRIPTION}}' }}" \ + --build-arg TIMESTAMP="{{ '{{.TIMESTAMP}}' }}" \ + --build-arg COMMIT_HASH="{{ '{{.COMMIT_HASH}}' }}" \ + -t {{ '{{.IMAGE_NAME}}' }}-dev:latest \ + . + # Start the container in detached mode + - | + docker run -d \ + --name {{ '{{.PROJECT_SLUG}}' }}-dev \ + -v "$(pwd):/workspace:cached" \ + -v "{{ '{{.PROJECT_SLUG}}' }}-uv-cache:/root/.cache/uv" \ + -e DEV_MODE=true \ + -e PYTHONPATH=/workspace/src \ + --network host \ + --cap-add SYS_PTRACE \ + --security-opt seccomp=unconfined \ + {{ '{{.IMAGE_NAME}}' }}-dev:latest \ + sleep infinity + - | + echo "✅ Development container '{{ '{{.PROJECT_SLUG}}' }}-dev' is running!" + echo "" + echo "To attach to it:" + echo " • VS Code: Use 'Dev Containers: Attach to Running Container' command" + echo " • Terminal: docker exec -it {{ '{{.PROJECT_SLUG}}' }}-dev bash" + echo "" + echo "To stop it: task dev-container-stop" + + dev-container-stop: + desc: Stop and remove development container + cmds: + - docker stop {{ '{{.PROJECT_SLUG}}' }}-dev 2>/dev/null || true + - docker rm {{ '{{.PROJECT_SLUG}}' }}-dev 2>/dev/null || true + - echo "Development container stopped and removed." + clean: desc: Clean up build artifacts, cache files/directories, temp files, etc. cmds: From 0673f38d8987af60800c3311e2bcd70a1f049ac3 Mon Sep 17 00:00:00 2001 From: Jon Zeolla Date: Thu, 18 Sep 2025 11:26:50 -0400 Subject: [PATCH 2/2] Yolo --- .../.devcontainer/README.md" | 12 +++-- .../README.md" | 44 +++++++++++++++++++ .../Taskfile.yml" | 33 ++++++++++++-- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" index 475f2b5..7493750 100644 --- "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/.devcontainer/README.md" @@ -17,13 +17,19 @@ This project includes Dev Container support for VS Code and other compatible edi 2. In VS Code, use Command Palette: `Dev Containers: Attach to Running Container` 3. Select the `{{ cookiecutter.project_slug }}-dev` container -### Option 3: Manual Docker Commands +### Option 3: Command Line Access ```bash # Build and start the dev container task dev-container +# Check if container is running +task dev-container-status + # Access the container shell -docker exec -it {{ cookiecutter.project_slug }}-dev bash +task dev-container-shell + +# Run a specific command +task dev-container-exec CMD="python --version" # Stop the container when done task dev-container-stop @@ -41,7 +47,7 @@ The dev container includes: ## Environment - `DEV_MODE=true` - Installs all development dependencies -- `PYTHONPATH=/workspace/src` - Ensures proper module imports +- Python path set to `/workspace/src` - Ensures proper module imports - Working directory: `/workspace` ## Troubleshooting diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/README.md" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/README.md" index 7467214..f54e567 100644 --- "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/README.md" +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/README.md" @@ -50,6 +50,50 @@ This project is configured with automated dependency management: Both tools are pre-configured and will start working once the repository is pushed to GitHub. +## Development Containers + +This project includes Dev Container support for consistent development environments. + +### Quick Start with VS Code + +1. Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +2. Open this project in VS Code +3. Click "Reopen in Container" when prompted, or use the command palette: `Dev Containers: Reopen in Container` + +### Alternative: Attach to Running Container + +If you prefer to manage the container manually: + +```bash +# Build and start the development container +task dev-container + +# Check container status +task dev-container-status + +# Access the container shell +task dev-container-shell + +# Run a specific command in the container +task dev-container-exec CMD="python --version" + +# Stop the container when done +task dev-container-stop +``` + +To attach from VS Code: Use command palette `Dev Containers: Attach to Running Container` and select `{{ cookiecutter.project_slug }}-dev`. + +### What's Included + +The development container provides: +- Python {{ cookiecutter.python_version }}+ with all project dependencies +- Development tools: uv, Task, pre-commit, git +- VS Code extensions for Python development +- Live code editing with proper volume mounts +- All dependencies installed (including dev dependencies) + +For more details, see [.devcontainer/README.md](.devcontainer/README.md). + ## FAQs For frequently asked questions including release workflow troubleshooting, see our [FAQ documentation](./FAQ.md). diff --git "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" index a724ab8..094fbdd 100644 --- "a/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" +++ "b/{{cookiecutter.project_name|replace(\" \", \"\")}}/Taskfile.yml" @@ -226,11 +226,11 @@ tasks: - | echo "✅ Development container '{{ '{{.PROJECT_SLUG}}' }}-dev' is running!" echo "" - echo "To attach to it:" + echo "To use it:" echo " • VS Code: Use 'Dev Containers: Attach to Running Container' command" - echo " • Terminal: docker exec -it {{ '{{.PROJECT_SLUG}}' }}-dev bash" - echo "" - echo "To stop it: task dev-container-stop" + echo " • Terminal: task dev-container-shell" + echo " • Check status: task dev-container-status" + echo " • Stop: task dev-container-stop" dev-container-stop: desc: Stop and remove development container @@ -239,6 +239,31 @@ tasks: - docker rm {{ '{{.PROJECT_SLUG}}' }}-dev 2>/dev/null || true - echo "Development container stopped and removed." + dev-container-exec: + desc: Execute a command in the development container (default: bash) + vars: + CMD: '{{ '{{.CMD | default "bash"}}' }}' + cmds: + - docker exec -it {{ '{{.PROJECT_SLUG}}' }}-dev {{ '{{.CMD}}' }} + + dev-container-shell: + desc: Open a shell in the development container + cmds: + - task: dev-container-exec + vars: + CMD: bash + + dev-container-status: + desc: Check status of the development container + cmds: + - | + if docker ps --format "table {{ '{{.Names}}' }}" | grep -q "^{{ '{{.PROJECT_SLUG}}' }}-dev$"; then + echo "✅ Development container '{{ '{{.PROJECT_SLUG}}' }}-dev' is running" + else + echo "❌ Development container '{{ '{{.PROJECT_SLUG}}' }}-dev' is not running" + echo "Run 'task dev-container' to start it" + fi + clean: desc: Clean up build artifacts, cache files/directories, temp files, etc. cmds: