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
5 changes: 3 additions & 2 deletions .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
_commit: v1.0.2-4-g02eefe5
_src_path: /home/trisdoan/projects/trobz-python-template
_commit: v1.1.0-3-g2dda840
_src_path: https://github.com/trobz/trobz-python-template.git
author_email: doaminhtri8183@gmail.com
author_username: trisdoan
enable_github_action: true
package_name: trobz_local
project_description: ''
project_name: trobz_local
project_type: cli
publish_to_pypi: false
repository_name: local.py
repository_namespace: trobz
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ __marimo__/
plans/**/*
!plans/templates/*
repomix-output.xml
AGENTS.md
.claude/
.opencode/
release-manifest.json
36 changes: 36 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# AGENTS.md

> Quick reference for AI coding agents.

## Project


- **Type**: CLI (Typer)

- **Language**: Python 3.10+
- **Package manager**: [uv](https://docs.astral.sh/uv/)

## Entry Points


- `trobz_local/main.py` — CLI entry point


## Commands

Run `make help` for all commands. Key ones:

```
make install # Install deps + pre-commit hooks
make check # Lint, format, type-check
make test # Run pytest

```

## Key Files

- `Makefile` — Project commands
- `pyproject.toml` — Dependencies and build config
- `ruff.toml` — Linter/formatter rules

- `tests/` — Test suite (pytest)
22 changes: 0 additions & 22 deletions CLAUDE.md

This file was deleted.

1 change: 1 addition & 0 deletions CLAUDE.md
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,22 @@ A developer tool for automating setup and management of local Odoo development e

## Installation

Install globally using [uv](https://docs.astral.sh/uv/):
### Quick Install (Recommended)

Run the bootstrap script to install all dependencies and `tlc` in one command:

```bash
curl -fsSL https://raw.githubusercontent.com/trobz/local.py/main/bootstrap.sh | bash
```

This installs: `git`, `gh`, `uv`, configures PostgreSQL APT repository, and sets up SSH for GitHub.

### Manual Install

If you already have `uv` installed:

```bash
uv tool install git+ssh://git@github.com:trobz/local.py.git
uv tool install git+https://github.com/trobz/local.py.git
```

## Quick Start
Expand Down Expand Up @@ -106,9 +118,9 @@ See [Configuration Schema](./docs/project-overview-pdr.md#configuration-schema)
## System Requirements

- Python 3.10+
- `uv` package manager
- Linux (Arch, Ubuntu) or macOS
- System tools: `git`, `wget` or `curl`, `sh`
- `curl`
- Sudo privileges (for bootstrap script)

## Documentation

Expand Down
10 changes: 10 additions & 0 deletions assets/odoo_minimal.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Minimal config to set up latest Odoo for development
# Place this file at ~/code/config.toml (or set TLC_CODE_DIR)

versions = ["18.0"]

[tools]
uv = ["odoo-venv", "odoo-addons-path"]

[repos]
odoo = ["odoo"]
137 changes: 137 additions & 0 deletions bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
export PATH="$HOME/.local/bin:$PATH"

# Bootstrap script for trobz_local (tlc)
# Installs prerequisites: git, gh, uv, and trobz_local CLI
# Note: Tool installation (Odoo, PostgreSQL, etc.) is done separately via `tlc install-tools`

echo "=== Bootstrap trobz_local ==="

# Check if user can sudo
check_sudo() {
if ! sudo -v &>/dev/null; then
echo "Error: This script requires sudo privileges."
echo "Please run as a user with sudo access."
exit 1
fi
}

check_sudo

# Detect OS
detect_os() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f /etc/debian_version ]; then
echo "debian"
elif [ -f /etc/fedora-release ]; then
echo "fedora"
elif [ -f /etc/arch-release ]; then
echo "arch"
else
echo "linux"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo "macos"
else
echo "unknown"
fi
}

OS=$(detect_os)
echo "Detected OS: $OS"

# Install git
install_git() {
if command -v git &>/dev/null; then
echo "git is already installed"
return
fi
echo "Installing git..."
case $OS in
debian) sudo apt-get update && sudo apt-get install -y git ;;
fedora) sudo dnf install -y git ;;
arch) sudo pacman -S --noconfirm git ;;
macos) brew install git ;;
*) echo "Please install git manually"; exit 1 ;;
esac
}

# Install gh (GitHub CLI)
install_gh() {
if command -v gh &>/dev/null; then
echo "gh is already installed"
return
fi
echo "Installing gh (GitHub CLI)..."
case $OS in
debian)
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null
sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt-get update && sudo apt-get install -y gh
;;
fedora) sudo dnf install -y gh ;;
arch) sudo pacman -S --noconfirm github-cli ;;
macos) brew install gh ;;
*) echo "Please install gh manually from https://cli.github.com/"; exit 1 ;;
esac
}

# Install uv
install_uv() {
if command -v uv &>/dev/null; then
echo "uv is already installed"
return
fi
echo "Installing uv..."
curl -LsSf https://astral.sh/uv/install.sh | sh
}

# Setup SSH known_hosts for GitHub
setup_github_ssh() {
echo "Setting up SSH known_hosts for GitHub..."
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
echo "GitHub added to known_hosts"
}

# Install trobz_local
install_trobz_local() {
echo "Installing trobz_local..."
uv tool install git+https://github.com/trobz/local.py.git
echo "trobz_local installed (CLI: tlc)"
}

# Main execution
install_git
install_gh
install_uv
setup_github_ssh
install_trobz_local

echo ""
echo "=== Bootstrap complete ==="
echo ""
echo "Prerequisites installed successfully!"
echo " ✓ git"
echo " ✓ gh (GitHub CLI)"
echo " ✓ uv"
echo " ✓ trobz_local (tlc command available)"
echo ""
echo "Next steps:"
echo ""
echo " 1. Install development tools (Odoo, PostgreSQL, etc.):"
echo " tlc install-tools"
echo ""
echo " 2. Initialize your development environment:"
echo " tlc init # Create directory structure"
echo " tlc pull-repos # Clone repositories"
echo " tlc create-venvs # Create virtual environments"
echo ""
echo " 3. Get help:"
echo " tlc --help"
echo ""
20 changes: 12 additions & 8 deletions docs/code-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Four-layer modular design with clear separation of concerns:
| Layer | Module(s) | Responsibility |
|---|---|---|
| **CLI Layer** | `main.py` | Command routing, user interaction, newcomer mode |
| **Implementation** | `installers.py` | Four installation strategies (script, system, npm, uv) |
| **Implementation** | `installers.py`, `postgres.py` | Installation strategies (script, system, npm, uv); PostgreSQL user management |
| **Utility Layer** | `utils.py` | Config validation, platform detection, helpers |
| **Infrastructure** | `concurrency.py`, `exceptions.py` | Parallel execution, custom exceptions |

Expand All @@ -23,6 +23,7 @@ Four-layer modular design with clear separation of concerns:
- **Line Length**: Max 120 characters (ruff.toml config)
- **Import Order**: stdlib → third-party → local (ruff-managed)
- **Active Rules**: YTT, S (security), B, A, C4, T10, SIM, I, C90, E, W, F, PGH, UP, RUF, TRY
- **UI Library**: Rich (progress bars, colored output, trees)

### Type Safety (Mandatory)
- All function signatures must have type hints
Expand Down Expand Up @@ -67,6 +68,7 @@ Config validated at startup. Early detection prevents side effects on invalid in
- **Never use shell=True** - Always pass arguments as list
- **Full paths only** - Use shutil.which() instead of relying on PATH
- **No user input in commands** - Build commands from validated config only
- **SQL injection prevention** - Use psql variable binding (`:\"identifier\"` for names, `:'string'` for values) instead of string interpolation

### Download Security
- **HTTPS enforcement** - Pydantic validator rejects non-HTTPS URLs
Expand All @@ -77,6 +79,7 @@ Config validated at startup. Early detection prevents side effects on invalid in
- Versions: `^(?:\d+\.\d+|master)$` (supports semver and "master" branch)
- UV tools: `^[a-zA-Z0-9][a-zA-Z0-9._\-\[\]@=<>!,]*$`
- Repo names: `^[a-zA-Z0-9._-]+$`
- PostgreSQL usernames: `^[a-zA-Z_][a-zA-Z0-9_]{0,62}$` (max 63 chars, alphanumeric + underscore)
- **Pydantic models** - No ad-hoc parsing of config
- **Ruff S* rules** - Security linting enabled in make check

Expand Down Expand Up @@ -168,13 +171,14 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/):

## File Structure

**Max file size**: 500 LOC (split if larger)
- `main.py`: CLI commands and orchestration (455 LOC)
- `installers.py`: Installation strategies (283 LOC)
- `utils.py`: Config, platform detection, helpers (275 LOC)
- `concurrency.py`: Task runner with progress (61 LOC)
- `exceptions.py`: Custom exception classes (39 LOC)
- `tests/`: pytest unit tests (613 LOC total, 69% coverage)
**Target file size**: 500 LOC; main.py at 523 LOC is exception due to command density.
- `main.py`: CLI commands and orchestration (523 LOC - consolidates 5 command implementations)
- `installers.py`: Installation strategies (389 LOC - 5 installation strategies)
- `postgres.py`: PostgreSQL user management (173 LOC)
- `utils.py`: Config, platform detection, helpers (277 LOC)
- `concurrency.py`: Task runner with progress (60 LOC)
- `exceptions.py`: Custom exception classes (38 LOC)
- `tests/`: pytest unit tests for all modules

**Imports in each module**:
- No circular imports
Expand Down
Loading