Commit Graph

357 Commits

Author SHA1 Message Date
cal
a80addc742 Merge pull request 'next-release' (#47) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 46s
Reviewed-on: #47
2026-02-22 22:33:35 +00:00
cal
22c7f841e8 Merge branch 'main' into next-release
All checks were successful
Build Docker Image / build (pull_request) Successful in 48s
2026-02-22 22:31:07 +00:00
cal
e280928b4d Merge pull request 'feat: include current week number in weekly-info channel post' (#46) from feat/weekly-info-current-week into next-release
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m10s
Reviewed-on: #46
2026-02-22 22:22:00 +00:00
Cal Corum
b7a88844b6 feat: include current week number in weekly-info channel post
The #weekly-info message already shows season and game times but not
which week it is, making managers check elsewhere for that context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:20:08 -06:00
cal
1df9527697 Merge pull request 'fix: use explicit America/Chicago timezone for freeze/thaw scheduling' (#45) from fix/utc-timezone-scheduling into next-release
Reviewed-on: #45
2026-02-22 22:16:54 +00:00
Cal Corum
8a1a957c2a fix: use explicit America/Chicago timezone for freeze/thaw scheduling
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
The production container has ambiguous timezone config — /etc/localtime
points to Etc/UTC but date reports CST. The transaction freeze/thaw task
used datetime.now() (naive, relying on OS timezone), causing scheduling
to fire at unpredictable wall-clock times.

- Add utils/timezone.py with centralized Chicago timezone helpers
- Fix tasks/transaction_freeze.py to use now_chicago() for scheduling
- Fix utils/logging.py timestamp to use proper UTC-aware datetime
- Add 14 timezone utility tests
- Update freeze task tests to mock now_chicago instead of datetime

Closes #43

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:00:22 -06:00
Cal Corum
a668a3505c docs: add release workflow section to CLAUDE.md
Documents the next-release staging branch pattern used for
batching changes before merging to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:59:07 -06:00
cal
12fe600e83 Merge pull request 'next-release' (#42) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 50s
Reviewed-on: #42
2026-02-20 20:28:15 +00:00
Cal Corum
d1a6b57ccd fix: scorebug stale data, win probability parsing, and read-failure tolerance (closes #39, #40)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m14s
#40: ScorecardTracker cached data in memory at startup — background task never
saw newly published scorecards. Fixed by reloading from disk on every read.

#39: Win percentage defaulted to 50% when unavailable, showing a misleading
50/50 bar. Now defaults to None with "unavailable" message in embed. Parsing
handles decimal (0.75), percentage string, and empty values. Also fixed
orientation bug where win% was always shown as home team's even when the
sheet reports the away team as the leader.

Additionally: live scorebug tracker now distinguishes between "all games
confirmed final" and "sheet read failures" — transient Google Sheets errors
no longer hide the live scores channel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:14:23 -06:00
Cal Corum
67f9c734b0 Merge branch 'fix/quick-wins-batch' into next-release 2026-02-20 13:14:49 -06:00
Cal Corum
9cd577cba1 fix: batch quick-wins — 4 issues resolved (closes #37, #27, #25, #38)
- #37: Fix stale comment in transaction_freeze.py referencing wrong moveid format
- #27: Change config.testing default from True to False (was masking prod behavior)
- #25: Replace deprecated asyncio.get_event_loop() with get_running_loop()
- #38: Replace naive datetime.now() with timezone-aware datetime.now(UTC) across
  7 source files and 4 test files to prevent subtle timezone bugs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:48:16 -06:00
Cal Corum
f64fee8d2e fix: remove 226 unused imports across the codebase (closes #33)
Ran `ruff check --select F401 --fix` to auto-remove 221 unused imports,
manually removed 4 unused `import discord` from package __init__.py files,
and fixed test import for DISAPPOINTMENT_TIERS to reference canonical location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:35:04 -06:00
Cal Corum
a44d037611 Merge branch 'fix/security-issues' into next-release 2026-02-20 10:39:47 -06:00
Cal Corum
f4be20afb3 fix: address 7 security issues across the codebase
- Remove hardcoded Giphy API key from config.py, load from env var (#19)
- URL-encode query parameters in APIClient._add_params (#20)
- URL-encode Giphy search phrases before building request URLs (#21)
- Replace internal exception details with generic messages to users (#22)
- Replace all bare except: with except Exception: (#23)
- Guard interaction.guild access in has_player_role (#24)
- Replace MD5 with SHA-256 for command change detection hash (#32)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 09:54:53 -06:00
Cal Corum
5af62171da chore: remove obsolete MoveAction test stubs
Closes #16

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 22:28:47 -06:00
Cal Corum
9e43ffa1c1 feat: add local deploy script for production deploys
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m13s
Automates the SSH-to-akamai deploy workflow: pulls latest image,
restarts the container, and verifies health. Includes pre-deploy
checks (dirty git warning, confirmation prompt) and prints a
rollback command if the image changed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:45:56 -06:00
cal
eaaa9496a3 Merge pull request 'fix: ContextualLogger crashes when callers pass exc_info=True' (#14) from fix/contextual-logger-exc-info into main
All checks were successful
Build Docker Image / build (push) Successful in 48s
Reviewed-on: #14
2026-02-20 03:26:39 +00:00
cal
9db128bd27 Merge branch 'main' into fix/contextual-logger-exc-info
All checks were successful
Build Docker Image / build (pull_request) Successful in 46s
2026-02-20 03:25:32 +00:00
Cal Corum
62b058bddf test: fix weather test expecting 4 embed fields instead of 5
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m30s
The Stadium Image field was added to the weather embed but the
test_full_weather_workflow assertion wasn't updated to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:19:31 -06:00
Cal Corum
313c3f857b fix: ContextualLogger crashes when callers pass exc_info=True
ContextualLogger methods forwarded all **kwargs as extra={} to Python's
standard logger. When callers passed exc_info=True, it landed in the
extra dict and Python's LogRecord raised KeyError("Attempt to overwrite
'exc_info' in LogRecord") since exc_info is a reserved attribute.

This caused /submit-scorecard to crash after game data was already
posted, masking the original error and preventing proper rollback.

Fix: Extract exc_info and stack_info from kwargs before passing as extra,
forwarding them as proper logging parameters instead. Also fix direct
callers in submit_scorecard.py and views/players.py to use error=e.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:19:06 -06:00
cal
42b7369b17 Merge pull request 'ci: Fix act_runner auth for composite actions' (#13) from ci/fix-action-auth into main
All checks were successful
Build Docker Image / build (push) Successful in 48s
Reviewed-on: #13
2026-02-18 19:49:31 +00:00
Cal Corum
4137204d9d Fix act_runner auth: short-form local actions + full GitHub URLs
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m17s
DEFAULT_ACTIONS_URL=self requires local actions use short form
(cal/gitea-actions/...) so the runner passes its auth token, and
GitHub actions use full URLs (https://github.com/...) to bypass
local resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:32:15 -06:00
cal
e0d86785a6 Merge pull request 'fix: Use Gitea API for CI tag creation' (#12) from fix/ci-tag-release-api into main
All checks were successful
Build Docker Image / build (push) Successful in 48s
Reviewed-on: #12
2026-02-17 23:28:52 +00:00
Cal Corum
5745a2334a fix: use Gitea API for tag creation to avoid branch protection failures
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m10s
The git push approach fails on protected main branches. Switch to the
Gitea REST API (POST /repos/{repo}/tags) matching the fix already
applied to Paper Dynasty's workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:27:17 -06:00
cal
af2fbc0234 Merge pull request 'ci: Switch to CalVer (YYYY.MM.BUILD) with auto-generated versions' (#11) from ci/calver into main
Some checks failed
Build Docker Image / build (push) Failing after 48s
Reviewed-on: #11
2026-02-17 23:05:16 +00:00
Cal Corum
c030a2835e ci: Switch to CalVer (YYYY.MM.BUILD) with auto-generated versions
All checks were successful
Build Docker Image / build (pull_request) Successful in 47s
Remove manual semver validation from PR checks. Versions are now
auto-generated on merge to main by counting existing monthly tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:02:59 -06:00
cal
d889106c4b Merge pull request 'ci: Switch to CalVer versioning' (#10) from ci/calver into main
Some checks failed
Build Docker Image / build (push) Failing after 58s
Reviewed-on: #10
2026-02-17 22:31:50 +00:00
Cal Corum
d4dbe8f019 ci: Switch to CalVer (YYYY.MM.BUILD) with auto-generated versions
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m11s
Remove manual semver validation from PR checks. Versions are now
auto-generated on merge to main by counting existing monthly tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:29:24 -06:00
cal
4eddcd112f Merge pull request 'fix: roster validation includes pending trades, fixes sWAR field' (#9) from bugfix/roster-validation-fixes into main
All checks were successful
Build Docker Image / build (push) Successful in 52s
Reviewed-on: #9
2026-02-16 05:00:31 +00:00
Cal Corum
c1ae955155 Bump version to 2.29.9
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m21s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:58:55 -06:00
Cal Corum
f29cccd3ab fix: roster validation now includes pending trades and fixes sWAR field name
Some checks failed
Build Docker Image / build (pull_request) Failing after 15s
RosterValidation used total_wara instead of total_sWAR, causing /legal
to silently fail. Transaction embed and submit validation now pass
next_week to validate_transaction() so pending trades are included in
roster count projections. Moved lazy imports to top-level in
transaction_embed.py. Fixed dropadd integration test fixtures that
exceeded sWAR cap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:57:06 -06:00
cal
25ba45e529 Merge pull request 'Fix thaw report channel lookup' (#8) from fix/thaw-report-channel into main
All checks were successful
Build Docker Image / build (push) Successful in 49s
Reviewed-on: #8
2026-02-16 00:02:29 +00:00
Cal Corum
67de736581 Add production environment details to CLAUDE.md
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m8s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:01:55 -06:00
Cal Corum
bf2f3005c3 Bump version to 2.29.8, fix stale deploy script reference in CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:01:55 -06:00
Cal Corum
23d8129b80 Fix thaw report posting to use channel ID instead of nonexistent channel names
The Saturday thaw report was silently failing because it searched for
channels named 'bot-admin', 'admin', or 'bot-logs' which don't exist.
Now uses a configurable channel ID (overridable via THAW_REPORT_CHANNEL_ID).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:01:39 -06:00
cal
8a4c6e459d Merge pull request 'fix: add stadium image link to weather command' (#7) from bugfix/weather-image-link into main
All checks were successful
Build Docker Image / build (push) Successful in 47s
Reviewed-on: #7
2026-02-13 20:55:42 +00:00
Discord Bot
4db02a516a fix: add stadium image link to weather command
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m11s
Add clickable link field to weather embed as fallback for Discord
caching issues. Users can click the link to view the stadium image
in their browser if the embedded image fails to render.

Changes:
- Added "Stadium Image" field with direct link to team.stadium
- Bump version to 2.29.7

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 20:52:10 +00:00
cal
cb6be23b3b Merge pull request 'chore: Compress CLAUDE.md from 775 to 67 lines' (#6) from chore/compress-claude-md into main
All checks were successful
Build Docker Image / build (push) Successful in 49s
Reviewed-on: #6
2026-02-13 20:41:17 +00:00
cal
8693576f1c Update .gitea/workflows/docker-build.yml
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m12s
2026-02-13 20:36:59 +00:00
cal
c0619e78a6 Update VERSION
Some checks failed
Build Docker Image / build (pull_request) Failing after 1m2s
2026-02-13 20:26:47 +00:00
Cal Corum
2c6cc499fa Audit and compress CLAUDE.md from 775 to 67 lines
Some checks failed
Build Docker Image / build (pull_request) Failing after 15s
Remove historical changelogs, redundant documentation references,
and content already covered by parent/sub-directory CLAUDE.md files.
Update deployment section to reflect Gitea Actions workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:24:22 -06:00
cal
d40ddb76be Merge pull request 'ci: switch Docker build cache to type=registry' (#5) from ci/registry-cache into main
All checks were successful
Build Docker Image / build (push) Successful in 4m7s
2026-02-11 22:14:23 +00:00
cal
d72595cef7 ci: switch Docker build cache from type=gha to type=registry
Some checks failed
Build Docker Image / build (pull_request) Failing after 16s
The gha cache backend silently fails on Gitea Actions due to Docker
networking issues between the Buildx builder container and the
act_runner cache server. Registry-based caching stores layers on
Docker Hub, which is more reliable for self-hosted runners.
2026-02-11 22:12:21 +00:00
cal
0ed0446607 Merge pull request 'Raise exception on spreadsheet errors instead of silently skipping' (#4) from fix/validate-spreadsheet-decision-data into main
All checks were successful
Build Docker Image / build (push) Successful in 44s
Reviewed-on: #4
2026-02-06 13:55:52 +00:00
cal
085e76134b Update VERSION
All checks were successful
Build Docker Image / build (pull_request) Successful in 34s
2026-02-06 07:54:33 -06:00
Cal Corum
1d08dc1755 Raise exception on spreadsheet errors instead of silently skipping
**Problem:**
The _is_spreadsheet_error() check was logging a warning and silently skipping
rows with formula errors (#REF!, #N/A, etc.). This could lead to incomplete
game data being submitted without the user knowing.

**Solution:**
Raise SheetsException immediately when spreadsheet errors are detected,
providing:
- Exact row number and field name
- Actual error value found in the cell
- Common error type explanations
- Clear action required to fix

**Impact:**
- Users get immediate feedback about spreadsheet errors
- No partial/incomplete data submitted to API
- Clear instructions on what needs to be fixed
- Better data integrity

**Example Error Message:**
```
 Spreadsheet Error Detected

**Location:** Row 7, Column 'pitcher_id'
**Value Found:** `#REF!`

This cell contains a formula error that must be fixed before submission.

**Action Required:** Fix cell pitcher_id in row 7 and resubmit.
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 07:54:33 -06:00
cal
ff3f9a0d1d Merge pull request 'fix: Validate and sanitize pitching decision data from Google Sheets' (#3) from fix/validate-spreadsheet-decision-data into main
All checks were successful
Build Docker Image / build (push) Successful in 1m10s
Reviewed-on: #3
2026-02-06 13:38:36 +00:00
cal
2be93dfc8a Update VERSION
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m32s
2026-02-06 13:35:49 +00:00
Cal Corum
92eb9055f1 fix: Validate and sanitize pitching decision data from Google Sheets
Some checks failed
Build Docker Image / build (pull_request) Failing after 19s
Added robust validation to handle spreadsheet errors and invalid data
when reading pitching decisions from scorecards.

Problem:
- POST /api/v3/decisions was failing with 422 errors
- Google Sheets cells containing "#N/A" were passed directly to API
- API correctly rejected invalid team_id values like "#N/A" string
- No validation of integer fields or required fields

Root Cause:
- sheets_service.py:read_pitching_decisions() read values without
  validation or type checking
- Spreadsheet formula errors (#N/A, #REF!, etc.) passed through
- Invalid data types not caught until API validation failed

Solution:
1. Added _is_spreadsheet_error() to detect formula errors
2. Added _sanitize_int_field() to validate and convert integers
3. Enhanced read_pitching_decisions() to:
   - Detect and skip rows with spreadsheet errors
   - Validate integer fields (pitcher_id, team_id, etc.)
   - Ensure required fields (pitcher_id, team_id) are present
   - Log warnings for invalid data with row numbers
   - Only return valid, sanitized decision data

Impact:
- Prevents 422 errors from bad spreadsheet data
- Provides clear warnings in logs when data is invalid
- Gracefully skips invalid rows instead of crashing
- Helps identify scorecard data entry errors

Testing:
- Handles #N/A, #REF!, #VALUE!, #DIV/0! and other errors
- Converts "123.0" strings to integers correctly
- Validates required fields before sending to API
- Logs row numbers for debugging bad data

Production logs showed:
  "Input should be a valid integer, unable to parse string as
   an integer", input: "#N/A" for team_id field

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 21:44:06 -06:00
cal
e0af40804d Merge pull request 'chore-cc-update' (#2) from chore-cc-update into main
All checks were successful
Build Docker Image / build (push) Successful in 1m29s
Reviewed-on: #2
2026-02-06 02:46:46 +00:00