Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Changelog

All notable changes to this project will be documented in this file.

All changes were made in collaboration with [Claude](https://claude.ai) (Anthropic).

## [3.0.5]

### Fixed

- `PendingRollbackError` in the safety checker when the SQLite database is locked — added `session.rollback()` in the except block before re-using the session, preventing the fallback commit from also failing
- `TypeError: can't compare offset-naive and offset-aware datetimes` when entering a giveaway — `update_win_check_for_new_entry` now compares both datetimes as timezone-aware, consistent with the `TZDateTime` fix introduced in v3.0.4

## [3.0.4]

### Fixed

- Automation cycle crash when the Steam API returns no review data for a game — review fields (`review_score`, `total_positive`, `total_negative`, `total_reviews`) now fall back to `0` instead of `None` to satisfy the database `NOT NULL` constraint

### Changed

- Replaced all uses of the deprecated `datetime.utcnow()` (52 call sites across 21 files + 19 test files) with `datetime.now(timezone.utc)` — required for Python 3.12+ compatibility
- Added `TZDateTime` SQLAlchemy TypeDecorator to re-attach `timezone.utc` when reading datetimes from SQLite, preventing naive/aware comparison errors
- Fixed CI workflow running 4 jobs per PR instead of 2 — push trigger now limited to `master`

## [3.0.3]

### Fixed

- "Failed to load wins" error on accounts with an expired SteamGifts session — read-only endpoints (Wins, Giveaways) now work regardless of session state; only live SteamGifts operations (entering, scanning) require a valid session
- Corrected misleading label "Min Game Price ($)" → "Min Giveaway Cost (points)" on the Accounts page to reflect that the value is in SteamGifts points, not dollars

### Changed

- Added Dependabot configuration for weekly automated dependency updates across npm (frontend), pip (backend), Docker base images, and GitHub Actions

## [3.0.1]

### Fixed

- Fixed play button on the Accounts page not reflecting automation status correctly on the Dashboard
- Dashboard scheduler status now shows the global scheduler state instead of the selected account's state, so starting automation from the Accounts page is immediately visible on the Dashboard
- Fixed 6 failing unit tests in `test_api_routers_system` after refactoring the logs endpoint to use a direct `NotificationService` instance instead of dependency injection

### Changed

- Logs page now shows entries from all accounts in a single combined view — no longer filtered by the selected account; each log entry displays an account badge
- Accounts no longer scan simultaneously: each additional account receives a 5-minute start offset (account 1 at T+0, account 2 at T+5 min, account 3 at T+10 min, etc.)
- The same staggering is applied automatically on startup for accounts that had automation enabled
- Added a 1-second delay between page requests within a single scan to avoid burst traffic

## [3.0.0]

### Added

- Full multi-account management: create, rename, delete, and switch between accounts
- Account switcher in the sidebar with automation status indicator
- Accounts page with expandable rows for credentials, settings, and per-account scheduler controls
- All settings (DLC, Safety Detection, Auto-Join Rules, Scheduler interval, Rate Limiting) configurable per account
- Per-account scheduler endpoints: start, stop, run cycle, scan, process, sync wins
- Version number (`v3.0.0`) shown at the bottom of the sidebar, sourced from the root `package.json`
- GitHub Actions workflow for automated Docker image publishing to `ghcr.io`

### Changed

- Removed the global Settings page from the navigation; all configuration lives on the Accounts page
- New accounts are created with sensible defaults
- Session cookies (PHPSESSID) are no longer exposed in list API responses; replaced with a `has_credentials` boolean flag
- `set_default` account operation is now atomic to prevent race conditions
- Scheduler jobs are automatically cleaned up when an account is deleted
- Optimistic cache updates: all account mutations update the UI immediately without a full refetch
- Single version number shared between backend (`pyproject.toml`) and frontend (root `package.json` read via Vite `define`)
- Backend process now runs as a non-root `appuser` inside the container
- Added `stopwaitsecs=30` to supervisord for graceful shutdown of in-flight requests
- `docker-compose.yml` is now for external deployments (pulls from `ghcr.io/sjeff/steamselfgifter:latest`)
- `docker-compose.dev.yml` is for local development (builds from source)
- Docker images tagged with `latest` on push to `master`, and semver tags on git tags

### Fixed

- "Session Not Configured" banner now links to the Accounts page instead of the removed Settings page
- Default account credentials section auto-expands when navigating from the setup banner
107 changes: 1 addition & 106 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,112 +197,7 @@ alembic upgrade head

## Changelog

### v3.0.4

All changes in this release were made in collaboration with [Claude](https://claude.ai) (Anthropic).

#### Bug fixes

- Fixed automation cycle crash when the Steam API returns no review data for a game — review fields (`review_score`, `total_positive`, `total_negative`, `total_reviews`) now fall back to `0` instead of `None` to satisfy the database `NOT NULL` constraint

#### Code quality

- Replaced all uses of the deprecated `datetime.utcnow()` (52 call sites across 21 files + 19 test files) with `datetime.now(timezone.utc)` — required for Python 3.12+ compatibility
- Added `TZDateTime` SQLAlchemy TypeDecorator to re-attach `timezone.utc` when reading datetimes from SQLite, preventing naive/aware comparison errors
- Fixed CI workflow running 4 jobs per PR instead of 2 — push trigger now limited to `master`

### v3.0.3

All changes in this release were made in collaboration with [Claude](https://claude.ai) (Anthropic).

#### Bug fixes

- Fixed "Failed to load wins" error on accounts with an expired SteamGifts session — read-only endpoints (Wins, Giveaways) now work regardless of session state; only live SteamGifts operations (entering, scanning) require a valid session
- Corrected misleading label "Min Game Price ($)" → "Min Giveaway Cost (points)" on the Accounts page to reflect that the value is in SteamGifts points, not dollars

#### Dependency management

- Added Dependabot configuration for weekly automated dependency updates across npm (frontend), pip (backend), Docker base images, and GitHub Actions

### v3.0.1

All changes in this release were made in collaboration with [Claude](https://claude.ai) (Anthropic).

#### Activity Logs

- Logs page now shows entries from all accounts in a single combined view — no longer filtered by the selected account
- Each log entry displays an account badge so you can see which account generated it
- Switching accounts in the sidebar no longer affects the logs view
- All log operations (view, clear, export) are now permanently account-agnostic on the backend

#### Automation

- Fixed play button on the Accounts page not reflecting automation status correctly on the Dashboard
- Dashboard scheduler status now shows the global scheduler state instead of the selected account's state, so starting automation from the Accounts page is immediately visible on the Dashboard

#### Bug fixes

- Fixed 6 failing unit tests in `test_api_routers_system` after refactoring the logs endpoint to use a direct `NotificationService` instance instead of dependency injection

#### Rate limiting & scan staggering

- Accounts no longer scan simultaneously: each additional account receives a 5-minute start offset (account 1 at T+0, account 2 at T+5 min, account 3 at T+10 min, etc.)
- The same staggering is applied automatically on startup for accounts that had automation enabled
- Added a 1-second delay between page requests within a single scan to avoid burst traffic

### v3.0.0

All changes in this release were made in collaboration with [Claude](https://claude.ai) (Anthropic).

#### Multi-account support

- Added full multi-account management: create, rename, delete, and switch between accounts
- Account switcher in the sidebar with automation status indicator
- Accounts page with expandable rows for credentials, settings, and per-account scheduler controls
- Default account promotion when the current default is deleted

#### Per-account settings

- All settings (DLC, Safety Detection, Auto-Join Rules, Scheduler interval, Rate Limiting) are now configurable per account
- Removed the global Settings page from the navigation; all configuration lives on the Accounts page
- New accounts are created with sensible defaults

#### Security

- Session cookies (PHPSESSID) are no longer exposed in list API responses; replaced with a `has_credentials` boolean flag
- `set_default` account operation is now atomic (two SQL `UPDATE` statements) to prevent race conditions

#### Automation

- Scheduler jobs are automatically cleaned up when an account is deleted
- Per-account scheduler endpoints: start, stop, run cycle, scan, process, sync wins

#### Frontend improvements

- Optimistic cache updates: all account mutations update the UI immediately without a full refetch
- Version number (`v3.0.0`) shown at the bottom of the sidebar, sourced from the root `package.json`

#### Version management

- Single version number (`3.0.0`) shared between backend (`pyproject.toml`) and frontend (root `package.json` read via Vite `define`)

#### Docker

- Backend process now runs as a non-root `appuser` inside the container
- Added `stopwaitsecs=30` to supervisord for graceful shutdown of in-flight requests
- Stage 3 copies backend source from the build stage instead of re-sending from the build context
- `docker-compose.yml` is now for external deployments (pulls from `ghcr.io/sjeff/steamselfgifter:latest`)
- `docker-compose.dev.yml` is for local development (builds from source)

#### CI/CD

- Added GitHub Actions workflow for automated Docker image publishing to `ghcr.io`
- Images are tagged with `latest` on push to `master`, and semver tags (`3.0.0`, `3.0`, `3`) on git tags

#### Bug fixes

- "Session Not Configured" banner now links to the Accounts page instead of the removed Settings page
- Default account credentials section auto-expands when navigating from the setup banner
See [CHANGELOG.md](CHANGELOG.md) for the full release history.

## Contributing

Expand Down
7 changes: 4 additions & 3 deletions backend/src/services/scheduler_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,10 @@ async def update_win_check_for_new_entry(
# No job exists, schedule one
self._schedule_win_check_job(new_check_time)
elif job.next_run_time:
# Compare naive datetimes (APScheduler returns timezone-aware)
job_next_run_naive = job.next_run_time.replace(tzinfo=None)
if new_check_time < job_next_run_naive:
# Ensure both datetimes are timezone-aware for comparison
job_next_run = job.next_run_time
check_time = new_check_time if new_check_time.tzinfo else new_check_time.replace(tzinfo=timezone.utc)
if check_time < job_next_run:
# New giveaway expires sooner, update the job
self._schedule_win_check_job(new_check_time)

Expand Down
1 change: 1 addition & 0 deletions backend/src/workers/safety_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ async def safety_check_cycle(account_id: int = None) -> Dict[str, Any]:
error=str(e),
error_type=type(e).__name__,
)
await session.rollback()
# Mark as checked but with unknown status to avoid retrying indefinitely
giveaway.is_safe = True # Assume safe on error to not block entry
giveaway.safety_score = 50 # Middle score to indicate uncertainty
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "steamselfgifter",
"version": "3.0.4",
"version": "3.0.5",
"private": true
}
Loading