Metadata-Version: 2.4
Name: sum-cli
Version: 3.2.0
Summary: SUM Platform CLI: single control plane for site lifecycle management
Author: Mark Ashton
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/markashton480/sum-platform
Project-URL: Repository, https://github.com/markashton480/sum-platform
Project-URL: Issues, https://github.com/markashton480/sum-platform/issues
Project-URL: Documentation, https://github.com/markashton480/sum-platform/tree/main/docs/dev/cli.md
Keywords: sum,cli,django,wagtail
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1.7
Requires-Dist: packaging>=21.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: gitea
Requires-Dist: httpx>=0.27.0; extra == "gitea"
Dynamic: license-file

# SUM CLI (v3.2)

[![PyPI](https://img.shields.io/pypi/v/sum-cli.svg)](https://pypi.org/project/sum-cli/)

The SUM CLI is the single control plane for deploying and managing SUM Platform client sites on staging and production servers.

## Install

```bash
pip install sum-cli
sum-platform --version
```

### With Gitea Support

If using Gitea instead of GitHub for repository hosting:

```bash
pip install sum-cli[gitea]
```

## Initial Setup

Before using the CLI, configure your infrastructure settings:

```bash
sudo sum-platform setup
```

This interactive command creates `/etc/sum/config.yml` with your staging/production server settings.

## Commands

| Command | Description | Requires Sudo |
|---------|-------------|---------------|
| `setup` | Configure infrastructure settings | Yes |
| `init` | Create new site at `/srv/sum/<name>/` | Yes |
| `update` | Pull updates, migrate, restart | No (staging) |
| `backup` | Database and media backup | No |
| `restore` | Point-in-time database restore | No |
| `monitor` | Check backup health, send alerts | No |
| `promote` | Deploy staging site to production | No |
| `check` | Validate project setup | No |
| `theme` | Theme management (list, check, update) | No |
| `themes` | List themes (deprecated, use `theme list`) | No |

## Theme Management

The `theme` command group provides tools for managing themes in existing projects.

### Listing Themes

```bash
# List local themes (from themes/ directory or SUM_THEME_PATH)
sum-platform theme list

# List remote themes from sum-themes repository
sum-platform theme list --remote
```

### Checking for Updates

```bash
# Compare current theme version against latest available
cd /path/to/project
sum-platform theme check
```

### Viewing Available Versions

```bash
# Show all available versions for a theme
sum-platform theme versions theme_a
```

### Updating Themes

```bash
# Update to latest version
cd /path/to/project
sum-platform theme update

# Update to specific version
sum-platform theme update --version 1.2.0

# Allow downgrade to older version
sum-platform theme update --version 1.0.0 --allow-downgrade

# Force reinstall even if at target version
sum-platform theme update --force
```

Theme updates are atomic with automatic rollback on failure. The lockfile at `.sum/theme.json` tracks version history.

## Site Directory Structure

Each site lives at `/srv/sum/<slug>/`:

```
/srv/sum/<slug>/
├── app/          # Django project (git checkout)
├── venv/         # Python virtualenv
├── static/       # collectstatic output
├── media/        # User uploads
└── backups/      # Database backups
```

### Ownership

The CLI runs as root (`sudo sum-platform init`). After setup, `fix_site_ownership()` sets the final permissions:

| Directory | Owner | Group | Why |
|-----------|-------|-------|-----|
| `app/` | deploy | www-data | Gunicorn reads code; deploy user runs git pulls |
| `static/` | deploy | www-data | collectstatic writes here; Caddy serves directly |
| `media/` | deploy | www-data | Django writes uploads here; Caddy serves directly |
| `venv/` | root | root | Security — prevents application code from modifying its own runtime |
| `backups/` | root | root | Security — prevents application code from accessing/tampering with backups |

The `deploy` user runs gunicorn, owns application files, and is a member of `www-data`. It has no sudo access. Configured in `/etc/sum/config.yml` under `defaults.deploy_user`.

Operations on site files (`app/`, `static/`, `media/`) should run as the deploy user:

```bash
sudo -u deploy /srv/sum/mysite/venv/bin/python /srv/sum/mysite/app/manage.py migrate
sudo -u deploy /srv/sum/mysite/venv/bin/python /srv/sum/mysite/app/manage.py collectstatic
```

Operations on `venv/` and `backups/` require root.

## Creating Sites

### With GitHub

```bash
sudo sum-platform init acme --git-provider github --git-org acme-corp
```

### With Gitea

```bash
sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com
```

### With Gitea (Custom SSH Port)

```bash
sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com --gitea-ssh-port 2222
```

### Without Git

```bash
sudo sum-platform init acme --no-git
```

### Additional Init Options

```bash
sudo sum-platform init acme --git-provider github --git-org acme-corp \
  --theme theme_a \
  --profile sage-stone \
  --content-path /path/to/custom/content
```

### Dev / Testing (Unreleased sum-core)

By default, `init` installs sum-core from a pinned git tag in the boilerplate `requirements.txt`. To test with unreleased changes, use one of these overrides (listed in priority order):

**`SUM_CORE_SOURCE` environment variable** — raw pip requirement line, always takes priority:

```bash
SUM_CORE_SOURCE="-e /path/to/local/core" sudo sum-platform init acme --no-git
SUM_CORE_SOURCE="sum-core==0.8.0" sudo sum-platform init acme --no-git
```

**`--dev` flag** — editable install from the monorepo using an absolute path (must run from within the monorepo):

```bash
cd /path/to/sum-platform
sudo sum-platform init acme --dev --no-git
```

**`--core-ref` flag** — install from a specific git branch or tag:

```bash
sudo sum-platform init acme --core-ref develop --no-git
sudo sum-platform init acme --core-ref feature/my-branch --no-git
```

`--dev` and `--core-ref` are mutually exclusive. `SUM_CORE_SOURCE` silently overrides both.

## Managing Sites

```bash
# Update a deployed site (pull, migrate, restart)
sum-platform update acme

# Backup database and media
sum-platform backup acme --include-media

# Promote staging to production
sum-platform promote acme --domain acme.example.com

# Validate project setup
sum-platform check acme

# List available themes
sum-platform theme list

# List remote themes with latest versions
sum-platform theme list --remote

# Check for theme updates in a project
cd /srv/sum/acme && sum-platform theme check

# Update theme to latest version
cd /srv/sum/acme && sum-platform theme update
```

## Backup and Recovery

```bash
# Create differential backup
sum-platform backup acme

# Create full backup
sum-platform backup acme --type=full

# List available backups
sum-platform backup acme --list

# List restore points with details
sum-platform restore acme --list

# Restore to specific point in time
sum-platform restore acme --time "2024-01-15 14:30:00"

# Restore to latest backup
sum-platform restore acme --latest

# Clean up pre-restore data after verifying restore
sum-platform restore acme --latest --cleanup
```

## Backup Monitoring

The `monitor` command checks backup freshness and sends email alerts for stale backups.

```bash
# Check all sites, send alerts for problems
sum-platform monitor

# Check without sending alerts
sum-platform monitor --no-alerts

# Verbose output (show all sites)
sum-platform monitor -v
```

### Cron Setup

Add to crontab for hourly monitoring:

```cron
0 * * * * /usr/local/bin/sum-platform monitor
```

Alerts are sent when:
- Backup is older than 48 hours
- Backup status file is missing

## Configuration

### Global Config (`/etc/sum/config.yml`)

Infrastructure settings only. Created via `sum-platform setup`.

```yaml
agency:
  name: Your Agency Name

staging:
  server: staging.example.com
  domain_pattern: "{slug}.staging.example.com"
  base_dir: /srv/sum

production:
  server: prod.example.com
  ssh_host: 10.0.0.1
  base_dir: /srv/sum

templates:
  dir: /opt/your-ops/infra
  systemd: systemd/sum-site-gunicorn.service.template
  caddy: caddy/Caddyfile.template

defaults:
  theme: theme_a
  seed_profile: starter
  deploy_user: deploy
  postgres_port: 5432

backups:
  storage_box:
    host: u123456.your-storagebox.de
    user: u123456
    port: 23
    ssh_key: /etc/sum/backup-key
    base_path: /backups
  retention:
    full_backups: 2
    diff_backups: 7
  alerts:
    email: alerts@agency.com
```

### Site Config (`/srv/sum/<site>/.sum/config.yml`)

Per-site configuration. Auto-created when you run `init`.

**GitHub site:**
```yaml
site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git:
  provider: github
  org: acme-corp
```

**Gitea site:**
```yaml
site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git:
  provider: gitea
  org: clients
  url: https://gitea.agency.com
  ssh_port: 2222
  token_env: GITEA_TOKEN
```

**No-git site:**
```yaml
site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git: null
```

## Git Provider Setup

### GitHub

Requires the GitHub CLI (`gh`) to be installed and authenticated:

```bash
gh auth login
```

### Gitea

Set the API token environment variable:

```bash
export GITEA_TOKEN=your-token-here
```

Or use a custom environment variable name:

```bash
sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com --gitea-token-env MY_GITEA_TOKEN
```

## Development Install (monorepo)

```bash
pip install -e ./cli
```
