feat: push interview events to connected calendar integrations #20

Merged
pyr0ball merged 3 commits from feature/calendar-push into main 2026-03-16 21:45:07 -07:00

3 commits

Author SHA1 Message Date
c1ec1fc9f6 feat: push interview events to connected calendar integrations (#19)
All checks were successful
CI / test (pull_request) Successful in 53s
Implements idempotent calendar push for Apple Calendar (CalDAV) and
Google Calendar from the Interviews kanban.

- db: add calendar_event_id column (migration) + set_calendar_event_id helper
- integrations/apple_calendar: create_event / update_event via caldav + icalendar
- integrations/google_calendar: create_event / update_event via google-api-python-client;
  test() now makes a real API call instead of checking file existence
- scripts/calendar_push: orchestrates push/update, builds event title from stage +
  job title + company, attaches job URL and company brief to description,
  defaults to noon UTC / 1hr duration
- app/pages/5_Interviews: "Add to Calendar" / "Update Calendar" button shown
  when interview date is set and a calendar integration is configured
- environment.yml: pin caldav, icalendar, google-api-python-client, google-auth
- tests/test_calendar_push: 9 tests covering create, update, error handling,
  event timing, idempotency, and missing job/date guards
2026-03-16 21:31:22 -07:00
2fcab541c7 fix: bootstrap resume_keywords.yaml on first cloud session
New cloud users got a "resume_keywords.yaml not found" warning in
Settings → Skills & Keywords because the file was never created during
account provisioning. resolve_session() now writes an empty scaffold
(skills/domains/keywords: []) to the user's config dir on first visit
if the file doesn't exist, consistent with how config/ and data/ dirs
are already created. Never overwrites an existing file.
2026-03-16 12:01:25 -07:00
84ae348f16 fix: auto-provision free license on first cloud session, fix score button in Docker
- cloud_session.py: add _ensure_provisioned() called in resolve_session() so
  new Google OAuth signups get a free Heimdall key created on first page load;
  previously resolve returned "free" tier but no key was ever written to
  Heimdall, leaving users in an untracked state
- Home.py: replace conda run invocation in "Score All Unscored Jobs" with
  sys.executable so the button works inside Docker where conda is not present
2026-03-16 11:51:15 -07:00