Merge branch 'main' into dev
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# NFOGuard Environment Variables
|
||||
|
||||
# User and Group IDs
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
|
||||
# Timezone
|
||||
TZ=UTC
|
||||
|
||||
# Media path (for read-only access to scan NFO files)
|
||||
MEDIA_PATH=/path/to/your/media
|
||||
|
||||
# Database settings (if using PostgreSQL)
|
||||
# DB_USER=nfoguard
|
||||
# DB_PASSWORD=your_secure_password
|
||||
|
||||
# Emby Plugin Deployment - Bind Mount Method (Recommended)
|
||||
# Set this to the path where Emby plugins are installed on your host
|
||||
# Common paths:
|
||||
# - /var/lib/emby/plugins (native Emby install)
|
||||
# - /path/to/emby/config/plugins (Docker Emby)
|
||||
# - /config/plugins (linuxserver.io Emby)
|
||||
EMBY_PLUGINS_PATH=/path/to/emby/plugins
|
||||
|
||||
# NFOGuard specific settings
|
||||
DEBUG=false
|
||||
PATH_DEBUG=false
|
||||
SUPPRESS_TVDB_WARNINGS=true
|
||||
@@ -0,0 +1,141 @@
|
||||
# NFOGuard Environment Configuration Template
|
||||
# Copy this to .env and customize for your setup
|
||||
|
||||
# ===========================================
|
||||
# MEDIA PATHS (REQUIRED)
|
||||
# ===========================================
|
||||
# Paths where your movies and TV shows are stored inside the container
|
||||
# Adjust these to match YOUR directory structure
|
||||
TV_PATHS=/media/TV/tv,/media/TV/tv6
|
||||
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6
|
||||
|
||||
# ===========================================
|
||||
# DATABASE CONFIGURATION
|
||||
# ===========================================
|
||||
# NFOGuard SQLite database location
|
||||
DB_PATH=/app/data/media_dates.db
|
||||
|
||||
# ===========================================
|
||||
# RADARR DATABASE CONNECTION (REQUIRED)
|
||||
# ===========================================
|
||||
# Connection to Radarr's PostgreSQL database
|
||||
# NOTE: Database password should be set in .env.secrets file
|
||||
RADARR_DB_HOST=radarr-postgres
|
||||
RADARR_DB_PORT=5432
|
||||
RADARR_DB_NAME=radarr
|
||||
RADARR_DB_USER=radarr
|
||||
|
||||
# ===========================================
|
||||
# RADARR API (OPTIONAL - for fallback)
|
||||
# ===========================================
|
||||
# Only needed if you want API fallback (not recommended for performance)
|
||||
# NOTE: API key should be set in .env.secrets file
|
||||
RADARR_URL=http://radarr:7878
|
||||
|
||||
# ===========================================
|
||||
# SONARR API (REQUIRED for Enhanced TV NFOs - v0.6.0+)
|
||||
# ===========================================
|
||||
# Required for TV processing and enhanced NFO generation with metadata
|
||||
# NOTE: API key should be set in .env.secrets file
|
||||
SONARR_URL=http://sonarr:8989
|
||||
|
||||
# ===========================================
|
||||
# EXTERNAL APIs FOR DIGITAL RELEASE DATES
|
||||
# ===========================================
|
||||
# NOTE: All API keys should be set in .env.secrets file
|
||||
# See .env.secrets.template for required keys:
|
||||
# - TMDB_API_KEY (recommended for digital release dates)
|
||||
# - OMDB_API_KEY (optional for DVD/digital release dates)
|
||||
# - JELLYSEERR_API_KEY (optional for additional digital release data)
|
||||
|
||||
# Jellyseerr URL (optional)
|
||||
JELLYSEERR_URL=http://jellyseerr:5055
|
||||
|
||||
# ===========================================
|
||||
# NFO MANAGEMENT
|
||||
# ===========================================
|
||||
# Whether to create/update .nfo files
|
||||
MANAGE_NFO=true
|
||||
|
||||
# Whether to fix file modification times to match import dates
|
||||
FIX_DIR_MTIMES=true
|
||||
|
||||
# Whether to add <lockdata> tags to prevent metadata drift
|
||||
LOCK_METADATA=true
|
||||
|
||||
# Brand name to add to NFO files
|
||||
MANAGER_BRAND=NFOGuard
|
||||
|
||||
# ===========================================
|
||||
# PROCESSING SETTINGS
|
||||
# ===========================================
|
||||
# Delay before processing batched webhook events (seconds)
|
||||
BATCH_DELAY=5.0
|
||||
|
||||
# Maximum concurrent series processing
|
||||
MAX_CONCURRENT_SERIES=3
|
||||
|
||||
# Movie date strategy: import_then_digital or digital_then_import
|
||||
MOVIE_PRIORITY=import_then_digital
|
||||
|
||||
# Smart fallback: prefer release dates over file dates for manual imports (true/false)
|
||||
PREFER_RELEASE_DATES_OVER_FILE_DATES=true
|
||||
|
||||
# Allow file dates as absolute last resort (true/false)
|
||||
# If false, movies with no valid import AND no release dates will be skipped entirely
|
||||
ALLOW_FILE_DATE_FALLBACK=false
|
||||
|
||||
# Fallback priority order when no valid Radarr import exists (comma-separated)
|
||||
# Options: digital, physical, theatrical
|
||||
# digital = VOD/streaming release, physical = DVD/Blu-ray, theatrical = cinema release
|
||||
RELEASE_DATE_PRIORITY=digital,physical,theatrical
|
||||
|
||||
# Smart date validation: automatically prefer theatrical over unreasonably late digital/physical dates
|
||||
# Example: "The Craft (1996)" theatrical vs "The Craft (2022)" physical → chooses 1996 theatrical
|
||||
ENABLE_SMART_DATE_VALIDATION=true
|
||||
|
||||
# Maximum reasonable gap between theatrical and digital/physical release (in years)
|
||||
# If digital/physical is more than this many years after theatrical, prefer theatrical instead
|
||||
MAX_RELEASE_DATE_GAP_YEARS=10
|
||||
|
||||
# TMDB country for regional release date preferences
|
||||
TMDB_COUNTRY=US
|
||||
|
||||
# TMDB release type priority (comma-separated numbers)
|
||||
# 1=Premiere, 2=Limited Theatrical, 3=Theatrical, 4=Digital, 5=Physical, 6=TV Premiere
|
||||
# Default: 4,5,3,2,6,1 (Digital → Physical → Theatrical → Limited → TV → Premiere)
|
||||
TMDB_TYPE_PRIORITY=4,5,3,2,6,1
|
||||
|
||||
# When to query APIs: always, if_missing, never
|
||||
MOVIE_POLL_MODE=always
|
||||
|
||||
# Update mode: backfill_only or overwrite
|
||||
MOVIE_DATE_UPDATE_MODE=backfill_only
|
||||
|
||||
# ===========================================
|
||||
# TV SERIES PROCESSING
|
||||
# ===========================================
|
||||
# Season directory naming format (supports {season} placeholder)
|
||||
# Examples: "Season {season:02d}" -> "Season 01", "S{season:02d}" -> "S01"
|
||||
TV_SEASON_DIR_FORMAT=Season {season:02d}
|
||||
|
||||
# Season directory detection pattern (lowercase, what to look for at start of dir name)
|
||||
# Examples: "season " -> matches "Season 01", "s" -> matches "S01", "season" -> matches "Season01"
|
||||
TV_SEASON_DIR_PATTERN=season
|
||||
|
||||
# TV webhook processing mode (v0.6.0+)
|
||||
# targeted = Only process episodes mentioned in webhook (efficient, recommended)
|
||||
# series = Process entire series directory (comprehensive, current default)
|
||||
TV_WEBHOOK_PROCESSING_MODE=targeted
|
||||
|
||||
# ===========================================
|
||||
# LOGGING
|
||||
# ===========================================
|
||||
# Enable debug logging
|
||||
DEBUG=false
|
||||
|
||||
# ===========================================
|
||||
# SERVER
|
||||
# ===========================================
|
||||
# Port to run the webhook server on
|
||||
PORT=8080
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# NFOGuard Setup Guide
|
||||
|
||||
## 🔐 Secure Configuration Setup
|
||||
|
||||
NFOGuard now uses a **two-file configuration system** for better security and easier troubleshooting:
|
||||
|
||||
- **`.env`** - Main configuration (safe to share for debugging)
|
||||
- **`.env.secrets`** - Sensitive API keys and passwords (never commit to git)
|
||||
|
||||
### Step 1: Copy Configuration Templates
|
||||
|
||||
```bash
|
||||
# Copy main configuration
|
||||
cp .env.template .env
|
||||
|
||||
# Copy secrets configuration
|
||||
cp .env.secrets.template .env.secrets
|
||||
```
|
||||
|
||||
### Step 2: Configure Main Settings
|
||||
|
||||
Edit your `.env` file with your specific paths and preferences:
|
||||
|
||||
```bash
|
||||
# Media paths (adjust to your directory structure)
|
||||
TV_PATHS=/media/TV/tv,/media/TV/tv6
|
||||
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6
|
||||
|
||||
# Database connection details
|
||||
RADARR_DB_HOST=radarr-postgres
|
||||
RADARR_DB_PORT=5432
|
||||
RADARR_DB_NAME=radarr
|
||||
RADARR_DB_USER=radarr
|
||||
|
||||
# Processing preferences
|
||||
PREFER_RELEASE_DATES_OVER_FILE_DATES=true
|
||||
ALLOW_FILE_DATE_FALLBACK=false
|
||||
RELEASE_DATE_PRIORITY=digital,physical,theatrical
|
||||
|
||||
# TV webhook processing mode (v0.6.0+)
|
||||
TV_WEBHOOK_PROCESSING_MODE=targeted
|
||||
```
|
||||
|
||||
### Step 3: Configure Secrets
|
||||
|
||||
Edit your `.env.secrets` file with your actual API keys and passwords:
|
||||
|
||||
```bash
|
||||
# Database password
|
||||
RADARR_DB_PASSWORD=your_actual_radarr_password
|
||||
|
||||
# TMDB API key (required for release date detection)
|
||||
TMDB_API_KEY=your_actual_tmdb_api_key
|
||||
|
||||
# Sonarr API key (REQUIRED for v0.6.0+ Enhanced TV NFO Generation)
|
||||
SONARR_API_KEY=your_actual_sonarr_api_key
|
||||
|
||||
# Optional API keys
|
||||
RADARR_API_KEY=your_radarr_api_key
|
||||
OMDB_API_KEY=your_omdb_api_key
|
||||
```
|
||||
|
||||
### Step 4: Verify Configuration
|
||||
|
||||
Test your setup:
|
||||
|
||||
```bash
|
||||
# Test database connections
|
||||
curl -X POST "http://localhost:8080/test/bulk-update"
|
||||
|
||||
# Test movie scanning
|
||||
curl -X POST "http://localhost:8080/test/movie-scan"
|
||||
|
||||
# Check system health
|
||||
curl "http://localhost:8080/health"
|
||||
```
|
||||
|
||||
## 🔒 Security Features
|
||||
|
||||
### API Key Masking
|
||||
All API keys and passwords are automatically masked in logs:
|
||||
```
|
||||
[2025-09-09T12:34:56] INFO: TMDB API call with key=***masked***
|
||||
[2025-09-09T12:34:56] INFO: Database connection password=***masked***
|
||||
```
|
||||
|
||||
### Sensitive Data Separation
|
||||
- **Main `.env`**: Paths, preferences, URLs (safe to share)
|
||||
- **`.env.secrets`**: API keys, passwords (never commit to version control)
|
||||
- **Automatic loading**: Both files loaded automatically at startup
|
||||
|
||||
### Git Protection
|
||||
The `.gitignore` file prevents accidental commits:
|
||||
```
|
||||
.env
|
||||
.env.secrets
|
||||
.env.local
|
||||
```
|
||||
|
||||
## 🛠 Troubleshooting
|
||||
|
||||
### "Environment files not loaded" Warning
|
||||
Install python-dotenv:
|
||||
```bash
|
||||
pip install python-dotenv==1.0.0
|
||||
# or
|
||||
docker-compose build # rebuilds with updated requirements.txt
|
||||
```
|
||||
|
||||
### Sharing Configuration for Help
|
||||
You can safely share your `.env` file for debugging since it contains no sensitive data. The `.env.secrets` file should never be shared.
|
||||
|
||||
### Migration from Old Setup
|
||||
If you have an existing `.env` with API keys:
|
||||
1. Move all `*_API_KEY` and `*_PASSWORD` variables to `.env.secrets`
|
||||
2. Remove sensitive data from `.env`
|
||||
3. Restart NFOGuard
|
||||
|
||||
## 🎯 Docker Compose Example
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
nfoguard:
|
||||
image: sbcrumb/nfoguard:latest
|
||||
container_name: nfoguard
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /path/to/your/media:/media:rw
|
||||
- ./data:/app/data
|
||||
- ./.env:/app/.env:ro # Main configuration
|
||||
- ./.env.secrets:/app/.env.secrets:ro # Secrets
|
||||
environment:
|
||||
- PORT=8080
|
||||
depends_on:
|
||||
- radarr-postgres
|
||||
```
|
||||
|
||||
## 📋 Configuration Reference
|
||||
|
||||
### Main Configuration (.env)
|
||||
- **Paths**: `TV_PATHS`, `MOVIE_PATHS`, `DB_PATH`
|
||||
- **Processing**: `MOVIE_PRIORITY`, `RELEASE_DATE_PRIORITY`
|
||||
- **Features**: `MANAGE_NFO`, `FIX_DIR_MTIMES`, `LOCK_METADATA`
|
||||
- **URLs**: `RADARR_URL`, `SONARR_URL`, `JELLYSEERR_URL`
|
||||
|
||||
### Secrets Configuration (.env.secrets)
|
||||
- **Database**: `RADARR_DB_PASSWORD`
|
||||
- **APIs**: `TMDB_API_KEY`, `OMDB_API_KEY`, `RADARR_API_KEY`, `SONARR_API_KEY`
|
||||
- **Optional**: `JELLYSEERR_API_KEY`
|
||||
|
||||
This setup makes NFOGuard more secure while keeping configuration manageable for troubleshooting and deployment.
|
||||
@@ -0,0 +1,567 @@
|
||||
# NFOGuard Project Summary
|
||||
|
||||
## Overview
|
||||
NFOGuard is a Python-based tool that manages NFO (metadata) files for movies and TV shows in Plex/Emby media servers. It integrates with Radarr and Sonarr to automatically manage metadata, ensuring proper dates and metadata consistency.
|
||||
|
||||
## 🎯 CURRENT SESSION ACCOMPLISHMENTS (September 22, 2025)
|
||||
|
||||
### ✅ WORKFLOW AUTOMATION OVERHAUL
|
||||
1. **Removed Docker Hub Dependencies**: Eliminated all Docker Hub pushes from Gitea workflows
|
||||
2. **Local-Only Builds**: Configured dev and main branches to build locally only
|
||||
3. **GitHub Integration**: Set up automated local → GitHub workflow for public testing
|
||||
4. **Post-Merge Automation**: Created git hook for automatic GitHub sync when merging to main
|
||||
|
||||
### ✅ NFO MIGRATION BUG FIX
|
||||
**Problem**: Long-named episode NFO files created by Sonarr weren't properly migrated
|
||||
- ❌ Content (title, plot, runtime) was lost during migration
|
||||
- ❌ Long-named files weren't being cleaned up
|
||||
- ❌ Short NFO files had minimal metadata
|
||||
|
||||
**Solution**: Enhanced episode NFO migration process
|
||||
- ✅ **Content Preservation**: All metadata (title, plot, runtime, premiered) now preserved from long-named NFO files
|
||||
- ✅ **Smart Migration**: `find_existing_episode_nfo()` detects matching season/episode in long-named files
|
||||
- ✅ **Automatic Cleanup**: Old long-named NFO files automatically deleted after successful migration
|
||||
- ✅ **Rich Output**: Standard `S##E##.nfo` files now contain full metadata + NFOGuard fields
|
||||
- ✅ **Debug Logging**: Added detailed logging to track content preservation during migration
|
||||
- ✅ **FIXED**: Migration logic now properly prioritizes long-named files over existing short files
|
||||
- ✅ **WORKING**: Content preservation, cleanup, and migration all functioning correctly
|
||||
|
||||
### ✅ DOCKER SHUTDOWN FIX
|
||||
**Problem**: Container wouldn't stop gracefully with `docker compose down`
|
||||
- ❌ 24-second timeout waiting for container to stop
|
||||
- ❌ Python process not handling SIGTERM signals properly
|
||||
|
||||
**Solution**: Added proper signal handling to NFOGuard
|
||||
- ✅ **Signal Handlers**: SIGTERM and SIGINT now properly handled
|
||||
- ✅ **Graceful Shutdown**: Clean exit with logging
|
||||
- ✅ **Fast Stops**: Container stops in seconds instead of timing out
|
||||
|
||||
### ✅ NEW RELEASE WORKFLOW
|
||||
**Local Development Flow**:
|
||||
1. **Local dev branch** → Development and testing
|
||||
2. **Local main branch** → Merge when ready for release
|
||||
3. **Auto-trigger** → Post-merge hook pushes main to GitHub dev
|
||||
4. **GitHub dev branch** → Public testing environment
|
||||
5. **GitHub main branch** → Production releases (manual PR approval)
|
||||
|
||||
### ✅ AUTOMATION TOOLS CREATED
|
||||
- **Post-merge hook** (`.git/hooks/post-merge`): Auto-syncs main → GitHub dev + creates PR
|
||||
- **Enhanced sync script** (`sync-to-github.sh`): Manual control over GitHub sync + **automatic version management**
|
||||
- **GitHub remote**: Added `git@github.com:sbcrumb/nfoguard.git` for public repository
|
||||
|
||||
### ✅ VERSION MANAGEMENT AUTOMATION
|
||||
**Never Forget Version Bumps Again!**
|
||||
- **Automatic version increment** integrated into sync workflow
|
||||
- **Semantic versioning support**: patch/minor/major increments
|
||||
- **Smart commit messages**: `🔖 Bump version to X.Y.Z (type)`
|
||||
- **Flexible options**: Version-only updates or sync with version bump
|
||||
|
||||
### ✅ BUILD IDENTIFICATION SYSTEM
|
||||
**Always Know What Version You're Running!**
|
||||
- **Branch Detection**: Automatically detects git branch during build
|
||||
- **Gitea Branding**: All builds tagged with `-gitea` suffix for clear identification
|
||||
- **Version Examples**:
|
||||
- Dev builds: `1.6.8-dev-gitea`
|
||||
- Main builds: `1.6.8-gitea`
|
||||
- **Build Source**: All builds performed in Gitea CI (never local manual builds)
|
||||
|
||||
### ✅ WORKFLOW BENEFITS
|
||||
- ✅ **No more Docker Hub costs/dependencies**
|
||||
- ✅ **Local builds only** (faster, more secure)
|
||||
- ✅ **Automated public testing** via GitHub dev branch
|
||||
- ✅ **Controlled releases** via PR approval process
|
||||
- ✅ **Maintains local Gitea workflow** for internal development
|
||||
|
||||
---
|
||||
|
||||
## 🎯 PREVIOUS SESSION ACCOMPLISHMENTS (September 21, 2025)
|
||||
|
||||
### ✅ MAJOR ISSUES RESOLVED
|
||||
1. **Database Save Bug**: Identified and resolved "phantom" database save issue (was logging interpretation error)
|
||||
2. **Enhanced Movie Detection**: Movies without IMDb IDs in directory names now detected via filenames/NFO content
|
||||
3. **Enhanced Logging**: Crystal-clear source attribution showing NFOGuard DB vs Radarr vs External APIs
|
||||
4. **Priority Flow Confirmed**: Perfect implementation of user's requested flow
|
||||
|
||||
### ✅ KEY IMPROVEMENTS MADE
|
||||
|
||||
**🔍 Enhanced Movie Detection**:
|
||||
- Added `find_movie_imdb_id()` function with comprehensive detection
|
||||
- Supports directory names, filenames, and NFO file content parsing
|
||||
- Movies like "Ick (2024)" now properly processed without directory IMDb tags
|
||||
|
||||
**📊 Crystal-Clear Logging System**:
|
||||
- Added emoji-based logging for easy visual scanning
|
||||
- Clear source attribution: `nfoguard_db:`, `radarr:db.`, `tmdb:`, etc.
|
||||
- Priority flow display shows exact decision path
|
||||
- Final completion logs show chosen date and source
|
||||
|
||||
**🔄 Perfect Priority Flow**:
|
||||
1. NFOGuard Database (cached entries) →
|
||||
2. Radarr Import History (real import dates) →
|
||||
3. External APIs (TMDB/OMDb with configurable priority) →
|
||||
4. Save to NFOGuard Database (cache for future)
|
||||
|
||||
**🚀 Manual Scan Commands**:
|
||||
- Movies only: `curl -X POST "http://nfoguard:8080/manual/scan?scan_type=movies"`
|
||||
- TV only: `curl -X POST "http://nfoguard:8080/manual/scan?scan_type=tv"`
|
||||
- Both: `curl -X POST "http://nfoguard:8080/manual/scan?scan_type=both"`
|
||||
|
||||
### ✅ CONFIGURATION MAINTAINED
|
||||
All existing .env settings fully preserved and respected:
|
||||
- `RELEASE_DATE_PRIORITY=digital,physical,theatrical`
|
||||
- `MOVIE_PRIORITY=import_then_digital`
|
||||
- `PREFER_RELEASE_DATES_OVER_FILE_DATES=true`
|
||||
- `ALLOW_FILE_DATE_FALLBACK=false`
|
||||
|
||||
### ✅ DEBUGGING COMPLETED
|
||||
- **Root Cause**: "Phantom database save" was actually two different movie executions in logs
|
||||
- **Database Save**: Working correctly in both early-exit and full-processing paths
|
||||
- **NFO Processing**: Fixed to execute before date validation (preserves existing metadata)
|
||||
- **File Detection**: Enhanced to handle movies without directory IMDb tags
|
||||
|
||||
## Core Architecture
|
||||
|
||||
### Main Components
|
||||
- **nfoguard.py**: Main application file containing the core logic
|
||||
- **core/nfo_manager.py**: Handles NFO file creation and updates
|
||||
- **clients/**: External API integrations (Radarr, Sonarr, etc.)
|
||||
|
||||
### Key Features
|
||||
- Creates and updates movie.nfo files with proper metadata
|
||||
- Manages TV show NFO files (tvshow.nfo, season.nfo, episode NFOs)
|
||||
- Preserves existing metadata while adding NFOGuard-managed fields
|
||||
- Supports date management from multiple sources (Radarr, file dates, etc.)
|
||||
- Webhook support for real-time processing
|
||||
|
||||
## Current Issue Analysis
|
||||
|
||||
### Problem
|
||||
When a movie.nfo file already exists (e.g., from Radarr), NFOGuard is **not** processing the file to:
|
||||
1. Move date fields to the bottom
|
||||
2. Add NFOGuard comment
|
||||
3. Add NFOGuard-managed fields (dateadded, lockdata, etc.)
|
||||
|
||||
### Root Cause Identified
|
||||
The issue is in `nfoguard.py:1009-1012`. The processing logic has a premature exit condition:
|
||||
|
||||
```python
|
||||
# Skip processing if no valid date found and file dates disabled
|
||||
if dateadded is None:
|
||||
_log("WARNING", f"Skipping movie {movie_path.name} - no valid date source available")
|
||||
self.db.upsert_movie_dates(imdb_id, released, None, source, True)
|
||||
return # <-- This exits BEFORE NFO processing
|
||||
```
|
||||
|
||||
**The NFO processing code (lines 1015-1018) never executes when dateadded is None.**
|
||||
|
||||
### Analysis of NFO Processing Logic
|
||||
The `create_movie_nfo` function in `core/nfo_manager.py:52-147` is actually well-designed:
|
||||
- Lines 60-78: Properly loads and preserves existing NFO content
|
||||
- Lines 69-78: Removes NFOGuard-managed fields to re-add them at the bottom
|
||||
- Lines 96-123: Adds all NFOGuard fields at the end
|
||||
- Lines 124-141: Adds NFOGuard comment and proper formatting
|
||||
|
||||
**The NFO manager code is correct - it's just not being called due to the early exit.**
|
||||
|
||||
## Files That Need Updates
|
||||
1. `nfoguard.py` - Fix the early exit logic around line 1009-1012
|
||||
|
||||
## Status
|
||||
- ✅ NFO Processing Issue: Fixed in nfoguard.py:1008-1025
|
||||
- 🔍 **NEW ISSUE**: Database not persisting dateadded values on manual scans
|
||||
|
||||
## Fix Summary
|
||||
|
||||
### Movie NFO Processing (✅ Fixed)
|
||||
**Problem**: NFO processing was skipped entirely when `dateadded` was None due to early return.
|
||||
|
||||
**Solution**: Moved NFO processing (`create_movie_nfo`) to execute **before** the `dateadded` check, ensuring that:
|
||||
1. Existing NFO files are always processed and standardized
|
||||
2. NFOGuard comment is added
|
||||
3. Date fields are moved to bottom
|
||||
4. lockdata is added if configured
|
||||
5. Only file mtime updates are skipped when no valid date is found
|
||||
|
||||
### TV Episode NFO Processing (✅ Enhanced)
|
||||
**Enhancement**: Added smart episode NFO migration for long-named files.
|
||||
|
||||
**New Functionality**:
|
||||
1. **Detection**: `find_existing_episode_nfo()` scans for non-standard NFO files that match season/episode
|
||||
2. **Migration**: Extracts metadata from long-named files (e.g., `Episode.Name.Here.S01E05.nfo`)
|
||||
3. **Standardization**: Creates standard `S01E05.nfo` with preserved metadata + NFOGuard enhancements
|
||||
4. **Cleanup**: Automatically deletes old long-named NFO files after successful migration
|
||||
5. **Preservation**: All existing metadata is preserved, dates moved to bottom, NFOGuard fields added
|
||||
|
||||
## 🔍 DATABASE SAVE BUG RESOLVED! ✅
|
||||
|
||||
### Problem Analysis COMPLETED
|
||||
**Root Cause Identified**: The "phantom database save bug" was actually a **logging interpretation error**.
|
||||
|
||||
### What Actually Happened
|
||||
The debug logs showing these two lines:
|
||||
```
|
||||
DEBUG: Movie processing reached post-mtime section: Dear Santa (2024) [imdb-tt2396431]
|
||||
INFO: Completed processing movie: Dear Santa (2024) [imdb-tt2396431] (source: tmdb:digital)
|
||||
```
|
||||
|
||||
**Cannot be from the same function execution!** Here's why:
|
||||
|
||||
### The Real Execution Flow
|
||||
**Line 1014-1018**: Early exit when `dateadded is None`:
|
||||
```python
|
||||
if dateadded is None:
|
||||
_log("WARNING", f"Movie {movie_path.name} - no valid date source available, but NFO was still processed")
|
||||
self.db.upsert_movie_dates(imdb_id, released, None, source, True)
|
||||
return # <-- EXITS HERE, never reaches line 1029!
|
||||
```
|
||||
|
||||
**Line 1029**: Debug log that only executes when `dateadded` has a valid value:
|
||||
```python
|
||||
_log("DEBUG", f"Movie processing reached post-mtime section: {movie_path.name}")
|
||||
```
|
||||
|
||||
**Line 1045**: Completion log that only executes after successful database save:
|
||||
```python
|
||||
_log("INFO", f"Completed processing movie: {movie_path.name} (source: {source})")
|
||||
```
|
||||
|
||||
### Key Insight
|
||||
**The logs are from TWO different executions:**
|
||||
1. **First run**: `dateadded = None` → early exit at line 1018 → database save executes BUT for NULL value
|
||||
2. **Second run**: `dateadded` has value → reaches line 1029 → full processing → line 1045
|
||||
|
||||
### Database Save Status
|
||||
✅ **Database saves ARE working correctly!**
|
||||
- Early exit path (line 1018): Saves NULL dateadded when no valid date found
|
||||
- Full processing path (lines 1038-1043): Saves valid dateadded when available
|
||||
- Both paths call `upsert_movie_dates()` appropriately
|
||||
|
||||
### Investigation Status
|
||||
✅ **Enhanced Movie Detection**: Working (Ick 2024 now processed)
|
||||
✅ **NFO Processing**: Working (files get updated)
|
||||
✅ **File Timestamp Updates**: Working (mtimes get set)
|
||||
✅ **Database Persistence**: **WORKING CORRECTLY** - saves happen in both execution paths
|
||||
|
||||
## 📊 ENHANCED LOGGING SYSTEM (September 21, 2025) ✅
|
||||
|
||||
### New Crystal-Clear Source Attribution
|
||||
**Problem**: Logs didn't clearly show whether dates came from NFOGuard DB vs Radarr vs external APIs.
|
||||
|
||||
**Solution**: Added comprehensive logging with emojis and clear source identification.
|
||||
|
||||
### New Logging Format
|
||||
**Priority Flow Display**:
|
||||
```
|
||||
🔄 PRIORITY FLOW: NFOGuard DB → Radarr import → External APIs (digital,physical,theatrical) → Save to NFOGuard DB
|
||||
```
|
||||
|
||||
**NFOGuard Database Lookups**:
|
||||
```
|
||||
🔍 NFOGuard DB lookup for tt1234567: FOUND - dateadded=2025-06-15T11:10:31-04:00, source=radarr:db.history.import
|
||||
✅ MANUAL SCAN: Using existing NFOGuard database entry: 2025-06-15T11:10:31-04:00 (original source: radarr:db.history.import)
|
||||
```
|
||||
|
||||
**External Source Queries**:
|
||||
```
|
||||
🔍 RADARR DATABASE: Checking import history for movie ID 123 (tt1234567)...
|
||||
📦 RADARR DATABASE: Found import date=2025-07-20T14:30:00Z, source=radarr:db.history.import
|
||||
🔍 EXTERNAL APIs: Trying digital release date fallback...
|
||||
🌐 EXTERNAL APIs: Found digital release date=2025-06-15T00:00:00+00:00, source=tmdb:digital
|
||||
```
|
||||
|
||||
**Final Decision Tracking**:
|
||||
```
|
||||
✅ FINAL CHOICE: Using Radarr import date 2025-07-20T14:30:00-04:00 from radarr:db.history.import
|
||||
🎬 COMPLETED: Movie Name (2024) | Final date: 2025-07-20T14:30:00-04:00 | Final source: radarr:db.history.import
|
||||
```
|
||||
|
||||
### Source Attribution System
|
||||
**NFOGuard Database**: `nfoguard_db:radarr:db.history.import` (shows original source)
|
||||
**Radarr Database**: `radarr:db.history.import` (fresh query)
|
||||
**External APIs**: `tmdb:digital`, `omdb:dvd`, etc.
|
||||
|
||||
### Perfect Priority Flow Confirmed
|
||||
1. ✅ **NFOGuard DB First**: Check cached entries, use if available
|
||||
2. ✅ **Radarr Import History**: Query for real import dates if not cached
|
||||
3. ✅ **External APIs**: TMDB/OMDb fallback with configurable priority (`RELEASE_DATE_PRIORITY`)
|
||||
4. ✅ **Save to NFOGuard DB**: Cache result for future lookups
|
||||
|
||||
**This ensures we don't repeatedly query Radarr/external APIs for the same movies!**
|
||||
|
||||
## 🚀 MANUAL SCAN API COMMANDS
|
||||
|
||||
### Available Scan Types
|
||||
**Movies Only:**
|
||||
```bash
|
||||
curl -X POST "http://nfoguard:8080/manual/scan?scan_type=movies"
|
||||
```
|
||||
|
||||
**TV Shows Only:**
|
||||
```bash
|
||||
curl -X POST "http://nfoguard:8080/manual/scan?scan_type=tv"
|
||||
```
|
||||
|
||||
**Both Movies AND TV Shows (Default):**
|
||||
```bash
|
||||
curl -X POST "http://nfoguard:8080/manual/scan?scan_type=both"
|
||||
# OR simply:
|
||||
curl -X POST "http://nfoguard:8080/manual/scan"
|
||||
```
|
||||
|
||||
**Specific Path Scan:**
|
||||
```bash
|
||||
curl -X POST "http://nfoguard:8080/manual/scan?path=/media/Movies/Movie.Name.2024&scan_type=movies"
|
||||
```
|
||||
|
||||
### What Each Scan Does
|
||||
- **Movies**: Processes all movie directories in `MOVIE_PATHS`, follows NFOGuard priority flow
|
||||
- **TV**: Processes all TV series in `TV_PATHS`, updates episode NFO files with proper dates
|
||||
- **Both**: Processes both movies and TV shows in sequence (recommended for full refresh)
|
||||
|
||||
All scans run in background and return immediately with status confirmation.
|
||||
|
||||
### Movie IMDb ID Detection (✅ Enhanced)
|
||||
**Enhancement**: Added comprehensive IMDb ID detection for movies without directory tags.
|
||||
|
||||
**New Detection Methods**:
|
||||
1. **Directory Name**: `[imdb-tt123456]` format (existing)
|
||||
2. **Filename Patterns**: IMDb ID in any video file name `Movie.Name.2024.[tt123456].mkv`
|
||||
3. **NFO File Content**: `<uniqueid type="imdb">tt123456</uniqueid>` (NEW)
|
||||
4. **Legacy NFO Tags**: `<imdbid>` and `<imdb>` tags (NEW)
|
||||
|
||||
**Implementation**:
|
||||
- Added `find_movie_imdb_id()` function that tries all methods in priority order
|
||||
- Extended `parse_imdb_from_nfo()` to handle XML parsing
|
||||
- Updated movie processing to use comprehensive detection
|
||||
|
||||
**Example**: Ick (2024) directory without IMDb in folder name will now be detected via NFO file content.
|
||||
|
||||
|
||||
# NFOGuard Development Summary
|
||||
|
||||
## Current Status: v1.6.6 - Docker Plugin Deployment! 🐳
|
||||
|
||||
### Latest Updates (v1.6.6) - September 19, 2025
|
||||
- **🐳 DOCKER PLUGIN DEPLOYMENT**: Added automatic Emby plugin deployment via Docker
|
||||
- **📦 DLL PACKAGING**: NFOGuard.Emby.Plugin.dll now packaged with Docker image
|
||||
- **🔗 BIND MOUNT SUPPORT**: Primary method using bind mount to Emby plugins directory
|
||||
- **⚙️ ENVIRONMENT FALLBACK**: Secondary method using EMBY_PLUGINS_PATH environment variable
|
||||
- **🚀 AUTO-UPDATE**: Plugin automatically updates when new Docker image is deployed
|
||||
- **📋 CONFIGURATION**: Added .env.example with plugin deployment settings
|
||||
- **🔄 STARTUP SCRIPT**: Container automatically deploys plugin on startup
|
||||
- **🎯 WORKFLOW INTEGRATION**: Compatible with Gitea → DockerHub deployment pipeline
|
||||
|
||||
### Docker Plugin Deployment Flow
|
||||
**Bind Mount Method (Recommended):**
|
||||
1. Set `EMBY_PLUGINS_PATH=/path/to/emby/plugins` in .env
|
||||
2. Docker bind mounts host directory to `/emby-plugins` in container
|
||||
3. On startup, NFOGuard copies DLL to mounted directory
|
||||
4. Plugin updates automatically with each new image deployment
|
||||
|
||||
**Benefits:**
|
||||
- Works with separate Emby/NFOGuard containers
|
||||
- Compatible with native Emby installations
|
||||
- Secure - only exposes plugins directory
|
||||
- Automatic updates via CI/CD pipeline
|
||||
|
||||
## Previous Status: v1.6.0 - NFO-Based Identification! 📄
|
||||
|
||||
### Latest Updates (v1.6.0) - September 16, 2025
|
||||
- **📄 NFO IDENTIFICATION**: Added support for identifying movies/TV shows from NFO files
|
||||
- **🔄 DUAL METHOD**: Directory name IMDb IDs (primary) + NFO file IMDb IDs (fallback)
|
||||
- **📋 NFO FORMATS**: Supports `<uniqueid type="imdb">`, `<imdbid>`, and `<imdb>` XML tags
|
||||
- **🎬 MOVIE SUPPORT**: Reads movie.nfo files for IMDb ID extraction
|
||||
- **📺 TV SUPPORT**: Reads tvshow.nfo files for series identification
|
||||
- **✅ SMART FALLBACK**: Only checks NFO files when directory name lacks IMDb ID
|
||||
- **📝 DOCUMENTATION**: Updated README with NFO identification examples and formats
|
||||
- **🔄 NFO RENAMING**: Added smart episode NFO file renaming to standardized `S##E##.nfo` format
|
||||
- **🎯 SONARR INTEGRATION**: Detects existing NFO files created by Sonarr/other tools, extracts metadata, and renames to standard format
|
||||
- **📁 METADATA PRESERVATION**: Preserves all existing metadata when renaming non-standard NFO files
|
||||
- **🧹 CLEANUP**: Removes old non-standard NFO files after successful rename to prevent duplicates
|
||||
|
||||
### Previous Updates (v1.5.5) - September 15, 2025
|
||||
- **🔧 DATABASE BUG FIX**: Fixed `upsert_movie_dates` to be a proper upsert operation
|
||||
- **💾 DATA INTEGRITY**: Manual scans now properly save `dateadded` to database
|
||||
- **🎯 ROOT CAUSE**: Fixed UPDATE-only operation that was leaving `dateadded` fields NULL
|
||||
- **✅ WEBHOOK FIX**: Webhooks now find existing database entries correctly
|
||||
- **📺 TV SHOWS**: NOT affected - already using proper `INSERT OR REPLACE` operations
|
||||
|
||||
### Previous Updates (v1.5.4) - September 15, 2025
|
||||
- **🎯 WEBHOOK DATE FIX**: Fixed webhook processing to use proper date decision logic
|
||||
- **🔍 SMART FALLBACK**: Webhooks now check database → Radarr import dates → release dates → timestamp
|
||||
- **❌ ISSUE RESOLVED**: Upgrade webhooks no longer incorrectly use current timestamp when database exists
|
||||
- **✅ PROPER FLOW**: Webhook mode now uses same date logic as manual scans for missing entries
|
||||
|
||||
### Previous Updates (v1.5.3) - September 15, 2025
|
||||
- **🔧 RADARR RENAME FIX**: Added missing event type filtering to Radarr webhooks
|
||||
- **✅ CONSISTENCY**: Radarr now matches Sonarr's event handling (Download, Upgrade, Rename)
|
||||
- **🎯 FIXED ISSUE**: Radarr rename events now properly trigger NFO updates with correct dates
|
||||
- **🔄 WORKFLOW**: Both Sonarr and Radarr now follow identical webhook processing flows
|
||||
|
||||
### Previous Updates (v1.5.2)
|
||||
- **🔇 TVDB WARNINGS**: Added SUPPRESS_TVDB_WARNINGS configuration option
|
||||
- **✅ CLEAN LOGS**: Can now suppress non-critical TVDB API failure warnings
|
||||
- **🧹 PRODUCTION**: Cleaner logs for production monitoring
|
||||
- **🎯 FUNCTIONAL**: System works perfectly without TVDB (uses IMDb/Sonarr data)
|
||||
|
||||
### TVDB Warning Suppression
|
||||
**Added new environment variable:**
|
||||
```bash
|
||||
# Suppress TVDB API warnings (true/false) - TVDB failures are common and non-critical
|
||||
SUPPRESS_TVDB_WARNINGS=true
|
||||
```
|
||||
|
||||
### Why Suppress TVDB Warnings?
|
||||
- **❌ Common Failures**: Many series don't exist in TVDB database
|
||||
- **✅ Non-Critical**: NFOGuard works perfectly without TVDB data
|
||||
- **📊 Primary Data**: Uses IMDb IDs and Sonarr metadata (more reliable)
|
||||
- **🧹 Log Noise**: Reduces repetitive warning messages
|
||||
|
||||
### Before vs After
|
||||
|
||||
**Before (noisy):**
|
||||
```
|
||||
INFO: All episodes found in cache
|
||||
WARNING: GET https://api4.thetvdb.com/v4/search/remoteid?remoteId=tt0804484&type=series failed: HTTP Error 400: Bad Request
|
||||
INFO: Completed processing TV series: Foundation (2021) [imdb-tt0804484]
|
||||
WARNING: GET https://api4.thetvdb.com/v4/search/remoteid?remoteId=tt9737326&type=series failed: HTTP Error 400: Bad Request
|
||||
```
|
||||
|
||||
**After (clean):**
|
||||
```
|
||||
INFO: All episodes found in cache
|
||||
INFO: Completed processing TV series: Foundation (2021) [imdb-tt0804484]
|
||||
INFO: Completed processing TV series: Invasion (2021) [imdb-tt9737326]
|
||||
```
|
||||
|
||||
### Your Configuration
|
||||
```bash
|
||||
DEBUG=false # Clean production logging
|
||||
PATH_DEBUG=false # No path mapping debug
|
||||
SUPPRESS_TVDB_WARNINGS=true # Hide non-critical TVDB failures
|
||||
```
|
||||
|
||||
### System Status
|
||||
- ✅ **Processing**: All TV series processing successfully
|
||||
- ✅ **Episodes**: All episodes found and processed
|
||||
- ✅ **NFO Files**: Being created/updated with proper metadata
|
||||
- ✅ **Functionality**: TVDB failures don't affect operation
|
||||
|
||||
## 🔇 NFOGuard v1.5.2 - Ultra-clean production logs! 🔇
|
||||
|
||||
### Copy SUPPRESS_TVDB_WARNINGS=true to your server .env file and restart!
|
||||
|
||||
---
|
||||
|
||||
## 🔧 FIXED: Database Upsert Bug (September 15, 2025) - **CRITICAL**
|
||||
|
||||
### Issue Discovery
|
||||
**The Real Root Cause**: Manual scans were NOT actually saving `dateadded` to database due to faulty upsert operation!
|
||||
|
||||
### Problem Details
|
||||
**Database Method Bug** in `core/database.py:173-182`:
|
||||
- `upsert_movie_dates()` was doing UPDATE-only, not proper upsert
|
||||
- If movie row didn't exist properly, UPDATE would affect 0 rows
|
||||
- `dateadded` field remained NULL even after manual scan
|
||||
- Webhooks found database entries but with NULL `dateadded` → fell back to current timestamp
|
||||
|
||||
### 🔧 **Fix Applied**
|
||||
- **Location**: `core/database.py:173-186`
|
||||
- **Changed**: UPDATE-only → proper `INSERT OR REPLACE` upsert
|
||||
- **Result**: Manual scans now properly save `dateadded` to database
|
||||
- **Webhook Impact**: Now finds existing dates correctly, no more false timestamps
|
||||
|
||||
### Before vs After Database Operations
|
||||
**Before (BROKEN):**
|
||||
```sql
|
||||
UPDATE movies SET dateadded = '2025-06-15...' WHERE imdb_id = 'tt123';
|
||||
-- If row doesn't exist properly: 0 rows affected, dateadded stays NULL
|
||||
```
|
||||
|
||||
**After (FIXED):**
|
||||
```sql
|
||||
INSERT OR REPLACE INTO movies (...) VALUES (...);
|
||||
-- Always works: Creates row OR replaces with all data including dateadded
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 FIXED: Webhook Date Logic Issue (September 15, 2025)
|
||||
|
||||
### Issue Discovery
|
||||
Upgrade webhooks were incorrectly using current timestamp (`webhook:first_seen`) instead of checking Radarr for proper import dates when no database entry existed.
|
||||
|
||||
**Example Problem:**
|
||||
- Database populated via manual scan: `2025-06-15T11:10:31-04:00` (radarr:db.history.import)
|
||||
- Upgrade webhook comes in: `2025-09-15T12:04:23-04:00` (webhook:first_seen) ❌ **WRONG!**
|
||||
|
||||
### Root Cause
|
||||
Webhook mode was bypassing the full date decision logic (`_decide_movie_dates`) and jumping straight to current timestamp as fallback.
|
||||
|
||||
### ✅ **Fix Applied**
|
||||
- **Location**: `nfoguard.py:975-990`
|
||||
- **Logic**: Webhook mode now uses same date priority as manual scans:
|
||||
1. **Database first** (if exists)
|
||||
2. **Full date logic** (Radarr import → release dates → fallbacks)
|
||||
3. **Current timestamp** (only as absolute last resort)
|
||||
|
||||
### Result
|
||||
Webhook upgrades now properly find and use existing Radarr import dates instead of creating false "first seen" timestamps.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 FIXED: Radarr Rename Event Issue (September 15, 2025)
|
||||
|
||||
### Issue Resolution
|
||||
**COMPLETED**: Fixed missing Radarr rename event handling by adding proper event type filtering.
|
||||
|
||||
### ✅ **Both Sonarr & Radarr Webhook Handling** - **NOW WORKING CORRECTLY**
|
||||
- **Sonarr Location**: `nfoguard.py:1429`
|
||||
- **Radarr Location**: `nfoguard.py:1479` **(FIXED)**
|
||||
- **Event Filtering**: `if event_type not in ["Download", "Upgrade", "Rename"]:`
|
||||
- **✅ STATUS**: **Rename events ARE processed for both systems**
|
||||
- **✅ BEHAVIOR**: Both systems now update NFO files with proper date metadata on rename
|
||||
|
||||
### What Was Fixed
|
||||
1. **Added Event Type Filtering**: Radarr webhooks now explicitly filter for supported events
|
||||
2. **Consistent Processing**: Both Sonarr and Radarr now follow identical webhook workflows
|
||||
3. **Proper Rename Handling**: Rename events trigger full NFO processing pipeline
|
||||
|
||||
---
|
||||
|
||||
## 📋 NFOGuard Webhook Workflow Documentation
|
||||
|
||||
### 🎬 **Radarr Webhook Workflow**
|
||||
1. **Import Event**:
|
||||
- Check database - if not seen before, current timestamp = truth of first import
|
||||
- Update movie.nfo with proper date metadata
|
||||
|
||||
2. **Rename Event**:
|
||||
- Check database - if we have the date, use existing date
|
||||
- Update movie.nfo file as always (preserving original import date)
|
||||
|
||||
3. **Rename Event (No Database Entry)**:
|
||||
- Check Radarr database for earliest import date
|
||||
- If found, use earliest import date → update database + movie.nfo
|
||||
- If no import date found, use digital/theatrical release date (fallback logic)
|
||||
|
||||
### 📺 **Sonarr Webhook Workflow**
|
||||
1. **Import Event**:
|
||||
- Check database - if not seen before, current timestamp = truth of first import
|
||||
- Update episode.nfo with proper date metadata
|
||||
|
||||
2. **Rename Event**:
|
||||
- Check database - if we have the date, use existing date
|
||||
- Update episode.nfo file as always (preserving original import date)
|
||||
|
||||
3. **Rename Event (No Database Entry)**:
|
||||
- Check Sonarr API for earliest import date
|
||||
- If found, use earliest import date → update database + episode.nfo
|
||||
- If no import date found, use air date (fallback logic)
|
||||
|
||||
### 🔄 **Key Processing Logic**
|
||||
- **Database First**: Always check NFOGuard database for existing dates
|
||||
- **Import Truth**: Webhook import events establish "source of truth" timestamps
|
||||
- **Date Preservation**: Rename events preserve original import dates, never overwrite
|
||||
- **Smart Fallbacks**: API queries → Release dates → Air dates → File dates (configurable)
|
||||
- **Batch Processing**: All webhooks go through batching system with configurable delays
|
||||
@@ -0,0 +1,67 @@
|
||||
# =€ NFOGuard v1.6.9 - Enhanced NFO Migration & Workflow Automation
|
||||
|
||||
## <¯ Major Features
|
||||
|
||||
### Complete NFO Migration System
|
||||
- **Smart Content Preservation**: Automatically migrates rich metadata (title, plot, runtime) from long-named Sonarr NFO files to standardized `S##E##.nfo` format
|
||||
- **Intelligent File Detection**: Enhanced `find_existing_episode_nfo()` detects matching season/episode in any NFO file naming convention
|
||||
- **Automatic Cleanup**: Long-named NFO files automatically deleted after successful migration
|
||||
- **Priority Logic Fix**: Migration now correctly prioritizes long-named files over existing short files for content extraction
|
||||
|
||||
### Workflow Automation Overhaul
|
||||
- **Local-Only Builds**: Removed all Docker Hub dependencies, builds now local-only for faster, more secure CI/CD
|
||||
- **GitHub Integration**: Automated local ’ GitHub workflow for public testing and releases
|
||||
- **Post-Merge Automation**: Git hooks automatically sync local main to GitHub dev branch with PR creation
|
||||
- **Version Management**: Integrated semantic versioning with automatic increment options (patch/minor/major)
|
||||
|
||||
### Build Identification System
|
||||
- **Branch Detection**: Automatic git branch detection during Docker builds
|
||||
- **Environment Tagging**: Clear version identification (`1.6.9-dev-gitea` vs `1.6.9`)
|
||||
- **Build Source Tracking**: Distinguishes local Gitea builds from public GitHub releases
|
||||
|
||||
## =' Technical Improvements
|
||||
|
||||
### Docker Enhancements
|
||||
- **Graceful Shutdown**: Added proper SIGTERM/SIGINT signal handling for clean container stops
|
||||
- **Branch-Specific Builds**: Workflow now correctly clones target branch instead of default
|
||||
- **Build Arguments**: Proper `GIT_BRANCH` and `BUILD_SOURCE` parameter passing
|
||||
|
||||
### Debug System
|
||||
- **Conditional Logging**: All debug statements now respect `DEBUG=true/false` environment variable
|
||||
- **Migration Tracking**: Detailed logging for NFO content preservation process (when enabled)
|
||||
- **Clean Production Logs**: Debug noise eliminated when `DEBUG=false`
|
||||
|
||||
## <¬ NFO Migration Details
|
||||
|
||||
**Before**: Long-named Sonarr NFO files existed alongside minimal short NFO files, content was lost
|
||||
**After**: Rich metadata automatically preserved in standardized format, old files cleaned up
|
||||
|
||||
**Example Migration**:
|
||||
```
|
||||
Source: "Invasion (2021)-S03E04-The Mission[WEBDL-1080p][AAC2.0][h264].nfo"
|
||||
Target: "S03E04.nfo"
|
||||
Content: title, plot, runtime, premiered ’ All preserved
|
||||
Cleanup: Original long file ’ Automatically deleted
|
||||
```
|
||||
|
||||
## =€ New Release Workflow
|
||||
|
||||
1. **Local Development** ’ dev branch with local Gitea CI
|
||||
2. **Local Release** ’ Merge dev to main triggers GitHub sync
|
||||
3. **Public Testing** ’ GitHub dev branch for community testing
|
||||
4. **Production Release** ’ Manual PR approval to GitHub main
|
||||
|
||||
## =à Developer Experience
|
||||
|
||||
- **Version Bumping**: Never forget with integrated `sync-to-github.sh` script
|
||||
- **Build Clarity**: Always know which environment you're running
|
||||
- **Fast Iteration**: Local-only builds eliminate external dependencies
|
||||
- **Debug Control**: Toggle verbose logging with single environment variable
|
||||
|
||||
---
|
||||
|
||||
**Breaking Changes**: None - fully backward compatible
|
||||
**Migration**: Automatic - existing NFO files will be migrated on next scan
|
||||
**Requirements**: No additional dependencies
|
||||
|
||||
Co-authored-by: Claude Code <noreply@anthropic.com>
|
||||
@@ -0,0 +1,221 @@
|
||||
# NFOGuard Development Workflow
|
||||
|
||||
## Overview
|
||||
NFOGuard uses a dual-repository system:
|
||||
- **Gitea (Private)**: `origin` - Development, testing, messy commits
|
||||
- **GitHub (Public)**: `github` - Clean releases, public testing
|
||||
|
||||
## Repository Setup
|
||||
```bash
|
||||
# Remotes should be configured as:
|
||||
origin gitea@192.168.253.221:jskala/NFOguard.git (fetch/push)
|
||||
github git@github.com:sbcrumb/nfoguard.git (fetch/push)
|
||||
```
|
||||
|
||||
## Daily Development Workflow
|
||||
|
||||
### 1. Local Development
|
||||
```bash
|
||||
# Work on dev branch (make as many commits as you want)
|
||||
git checkout dev
|
||||
# ... make changes, commit frequently ...
|
||||
git add .
|
||||
git commit -m "fix: whatever you're working on"
|
||||
|
||||
# Push to Gitea regularly for backup
|
||||
git push origin dev
|
||||
```
|
||||
|
||||
### 2. Feature Complete - Merge to Main
|
||||
```bash
|
||||
# When feature/fix is complete, merge to main
|
||||
git checkout main
|
||||
git merge dev
|
||||
|
||||
# Push to Gitea main
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 3. Prepare for GitHub Release
|
||||
|
||||
**Use the sync script for clean releases:**
|
||||
```bash
|
||||
# From main branch, run the sync script
|
||||
./sync-to-github.sh
|
||||
|
||||
# Choose Option 3: "Create clean release branch for GitHub PR (RECOMMENDED)"
|
||||
# This will:
|
||||
# 1. Increment version (patch/minor/major)
|
||||
# 2. Create clean release-vX.X.X branch from GitHub main
|
||||
# 3. Copy your changes with single clean commit
|
||||
# 4. Push to GitHub automatically
|
||||
```
|
||||
|
||||
**The script will output:**
|
||||
```
|
||||
🔗 Create PR at: https://github.com/sbcrumb/nfoguard/pull/new/release-v1.7.0
|
||||
📝 PR will be: release-v1.7.0 → main (clean, single commit)
|
||||
```
|
||||
|
||||
### 4. GitHub Testing and Release
|
||||
```bash
|
||||
# 1. Create PR: release-vX.X.X → main on GitHub
|
||||
# 2. Test the release branch thoroughly
|
||||
# 3. Merge when satisfied (squash merge will be available)
|
||||
```
|
||||
|
||||
## Manual Process (If Script Unavailable)
|
||||
|
||||
### Emergency Manual Release
|
||||
If the sync script isn't available, here's the manual process:
|
||||
|
||||
```bash
|
||||
# 1. Fetch latest GitHub main
|
||||
git fetch github
|
||||
|
||||
# 2. Create clean release branch
|
||||
git checkout -b release-v1.7.0 github/main
|
||||
|
||||
# 3. Copy key files from your local main
|
||||
git checkout main -- VERSION Dockerfile core/nfo_manager.py nfoguard.py .env.template .env.secrets.template .gitea/
|
||||
|
||||
# 4. Increment version manually
|
||||
echo "1.7.0" > VERSION
|
||||
|
||||
# 5. Commit and push
|
||||
git add .
|
||||
git commit -m "feat: Release v1.7.0 - [describe key changes]"
|
||||
git push github release-v1.7.0
|
||||
|
||||
# 6. Create PR on GitHub: release-v1.7.0 → main
|
||||
```
|
||||
|
||||
## Important Files and Their Purpose
|
||||
|
||||
### Local-Only Files (Never Commit to Gitea/GitHub)
|
||||
- `sync-to-github.sh` - GitHub sync automation
|
||||
- `.local/` directory - Local documentation and notes
|
||||
- `.env.secrets` - API keys and passwords
|
||||
|
||||
### Repository-Specific Files
|
||||
- `.gitea/workflows/` - Gitea CI/CD (ignored by GitHub)
|
||||
- `.github/workflows/` - GitHub CI/CD (ignored by Gitea)
|
||||
|
||||
### Shared Files
|
||||
- Core application code
|
||||
- Dockerfile
|
||||
- Configuration templates
|
||||
- VERSION file
|
||||
|
||||
## Version Management
|
||||
|
||||
### Semantic Versioning
|
||||
- **Patch (X.Y.Z+1)**: Bug fixes, small updates
|
||||
- **Minor (X.Y+1.0)**: New features, enhancements
|
||||
- **Major (X+1.0.0)**: Breaking changes, major releases
|
||||
|
||||
### Version Identification
|
||||
- **Local Gitea builds**: `1.7.0-dev-gitea`
|
||||
- **GitHub releases**: `1.7.0`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Messy Commit History" in GitHub PRs
|
||||
**Problem**: Local dev has 20+ commits that make GitHub PRs hard to review
|
||||
**Solution**: Always use sync script Option 3 to create clean release branches
|
||||
|
||||
### "No Common History" Error
|
||||
**Problem**: GitHub and local repos have different histories
|
||||
**Solution**: Use the clean release branch workflow (creates branches from GitHub main)
|
||||
|
||||
### "Sync Script Not Working"
|
||||
**Fallback**: Use the manual process outlined above
|
||||
|
||||
### Local Branch "Ahead by X Commits"
|
||||
**Normal**: Your local dev is ahead of Gitea dev - just push when ready
|
||||
```bash
|
||||
git push origin dev # Sync to Gitea
|
||||
```
|
||||
|
||||
## Branch Strategy
|
||||
|
||||
### Local Branches
|
||||
- `dev` - Active development (tracks origin/dev)
|
||||
- `main` - Stable local code (tracks origin/main)
|
||||
|
||||
### GitHub Branches
|
||||
- `release-vX.X.X` - Clean release branches (created by sync script)
|
||||
- `main` - Public stable releases
|
||||
- `dev` - Optional testing branch
|
||||
|
||||
### Gitea Branches
|
||||
- `dev` - Development history (all commits)
|
||||
- `main` - Feature-complete code (merged from dev)
|
||||
|
||||
## CI/CD Behavior
|
||||
|
||||
### Gitea Workflows
|
||||
- Build locally only (no Docker Hub)
|
||||
- Version shows as "X.X.X-dev-gitea"
|
||||
- Triggered on dev/main pushes
|
||||
|
||||
### GitHub Workflows
|
||||
- Build to GitHub Container Registry
|
||||
- Version shows as "X.X.X" (clean)
|
||||
- Triggered on main pushes
|
||||
|
||||
## Emergency Procedures
|
||||
|
||||
### If Sync Script is Lost
|
||||
1. Recreate from this workflow document
|
||||
2. Use manual process for immediate needs
|
||||
3. Script should be in `.local/` directory and ignored by git
|
||||
|
||||
### If GitHub Repo Gets Corrupted
|
||||
1. Force push clean main from Gitea
|
||||
2. Recreate release branches as needed
|
||||
3. Your code is safe in Gitea
|
||||
|
||||
### If Gitea Goes Down
|
||||
1. Continue development locally
|
||||
2. Push to GitHub dev branch for backup
|
||||
3. Sync back to Gitea when restored
|
||||
|
||||
## Success Indicators
|
||||
|
||||
### Good Workflow Signs
|
||||
- ✅ GitHub PRs have 1-3 clean commits
|
||||
- ✅ Local history is detailed and preserved
|
||||
- ✅ Version numbers increment properly
|
||||
- ✅ CI/CD builds succeed on both platforms
|
||||
|
||||
### Warning Signs
|
||||
- ❌ GitHub PRs have 20+ messy commits
|
||||
- ❌ "No common history" errors
|
||||
- ❌ Version numbers out of sync
|
||||
- ❌ Sync script getting committed to repos
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
```bash
|
||||
# Daily development
|
||||
git checkout dev && git pull origin dev
|
||||
# ... work ...
|
||||
git add . && git commit -m "fix: description"
|
||||
git push origin dev
|
||||
|
||||
# Complete feature
|
||||
git checkout main && git merge dev && git push origin main
|
||||
|
||||
# Release to GitHub
|
||||
./sync-to-github.sh # Choose option 3
|
||||
|
||||
# Check status
|
||||
git status
|
||||
git log --oneline -5
|
||||
git remote -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember**: The sync script Option 3 is your best friend for clean GitHub releases!
|
||||
Reference in New Issue
Block a user