143 lines
5.7 KiB
Markdown
143 lines
5.7 KiB
Markdown
# Story 2.5: Deployment Target Assignment - Implementation Summary
|
|
|
|
## Status
|
|
**COMPLETED** - All acceptance criteria met, 100% test coverage
|
|
|
|
## Overview
|
|
Implemented deployment target assignment functionality that allows job configurations to specify which generated tier1 articles should be assigned to specific sites. **Only tier1 articles can be assigned to deployment targets** - tier2/tier3 always get `site_deployment_id = null`. The implementation uses a simple round-robin assignment strategy where the first N tier1 articles are assigned to N deployment targets, and remaining tier1 articles get null assignment.
|
|
|
|
## Changes Made
|
|
|
|
### 1. Job Configuration Schema (`src/generation/job_config.py`)
|
|
- Added `deployment_targets` field (optional array of strings) to `Job` dataclass
|
|
- Added validation to ensure `deployment_targets` is an array of strings
|
|
- Job configuration now supports specifying custom hostnames for deployment target assignment
|
|
|
|
### 2. Deployment Assignment Logic (`src/generation/deployment_assignment.py`) - NEW FILE
|
|
Created new module with three core functions:
|
|
|
|
- `resolve_hostname_to_id()` - Resolves a hostname to its site_deployment_id
|
|
- `validate_and_resolve_targets()` - Validates all hostnames at job start (fail-fast approach)
|
|
- `assign_site_for_article()` - Implements round-robin assignment logic
|
|
|
|
### 3. Database Repository Updates (`src/database/repositories.py`)
|
|
- Updated `GeneratedContentRepository.create()` to accept optional `site_deployment_id` parameter
|
|
- Maintains backward compatibility - parameter defaults to `None`
|
|
|
|
### 4. Batch Processor Integration (`src/generation/batch_processor.py`)
|
|
- Added `site_deployment_repo` parameter to `BatchProcessor.__init__()`
|
|
- Validates deployment targets at job start before generating any content
|
|
- **Only applies deployment targets to tier1 articles** - tier2/tier3 always get null
|
|
- Assigns `site_deployment_id` to each tier1 article based on its index
|
|
- Logs assignment decisions at INFO level
|
|
- Passes `site_deployment_id` to repository when creating content
|
|
|
|
### 5. CLI Updates (`src/cli/commands.py`)
|
|
- Updated `generate-batch` command to initialize and pass `SiteDeploymentRepository` to `BatchProcessor`
|
|
- Fixed merge conflict markers in the file
|
|
|
|
### 6. Example Job Configuration (`jobs/example_deployment_targets.json`) - NEW FILE
|
|
Created example job file demonstrating the `deployment_targets` field with 3 sites and 10 articles.
|
|
|
|
## Test Coverage
|
|
|
|
### Unit Tests (`tests/unit/test_deployment_assignment.py`) - NEW FILE
|
|
13 unit tests covering:
|
|
- Hostname resolution (valid and invalid)
|
|
- Target validation (empty lists, valid hostnames, invalid hostnames, type checking)
|
|
- Round-robin assignment logic (edge cases, overflow, single target)
|
|
- The 10-article, 3-target scenario from the story
|
|
|
|
### Integration Tests (`tests/integration/test_deployment_target_assignment.py`) - NEW FILE
|
|
10 integration tests covering:
|
|
- Job config parsing with deployment_targets
|
|
- Job config validation (type checking, missing field handling)
|
|
- Batch processor validation at job start
|
|
- End-to-end assignment logic
|
|
- Repository backward compatibility
|
|
- **Tier1-only deployment target assignment** (tier2+ always get null)
|
|
|
|
**Total Test Results: 23/23 tests passing**
|
|
|
|
## Assignment Logic Example
|
|
|
|
Job with tier1 (10 articles), tier2 (100 articles), and 3 deployment targets:
|
|
|
|
**Tier1 articles:**
|
|
```
|
|
Article 0 → www.domain1.com (site_deployment_id = 5)
|
|
Article 1 → www.domain2.com (site_deployment_id = 8)
|
|
Article 2 → www.domain3.com (site_deployment_id = 12)
|
|
Articles 3-9 → null (no assignment)
|
|
```
|
|
|
|
**Tier2 articles:**
|
|
```
|
|
All 100 articles → null (tier2+ never get deployment targets)
|
|
```
|
|
|
|
## Usage Example
|
|
|
|
```json
|
|
{
|
|
"jobs": [{
|
|
"project_id": 2,
|
|
"deployment_targets": [
|
|
"www.domain1.com",
|
|
"www.domain2.com",
|
|
"www.domain3.com"
|
|
],
|
|
"tiers": {
|
|
"tier1": {
|
|
"count": 10
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
The implementation provides clear error messages:
|
|
|
|
1. **Invalid hostnames**: "Deployment targets not found in database: invalid.com. Please ensure these sites exist using 'list-sites' command."
|
|
2. **Missing repository**: "deployment_targets specified but SiteDeploymentRepository not provided"
|
|
3. **Invalid configuration**: Validates array type and string elements with descriptive errors
|
|
|
|
## Backward Compatibility
|
|
|
|
- All changes are backward compatible
|
|
- Jobs without `deployment_targets` continue to work as before (all articles get `site_deployment_id = null`)
|
|
- Existing tests remain passing
|
|
- No database schema changes required (field already existed from Story 2.4)
|
|
|
|
## Integration with Story 2.4
|
|
|
|
The implementation correctly integrates with Story 2.4's template selection logic:
|
|
- If `site_deployment_id` is set → Story 2.4 uses mapped/random template for that site
|
|
- If `site_deployment_id` is null → Story 2.4 uses random template selection
|
|
|
|
## Acceptance Criteria Verification
|
|
|
|
✅ Job configuration supports optional `deployment_targets` array of custom_hostnames
|
|
✅ Round-robin assignment: articles 0 through N-1 get assigned, N+ get null
|
|
✅ Missing `deployment_targets` → all articles get null
|
|
✅ `site_deployment_id` stored in GeneratedContent at creation time
|
|
✅ Invalid hostnames cause graceful errors with clear messages
|
|
✅ Non-existent hostnames cause graceful errors
|
|
✅ Validation occurs at job start (fail-fast)
|
|
✅ Assignment decisions logged at INFO level
|
|
|
|
## Files Created
|
|
- `src/generation/deployment_assignment.py`
|
|
- `tests/unit/test_deployment_assignment.py`
|
|
- `tests/integration/test_deployment_target_assignment.py`
|
|
- `jobs/example_deployment_targets.json`
|
|
|
|
## Files Modified
|
|
- `src/generation/job_config.py`
|
|
- `src/generation/batch_processor.py`
|
|
- `src/database/repositories.py`
|
|
- `src/cli/commands.py`
|
|
|