Skip to content

GitHub activity: exclude bootstrap account; fresh get_team; shared CDN prefix - #287

Merged
gregv merged 1 commit into
developfrom
fix/github-activity-exclusions-team-cache-cdn
Sep 21, 2026
Merged

gregv merged 1 commit into
developfrom
fix/github-activity-exclusions-team-cache-cdn

Conversation

@gregv

@gregv gregv commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

What

Three fixes found while testing the team dashboard on test.ohack.dev. Pairs with frontend PR opportunity-hack/frontend-ohack.dev#370 (which only changes when the activity fetch fires; this PR changes what it returns).

1. get_repo_activity ignores the repo-bootstrap account

create_github_repo seeds LICENSE + README as the GITHUB_TOKEN owner, so every new team repo reported "2 commits, last commit by gregv" and the dashboard's "Push code to your repo" row was already done. Commits by GITHUB_ACTIVITY_EXCLUDED_LOGINS (comma-separated, case-insensitive, default gregv) are dropped before any counting — total_recent, last_24h, last commit and contributors. Matched on GitHub login, or the git author name for unlinked commits. Still exactly 3 GitHub calls. Trade-off: real commits by that account are hidden too.

2. get_team reads the team doc fresh (per-worker cache staleness)

Gunicorn runs --workers 2; every TTLCache is per process, so clear_cache() after a project save only busted the worker that handled it. The public team page's refetch hit the other worker ~half the time and got a story up to 10 min old. The team doc is one Firestore get and is now uncached; only the member-profile db.get_all fan-out is cached (_TEAM_USERS_CACHE, keyed by tuple of member ids). doc_to_json's cache is safe because DocumentSnapshot.__hash__ includes update_time. Documented in CLAUDE.md; the event payload cache (get_single_hackathon_event) still has this cross-worker lag — noted, not changed.

3. One cdn_server() for URL producers and validators

upload_to_cdn read CDN_SERVER at import (no default, no trailing-slash trim) while the submissions validator defaulted to https://cdn.ohack.dev and trimmed — an unset or …/-suffixed env on test produces exactly "Thumbnail: must be an ohack CDN URL under teams//". Both now use common/utils/cdn.py::cdn_server() (lazy, normalized, defaulted). Rejections log url + expected prefix at WARNING. Not confirmed against the test service's env — if it recurs, that log line names the mismatch. api/jobs / users_service keep their own copies for now (noted in CLAUDE.md).

Tests

pytest api/github/tests/test_github_activity.py api/submissions/tests/test_submissions_service.py api/peer_votes/tests/test_peer_votes_service.py → 121 passed. New: 3 exclusion tests (bootstrap-only repo → all zeros; first non-excluded commit is "last"; env override) + 1 trailing-slash-env prefix-agreement test.

Deploy order

Deploy this before relying on the frontend PR's numbers. No env change needed unless the token owner changes (GITHUB_ACTIVITY_EXCLUDED_LOGINS).

Test plan (test.ohack.dev after deploy)

  1. /hack/fall-2026/manageteam#project — team repo with only the two seed commits: "Push code to your repo" → "No commits yet"; Code activity card shows 0 commits/24h, 0 contributors, no gregv avatar. GET /api/github/activity?org=…&repo=…commits.total_recent: 0.
  2. Push one commit as another account → row flips to done; card shows that author as last commit and contributor.
  3. Edit the project story on the dashboard, wait for "Saved just now", then reload /hack/fall-2026/team/8ca80174b52511f19a2bdeadda6592f3 4–5 times in a row — every load shows the new text (previously ~half showed the old one for up to 10 min).
  4. Upload a thumbnail on the dashboard — no "must be an ohack CDN URL" line; the image persists after reload and appears on the team page. If it still errors, Render logs will contain _validate_own_cdn_image: rejected url=… expected prefix=….
  5. Mentor panel on /hack/fall-2026/team/<id>/mentor — raise/clear a flag, reload: still reflected immediately (cache path unchanged for mentor writes, now also worker-independent).

🤖 Generated with Claude Code

…N prefix

Three fixes found testing the team dashboard on test.ohack.dev:

- get_repo_activity drops commits by GITHUB_ACTIVITY_EXCLUDED_LOGINS
  (default gregv). create_github_repo seeds LICENSE + README as the token
  owner, so every new team repo showed "2 commits, last commit by gregv"
  and the dashboard's "Push code to your repo" row was done before the
  team pushed anything. Matched on GitHub login or, for unlinked commits,
  the git author name; counts, last commit and contributors all exclude.

- get_team is no longer @cached whole. Gunicorn runs --workers 2 and the
  TTL caches are per process, so a project save only busted the cache in
  the worker that handled it and the public team page kept showing the
  old story for up to 10 min about half the time. The team doc is one
  Firestore get and is now read fresh; only the member-profile fan-out
  (db.get_all over users) is cached, keyed by the tuple of member ids.

- common/utils/cdn.py::cdn_server() is the single, lazily-read, normalized
  CDN origin (rstrip("/"), default https://cdn.ohack.dev). upload_to_cdn /
  generate_signed_upload_url build URLs with it and the submissions
  validator delegates to it, so "Thumbnail: must be an ohack CDN URL under
  teams/<id>/" can't come from the two sides reading CDN_SERVER
  differently. Rejections now log the URL + expected prefix at WARNING.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gregv
gregv merged commit d1923b4 into develop Sep 21, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant