--- title: "Discord Bot Release — 2026.3.12" description: "Major catch-up release: trade deadline enforcement, performance parallelization, security fixes, CI/CD migration to CalVer, and 148 commits of accumulated improvements." type: reference domain: major-domo tags: [release-notes, deployment, discord, major-domo] --- # Discord Bot Release — 2026.3.12 **Date:** 2026-03-31 **Tag:** `2026.3.12` **Image:** `manticorum67/major-domo-discordapp:2026.3.12` / `:production` **Server:** akamai (`~/container-data/major-domo`) **Deploy method:** `.scripts/deploy.sh -y` (docker compose pull + up) **Previous tag:** `v2.29.4` (148 commits behind) ## Release Summary Large catch-up release covering months of accumulated work since the last tag. The headline feature is trade deadline enforcement — `/trade` commands are now blocked after the configured deadline week, with fail-closed behavior when API data is unavailable. Also includes significant performance improvements (parallelized API calls, cached signatures, Redis SCAN), security hardening, dependency pinning, and a full CI/CD migration from version-file bumps to CalVer tag-triggered builds. ## Changes ### New Features - **Trade deadline enforcement** — `is_past_trade_deadline` property on Current model; guards on `/trade initiate`, submit button, and `_finalize_trade`. Fail-closed when API returns no data. 4 new tests. (PR #121) - `is_admin()` helper in `utils/permissions.py` (#55) - Team ownership verification on `/injury set-new` and `/injury clear` (#18) - Current week number included in weekly-info channel posts - Local deploy script for production deploys ### Performance - Parallelize independent API calls with `asyncio.gather()` (#90) - Cache `inspect.signature()` at decoration time (#97) - Replace `json.dumps` serialization test with `isinstance` fast path (#96) - Use `channel.purge()` instead of per-message delete loops (#93) - Parallelize schedule_service week fetches (#88) - Replace Redis `KEYS` with `SCAN` in `clear_prefix` (#98) - Reuse persistent `aiohttp.ClientSession` in GiphyService (#26) - Cache user team lookup in player_autocomplete, reduce limit to 25 ### Bug Fixes - Fix chart_service path from `data/` to `storage/` - Make ScorecardTracker methods async to match await callers - Prevent partial DB writes and show detailed errors on scorecard submission failure - Add trailing slashes to API URLs to prevent 307 redirects dropping POST bodies - Trade validation: check against next week's projected roster, include pending trades and org affiliate transactions - Prefix trade validation errors with team abbreviation - Auto-detect player roster type in trade commands instead of assuming ML - Fix key plays score text ("tied at X" instead of "Team up X-X") (#48) - Fix scorebug stale data, win probability parsing, and read-failure tolerance (#39, #40) - Batch quick-wins: 4 issues resolved (#37, #27, #25, #38) - Fix ContextualLogger crash when callers pass `exc_info=True` - Fix thaw report posting to use channel ID instead of channel names - Use explicit America/Chicago timezone for freeze/thaw scheduling - Replace broken `@self.tree.interaction_check` with MaintenanceAwareTree subclass - Implement actual maintenance mode flag in `/admin-maintenance` (#28) - Validate and sanitize pitching decision data from Google Sheets - Fix `/player` autocomplete timeout by using current season only - Split read-only data volume to allow state file writes (#85) - Update roster labels to use Minor League and Injured List (#59) ### Security - Address 7 security issues across the codebase - Remove 226 unused imports (#33) - Pin all Python dependency versions in `requirements.txt` (#76) ### Refactoring & Cleanup - Extract duplicate command hash logic into `_compute_command_hash` (#31) - Move 42 unnecessary lazy imports to top-level - Remove dead maintenance mode artifacts in bot.py (#104) - Remove unused `weeks_ahead` parameter from `get_upcoming_games` - Invalidate roster cache after submission instead of force-refreshing ## Infrastructure Changes - **CI/CD migration**: Switched from version-file bumps to CalVer tag-triggered Docker builds - Added `.scripts/release.sh` for creating CalVer tags - Updated `.scripts/deploy.sh` for tag-triggered releases - Docker build cache switched from `type=gha` to `type=registry` - Used `docker-tags` composite action for multi-channel release support - Fixed act_runner auth with short-form local actions + full GitHub URLs - Use Gitea API for tag creation to avoid branch protection failures ## Deployment Notes - No migrations required - No config changes needed - Rollback: `ssh akamai "cd ~/container-data/major-domo && docker pull manticorum67/major-domo-discordapp@ && docker tag manticorum67/major-domo-discordapp:production && docker compose up -d discord-app"`