ITSulu Blog Publisher Odoo addon
Find a file
Nicholas Riegel 2cb2a48b98 fix: deploy E2E tests on ITSulu K8s cluster instead of external Runboat
Updated CI/CD pipeline to run E2E tests on the ITSulu K8s cluster
(itsulu-testing namespace) instead of using external Runboat service.

.gitlab-ci.yml Changes:
- Removed preview stage (no external Runboat dependency)
- Removed e2e_tests dependency on runboat_preview
- Updated e2e_tests job to run on K8s cluster:
  * Uses bitnami/kubectl image for K8s access
  * Configures kubectl with KUBE_CONFIG secret
  * Creates ephemeral E2E test job on K8s
  * initContainer: Creates test database from template
  * container: Installs Odoo, addon, Playwright, runs pytest
  * Waits for job completion and downloads report
  * Reports available in GitLab artifacts
- Consolidated performance tests into unit_tests stage (same runner)

K8s Job Manifest (inline YAML):
- Namespace: itsulu-testing
- Init container: postgres:15-alpine for DB setup
- Test container: blog-publisher Docker image
- Volumes: emptyDir for test results
- TTL: 3600s (1 hour) for log retention
- Uses existing secrets: test-db-info, gitlab-docker-creds

e2e/conftest.py Changes:
- Updated docstring: "Runs on ITSulu K8s cluster"
- Changed RUNBOAT_TIMEOUT → K8S_TIMEOUT (300s)
- Updated wait_for_odoo() to mention K8s namespace in error
- Increased timeout: 180s → 300s (Odoo init + addon install)

Required CI/CD Variables (now reduced):
- KUBE_CONFIG: base64-encoded kubeconfig for itsulu-testing namespace
  * Only one variable needed (replaces 3 Runboat variables)
  * Must have permissions to create Jobs in itsulu-testing namespace

Prerequisites (K8s cluster):
- test-db-svc: PostgreSQL service in itsulu-testing namespace
- odoo_template: Pre-seeded database
- gitlab-docker-creds: Secret for image pull
- test-runner: ServiceAccount with Job create permissions

Benefits:
- No external service dependency
- Leverages existing ITSulu K8s infrastructure
- Full isolation per test run (ephemeral jobs)
- Persistent logs via TTL
- Cost-effective (uses existing cluster)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-30 00:58:46 -04:00
.claude docs: add Kubernetes test infrastructure documentation 2026-05-29 18:13:32 -04:00
addons/itsulu_blog_publisher feat: add performance benchmark tests for Phase 3 2026-05-30 00:51:53 -04:00
docs Add comprehensive BDD framework documentation 2026-05-29 12:42:54 -04:00
e2e fix: deploy E2E tests on ITSulu K8s cluster instead of external Runboat 2026-05-30 00:58:46 -04:00
templates Initialized from 'GitLab CI/CD components' project template 2025-03-19 11:40:54 +01:00
.gitlab-ci.yml fix: deploy E2E tests on ITSulu K8s cluster instead of external Runboat 2026-05-30 00:58:46 -04:00
ARCHITECTURE.md docs: add Kubernetes test infrastructure documentation 2026-05-29 18:13:32 -04:00
CLAUDE.md docs: add E2E testing and performance SLO documentation to CLAUDE.md 2026-05-30 00:52:37 -04:00
conftest.py fix: auto-install addon via conftest for pytest-odoo 2026-05-29 22:45:54 -04:00
conftest_runner.py fix: auto-install addon via conftest for pytest-odoo 2026-05-29 22:45:54 -04:00
Dockerfile fix: auto-install addon via conftest for pytest-odoo 2026-05-29 22:45:54 -04:00
LICENCE Initialized from 'GitLab CI/CD components' project template 2025-03-19 11:40:54 +01:00
main.py Claude Sonnet 4.6 2026-05-29 01:40:58 -04:00
PHASE2_ROADMAP.md docs: mark Phase 2 as complete with final status 2026-05-30 00:47:09 -04:00
PHASE3_DEPLOYMENT_CHECKLIST.md docs: add Phase 3 deployment checklist with CI/CD variable setup 2026-05-30 00:55:38 -04:00
PHASE3_ROADMAP.md feat: integrate Runboat E2E testing and performance tests into CI/CD pipeline 2026-05-30 00:54:59 -04:00
README.md docs: add comprehensive project README with features and usage guide 2026-05-30 00:46:19 -04:00

ITSulu Blog Publisher — Odoo 17 Addon

Automated blog post generation and publishing for Odoo 17 Community Edition, powered by generative AI (Anthropic Claude, OpenAI, Google Gemini, or Ollama).

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

Phase 2 Complete: 63 automated tests across 6 test files

Test Suite Count Status
Unit Tests (TDD) 48 All Passing
Behavior Tests (BDD) 15 All Passing
Total 63 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 workflows (15 BDD scenarios)

Installation

Prerequisites

  • Odoo 17.0 Community
  • Python 3.10+
  • PostgreSQL 13+
  • pip packages: requests, pytest-odoo, pytest-bdd

Steps

  1. Clone the repository into your Odoo addons directory:
git clone https://github.com/itsulu-odoo/itsulu-blog-publisher.git \
  /path/to/odoo/addons/itsulu_blog_publisher
  1. Install Python dependencies:
pip install requests
  1. Install the addon in Odoo (UI or CLI):
odoo -d mydb -i itsulu_blog_publisher --stop-after-init
  1. 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)
  2. Configure notification emails in Settings:

    • itsulu_blog_publisher.notification_emails (comma-separated list)

Usage

1. Create a Blog Post On-Demand

  1. Go to BlogBlog PublisherGenerate 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 BlogBlog PublisherSchedule 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 BlogBlog PublisherTopics
  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 BlogBlog PublisherGeneration 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 EmailEmail 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

# 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):

  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:

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: "

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: EmailEmail Templates → "Blog Post Published"
  2. Set notification emails: Settings → Technical → Parameters → itsulu_blog_publisher.notification_emails

Documentation

License

MIT License. See 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: Phase 2 Complete (63/63 tests passing)
Last Updated: 2026-05-30
Maintainer: Nicholas Riegel (nicholasr@itsulu.com)