Event Management Automation keeps two public Google Calendars up to date:
- selected Pokémon GO events;
- selected VALORANT Champions Tour fixtures.
The application fetches public event data, validates and normalises it, applies the filters in
config/feeds.yml, and reconciles the result with Google Calendar. It runs
automatically through GitHub Actions, uses Europe/London-aware date handling, and only modifies
events that it owns.
You do not need to run this project to use the calendars:
Google will ask which account should subscribe to the calendar. Once added, updates made by this project appear automatically.
- The Pokémon source reads ScrapedDuck's event feed. The configured event-type whitelist is applied before each event is converted into either a timed or one-day all-day calendar event.
- The VALORANT source requests upcoming fixtures from the
vlresportsAPI. If that provider is unavailable or invalid, VLRdevAPI reads the public VLR.gg match listing as a fallback. - Both feeds are converted to the same internal event model. Timezone-less Pokémon timestamps are interpreted as Europe/London wall times; timezone-aware timestamps are treated as absolute instants.
- Each Google event receives private ownership metadata containing the feed and stable upstream identifier.
- A reconciliation run compares desired events with owned Google events and calculates creates, full updates, deletions, and unchanged events. Manual or unrelated events are never selected.
- Safety limits stop unexpectedly large deletions. A source failure never causes its calendar to be emptied.
The application is stateless: Google Calendar is the destination state, and no production JSON cache or continuously running server is required.
This project would not exist without the people maintaining the underlying community data sources:
- ScrapedDuck by bigfoott provides the Pokémon GO event data collected from Leek Duck.
- vlresports by Orloxx23 provides the primary VALORANT matches API hosted at vlr.orlandomm.net.
- VLRdevAPI by Vanshbordia provides the fallback client for public VLR.gg match data.
- Google Calendar API provides the calendar integration.
Huge credit and thanks to their creators and maintainers. Pokémon, Pokémon GO, VALORANT, Riot Games, VLR.gg, Leek Duck, and Google are owned by their respective rights holders. This personal project is not affiliated with or endorsed by them.
config/feeds.yml Version-controlled filters and behaviour
docs/CONFIGURATION.md Complete configuration reference and change recipes
docs/AUTOMATION.md GitHub Actions, Google authentication and operations guide
src/calendar_sync/ Application package
tests/ Unit and regression tests
.github/workflows/ci.yml Pull-request and main-branch quality checks
.github/workflows/sync.yml Scheduled, post-merge and manual calendar sync
.github/workflows/migrate.yml Protected one-time v1 migration and rollback backup
Python 3.12 and uv are required.
uv sync --all-extras --locked
Copy-Item .env.example .envFill in the two calendar IDs and local Google credential path in .env, then run:
uv run calendar-sync validate-config
uv run calendar-sync source-smoke --feed all
uv run ruff format --check .
uv run ruff check .
uv run mypy
uv run pytest
uv run calendar-sync sync --feed all --dry-runThe final command reads the real sources and calendars but does not write anything. Review its counts before running a live sync:
uv run calendar-sync sync --feed all.env and credential JSON files are intentionally ignored by Git and must never be committed.
GitHub Actions authenticates without a JSON key by using Google Workload Identity Federation.
Start with the guide that matches the change:
- Configuration guide: Pokémon event types, timed/all-day behaviour, VALORANT patterns, timezone, colours, deletion limits, environment variables, and common edits.
- Automation and operations guide: CI/CD triggers, GitHub variables and environments, Workload Identity Federation, manual runs, deployment, migration, rollback, and troubleshooting.
For every behavioural change:
- edit
config/feeds.ymlor the relevant source code; - add or update a regression test;
- run the local quality commands above;
- run a dry sync and review creates, updates, and deletions;
- open a pull request and wait for CI;
- merge only when the reported calendar changes are expected.
Production syncs run at 03:17 and 15:17 Europe/London and after successful CI on main, provided
the repository variable CALENDAR_SYNC_ENABLED is set to true.