# {package_name}

Database-driven application using [half-orm](https://github.com/half-orm/half-orm) with [half-orm-dev](https://github.com/half-orm/half-orm-dev) workflow.

**Database:** `{dbname}`
**Generated with:** half-orm-dev=={hop_version}

---

## 🚀 Quick Start

### Prerequisites

```bash
# Install half-orm-dev (includes half-orm)
# IMPORTANT: Install the version specified in .hop/config.
#   Replace <version> by the value of hop_version.
pip install half-orm-dev==<version>
```

**Version requirement:** This project requires `half-orm-dev >= {hop_version}`

### Clone This Project

```bash
# Clone project with automatic database setup (use git_origin in .hop/config)
half_orm dev clone <git_origin>
```

This will:
- Clone the repository and checkout `ho-prod` branch
- Configure database connection in `/etc/half_orm/{dbname}` or `${{HALFORM_CONF_DIR}}/{dbname}`
- Restore production schema from `.hop/model/schema.sql`
- Generate Python ORM classes in `{package_name}/` directory

---

## 📖 Development Workflow

This project uses **half-orm-dev** for database versioning and patch management.

### 1. Create a Release

```bash
# Create new minor release (e.g., 0.17.0)
half_orm dev release create minor

# Creates ho-release/0.17.0 branch
# Creates .hop/releases/0.17.0-patches.toml
```

### 2. Create a Patch

# Create patch (auto-added as candidate)
half_orm dev patch create <number>-<description>

# Example: Create user authentication patch
half_orm dev patch create 456-user-auth

# Creates ho-patch/456-user-auth branch
# Creates Patches/456-user-auth/ directory
```

### 3. Develop Your Changes

```bash
# Add SQL migration
echo "CREATE TABLE users (id SERIAL PRIMARY KEY, username TEXT);" > Patches/456-user-auth/1-create-users.sql

# Add Python migration (optional)
cat > Patches/456-user-auth/2-seed-data.py << 'EOF'
from {package_name}.public.users import Users

def apply(model):
    Users(username='admin').ho_insert()
EOF

# Apply patch to test database
half_orm dev patch apply

# Generated ORM classes available in {package_name}/
from {package_name}.public.users import Users
user = Users(username='john').ho_insert()
```

### 4. Test Your Changes

```bash
# Run tests (pytest must be configured)
pytest tests/

# half-orm-dev validates:
# - Patch SQL syntax
# - Patch idempotency (can be applied twice)
# - Test suite passes with full release context
```

### 5. Merge Patch into Release

```bash
# Merge patch (automatic validation + tests)
half_orm dev patch merge

# What happens:
# 1. Creates temp validation branch
# 2. Applies ALL staged patches + your patch
# 3. Runs pytest tests/
# 4. If tests pass → merges into ho-release/X.Y.Z
# 5. Changes patch status to "staged" in TOML
# 6. Deletes patch branch
```

### 6. Promote Release

```bash
# Stage → RC (first release candidate)
half_orm dev release promote rc

# Creates .hop/releases/0.17.0-rc1.txt snapshot
# Tags ho-release-0.17.0-rc1

# RC → Production (after validation)
half_orm dev release promote prod

# Merges into ho-prod branch
# Creates .hop/releases/0.17.0.txt
# Tags production-0.17.0
# Generates .hop/model/schema-0.17.0.sql
```

---

## 🔧 Common Commands

### Status & Information

```bash
half_orm dev check              # Show repository state
```

### Patch Management

```bash
half_orm dev patch create       # create a new patch for release
half_orm dev patch apply        # Apply patch to dev database
half_orm dev patch merge        # Integrate patch into release
```

### Release Management

```bash
half_orm dev release create <level>     # Create release (patch/minor/major)
half_orm dev release promote rc         # Stage → RC
half_orm dev release promote prod       # RC → Production
```

### Production Deployment

```bash
# On production server
half_orm dev update             # Check available releases
half_orm dev upgrade <version>  # Deploy specific version
```

---

## 📁 Project Structure

```
{package_name}/
├── .hop/                       # half-orm-dev metadata
│   ├── config                  # Repository configuration
│   ├── model/                  # Database schemas and data
│   │   ├── schema.sql          # Current production schema (symlink)
│   │   ├── schema-X.Y.Z.sql    # Versioned schemas
│   │   ├── metadata-X.Y.Z.sql  # half_orm_meta data dumps
│   │   └── data-X.Y.Z.sql      # Reference data from @HOP:data patches
│   └── releases/               # Release tracking files
│       ├── X.Y.Z-patches.toml  # Development releases (mutable)
│       ├── X.Y.Z-rcN.txt       # Release candidates (immutable)
│       └── X.Y.Z.txt           # Production releases (immutable)
├── Patches/                    # Patch directories
│   └── <id>-<description>/     # Individual patch files
│       ├── *.sql               # SQL migrations (numbered)
│       └── *.py                # Python migrations (optional)
├── {package_name}/             # Generated ORM package
│   └── <schema>/               # schema classes
└── tests/                      # Test suite (pytest)
```

---

## 🌿 Git Branch Structure

- **`ho-prod`**: Production branch (stable, source of truth)
- **`ho-release/X.Y.Z`**: Release integration branches (temporary)
- **`ho-patch/ID`**: Patch development branches (temporary)

All development happens on patch branches, merged into release branches, then promoted to production.

---

## 💾 Data Persistence (@HOP:data)

For reference data that must be loaded with every database installation (lookup tables, default roles, etc.), use the `@HOP:data` annotation:

```sql
-- @HOP:data
-- This file will be included in model/data-X.Y.Z.sql

INSERT INTO roles (name, description)
VALUES ('admin', 'Administrator')
ON CONFLICT (name) DO NOTHING;

INSERT INTO permissions (name)
VALUES ('read'), ('write'), ('delete')
ON CONFLICT DO NOTHING;
```

### How it works

1. **In patches**: SQL files starting with `-- @HOP:data` contain reference data
2. **Production promote**: All `@HOP:data` files are consolidated into `model/data-X.Y.Z.sql`
3. **Clone/Restore**: Data files are loaded automatically after schema restoration
4. **Production upgrade**: Data is inserted via normal patch application (no special handling)

### Best practices

- Use `ON CONFLICT DO NOTHING` or `ON CONFLICT DO UPDATE` for idempotency
- Keep data files small and focused (one concern per file)
- Number your SQL files to control execution order: `01_roles.sql`, `02_permissions.sql`
- Only use for **reference data**, not user-generated data

---

## 📚 Documentation

- **half-orm-dev**: https://github.com/half-orm/half-orm-dev
- **half-orm**: https://github.com/half-orm/half-orm
- **Workflow guide**: https://github.com/half-orm/half-orm-dev#readme

---

## 🆘 Getting Help

```bash
half_orm dev --help             # General help
half_orm dev patch --help       # Patch commands
half_orm dev release --help     # Release commands
```

---

## ⚠️ Important Notes

1. **Always work on patch branches** - Never commit directly to ho-prod or ho-release
2. **Test before merging** - `patch merge` runs tests automatically
3. **Sequential releases** - Only the smallest version in preparation can be promoted
4. **Idempotent patches** - SQL must be replayable (use `IF NOT EXISTS`, etc.)
5. **Production schema** - `.hop/model/schema.sql` is the source of truth

---

Generated by half-orm-dev {hop_version}
