itsulu-blog-publisher/README.md
Nicholas Riegel 6702c8390e release: v0.5.0 — establish Odoo 19.0 branch (multi-version support)
Seed the 19.0 series branch from the 17.0 baseline and wire up the
per-Odoo-version structure:
- .odoo-series = 19.0; Dockerfile FROM odoo:19.0; manifest 19.0.0.5.0
- PORTING.md tracks the Odoo-19 API porting checklist
- README retargeted to 19.0 with a porting-in-progress notice
- CHANGELOG v0.5.0 entry

NOTE: code is seeded from 17.0 — the Odoo-19 port is NOT yet verified
(see PORTING.md). Not deploy-ready on a 19.0 instance until the suite
runs green there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 11:15:50 -04:00

285 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ITSulu Blog Publisher — Odoo 19 Addon
**Version:** 0.5.0 · **Odoo series:** 19.0
Automated blog post generation and publishing for Odoo 19.0 Community Edition, powered by generative AI (Anthropic Claude, OpenAI, Google Gemini, or Ollama).
> ⚠️ **Porting in progress.** This `19.0` branch is seeded from the 17.0 baseline; the
> Odoo-19 API port is tracked in [PORTING.md](PORTING.md). Use the `14.0` branch for the
> ITSulu production instance until 19.0 is verified.
> **Versioning** — `MAJOR.MINOR.PATCH` (each 0999). MAJOR = major release for sale / significant change; MINOR = features or performance improvements; PATCH = a single group of commits. See [CHANGELOG.md](CHANGELOG.md) for release notes and [CLAUDE.md](CLAUDE.md) §15 for the full scheme.
> **Odoo version branches** — like [odoo/odoo](https://github.com/odoo/odoo), each Odoo
> Community release lives on its own branch. Supported targets:
> **[`19.0`](../../tree/19.0)** (latest stable) and **[`14.0`](../../tree/14.0)** (the version
> ITSulu runs). Check out the branch matching your Odoo version. Release tags are namespaced by
> series, e.g. `19.0-v0.5.0`.
## Features
### ✨ Core Functionality
- **On-Demand Generation** — Wizard-driven blog post creation via backend form
- **Scheduled Generation** — Three configurable daily cron slots (morning, afternoon, evening)
- **Multi-Provider LLM** — Route requests to Anthropic Claude, OpenAI ChatGPT, Google Gemini, or local Ollama models
- **SEO Automation** — Auto-populate meta titles, descriptions, keywords, and tags
- **Social Media Copy** — Generate platform-specific posts for X, BlueSky, Mastodon, and LinkedIn
- **Auto-Publish** — Publish generated posts immediately or save as drafts for review
- **Topic Queue** — Priority-based topic queue for scheduled generation
- **Notification Emails** — Automated emails with generated content and social copy
- **Generation Audit Trail** — Complete logs with token usage, provider, model, and error tracking
- **Error Recovery** — Retry button on failed generation logs
### 🧠 Supported LLM Providers
| Provider | Model Examples | Config Parameter |
|----------|---|---|
| **Anthropic Claude** | claude-sonnet-4-20250514, claude-opus-4-1 | `itsulu_blog_publisher.anthropic_api_key` |
| **OpenAI** | gpt-4o, gpt-4-turbo | `itsulu_blog_publisher.openai_api_key` |
| **Google Gemini** | gemini-2.0-flash, gemini-pro | `itsulu_blog_publisher.gemini_api_key` |
| **Ollama** | Any local model (mistral, llama2, etc.) | `itsulu_blog_publisher.ollama_base_url` |
### 📊 Test Coverage
**69 automated tests**, all passing on the ITSulu Kubernetes test cluster.
| Test Suite | Count | Status |
|---|---|---|
| Unit Tests (TDD) | 48 | ✅ All Passing |
| Behaviour Tests (BDD) | 15 | ✅ All Passing |
| Performance Benchmarks | 6 | ✅ All Passing |
| **Total** | **69** | **100% ✅** |
**Coverage Areas**:
- Topic queue management (7 tests)
- Generation audit logs (8 tests)
- Social media copy (16 tests)
- Schedule slots (10 tests)
- LLM router dispatch (7 tests)
- E2E / behaviour workflows (15 BDD scenarios)
- Performance SLOs — latency, query count, token usage, concurrency (6 benchmarks)
Tests run as ephemeral Kubernetes jobs in the `itsulu-testing` namespace against a
primed PostgreSQL template database. See [CLAUDE.md](CLAUDE.md) §8 for the K8s test setup.
## Installation
### Prerequisites
- Odoo 19.0 Community
- Python 3.11+
- PostgreSQL 13+
- pip packages: `requests`, `pytest-odoo`, `pytest-bdd`
### Steps
1. **Clone the repository** into your Odoo addons directory:
```bash
git clone https://github.com/itsulu-odoo/itsulu-blog-publisher.git \
/path/to/odoo/addons/itsulu_blog_publisher
```
2. **Install Python dependencies**:
```bash
pip install requests
```
3. **Install the addon** in Odoo (UI or CLI):
```bash
odoo -d mydb -i itsulu_blog_publisher --stop-after-init
```
4. **Configure API keys** in Odoo Settings → Technical → Parameters:
- `itsulu_blog_publisher.anthropic_api_key` (if using Claude)
- `itsulu_blog_publisher.openai_api_key` (if using OpenAI)
- `itsulu_blog_publisher.gemini_api_key` (if using Gemini)
- `itsulu_blog_publisher.ollama_base_url` (if using Ollama, e.g., `http://localhost:11434`)
5. **Configure notification emails** in Settings:
- `itsulu_blog_publisher.notification_emails` (comma-separated list)
## Usage
### 1. Create a Blog Post On-Demand
1. Go to **Blog****Blog Publisher****Generate Now**
2. Enter topic/prompt
3. Select LLM provider and model
4. Choose auto-publish or draft
5. Click **Generate**
The addon will:
- Call the selected LLM provider
- Create a blog.post with generated title, body, SEO fields
- Generate social media copy for enabled platforms
- Send notification email if published
- Log tokens used, provider, model, and generation time
### 2. Schedule Automatic Generation
1. Go to **Blog****Blog Publisher****Schedule Slots**
2. Create/configure 3 slots: Morning, Afternoon, Evening
3. Set trigger time (UTC hours)
4. Choose LLM provider and model per slot
5. Enable auto-publish or save as draft
6. Save and activate
The system will:
- Run active slots at configured times via cron
- Pull next topic from queue (if available) or LLM-chosen topic
- Publish immediately or save for review
- Send notification emails for published posts
### 3. Manage Topic Queue
1. Go to **Blog****Blog Publisher****Topics**
2. Create topics with title, notes, and priority (Urgent/High/Normal)
3. Set state to "Pending"
4. During generation, slots will consume pending topics in priority order
5. Topics move to "Used" state after generation
### 4. Monitor Generation Logs
1. Go to **Blog****Blog Publisher****Generation Logs**
2. View all generation attempts (success/error)
3. Check tokens used, provider, model, duration
4. Retry failed generations using **Retry** button
## Configuration
### Settings
| Parameter | Type | Default | Description |
|---|---|---|---|
| `itsulu_blog_publisher.notification_emails` | Char | (empty) | Comma-separated email addresses for notifications |
| `itsulu_blog_publisher.anthropic_api_key` | Char | (empty) | Anthropic API key for Claude models |
| `itsulu_blog_publisher.openai_api_key` | Char | (empty) | OpenAI API key for ChatGPT models |
| `itsulu_blog_publisher.gemini_api_key` | Char | (empty) | Google Gemini API key |
| `itsulu_blog_publisher.ollama_base_url` | Char | (empty) | Base URL for local Ollama server |
### Email Template
The addon includes a pre-configured email template (`email_template_blog_published`) that:
- Displays blog post title and metadata
- Includes social media copy for each enabled platform
- Links to the published post
- Shows generation stats (tokens, model, time)
Customize by editing the template in **Email****Email Templates**.
## Architecture
### Models
- **itsulu.blog.topic** — Topic queue with priority and state
- **itsulu.blog.generation.log** — Audit trail for all generation attempts
- **itsulu.blog.post.social** — Social media copy linked to blog posts
- **itsulu.blog.schedule** — Configurable cron slots for scheduled generation
### Services
- **llm_router.py** — Dispatcher that routes requests to provider APIs
- **anthropic_provider.py** — Anthropic Claude integration
- **openai_provider.py** — OpenAI ChatGPT integration
- **gemini_provider.py** — Google Gemini integration
- **ollama_provider.py** — Local Ollama model integration
- **image_router.py** — Optional cover image generation (DALL·E, Imagen, Stable Diffusion)
## Development
### Running Tests
```bash
# All tests
pytest addons/itsulu_blog_publisher/tests/ -v
# Specific test file
pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py -v
# Specific test
pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py::TestBlogTopicPriority::test_get_next_topic_returns_highest_priority_pending_topic -v
# BDD scenarios only
pytest addons/itsulu_blog_publisher/tests/test_bdd_steps.py -v
```
### TDD Workflow
This project follows strict TDD discipline (see [CLAUDE.md](CLAUDE.md)):
1. **RED** — Write failing test
2. **GREEN** — Write minimum code to pass
3. **REFACTOR** — Clean up while test stays green
4. **REPEAT** — Next feature
### Code Quality
Pre-commit hooks enforce:
- Black code formatting
- isort import sorting
- pylint-odoo linting
Run before committing:
```bash
pre-commit run --all-files
```
## Troubleshooting
### "Configuration error: API key not configured"
**Cause**: API key parameter not set in Settings
**Solution**: Go to Settings → Technical → Parameters and add the required key for your LLM provider
### "Unknown provider: <name>"
**Cause**: Provider name misspelled or provider not supported
**Solution**: Use one of: `anthropic`, `openai`, `gemini`, `ollama`
### "No blog.post record was created"
**Cause**: LLM response parsing failed or validation error
**Check**: Generation log for error message; verify LLM response format
### "No email sent for published post"
**Cause**: Notification email template not found or recipients not configured
**Solution**:
1. Ensure template exists: **Email****Email Templates** → "Blog Post Published"
2. Set notification emails: **Settings** → Technical → Parameters → `itsulu_blog_publisher.notification_emails`
## Documentation
- [CHANGELOG.md](CHANGELOG.md) — Release notes and version history
- [CLAUDE.md](CLAUDE.md) — Complete TDD framework, testing patterns, versioning scheme, troubleshooting
- [ARCHITECTURE.md](ARCHITECTURE.md) — System design, data flow, API contracts
- [PHASE2_ROADMAP.md](PHASE2_ROADMAP.md) — Phase 2 implementation status
## License
MIT License. See [LICENSE](LICENSE) for details.
## Support
For issues, feature requests, or questions, open an issue on GitLab:
https://gitlab.com/itsulu-odoo/itsulu-blog-publisher/issues
## Roadmap
### Phase 3 (Runboat E2E)
- Playwright end-to-end scenarios
- UI-driven generation workflow testing
- Multi-user collaboration scenarios
### Phase 4 (Performance & Scale)
- Query optimization (N+1 detection)
- Batch generation for multiple topics
- Template caching and pre-rendering
- Performance benchmarks (throughput, latency)
---
**Current Status**: v0.4.8 — test suite green (69/69 passing on ITSulu K8s) ✅
**Last Updated**: 2026-05-30
**Maintainer**: Nicholas Riegel (nicholasr@itsulu.com)