Skip to content

Conversation

@drazisil-codecov
Copy link
Contributor

@drazisil-codecov drazisil-codecov commented Jan 12, 2026

Summary

Adds get_provider_service() to BaseCodecovTask for unified handling of GitHub app availability errors. This replaces duplicated error handling across tasks with a single wrapper that:

  • Retries when GitHub apps are rate-limited (using API retry-after or next hour)
  • Returns None gracefully when apps are suspended/unavailable
  • Handles OwnerWithoutValidBotError and RepositoryWithoutValidBotError uniformly
  • Includes proper logging context and breadcrumb tracking

Updates sync_repos, sync_teams, commit_update, preprocess_upload, and upload_finisher to use the new centralized method.

Fixes

  • WORKER-TRS (~391k events) - NoConfiguredAppsAvailable in UploadFinisher
  • WORKER-P4H (~375k events) - OwnerWithoutValidBotError in SyncRepos
  • WORKER-NVD (~124k events) - NoConfiguredAppsAvailable in commit_update
  • WORKER-NVE (~119k events) - NoConfiguredAppsAvailable in preprocess_upload

Behavior

When NoConfiguredAppsAvailable is raised:

  • If rate_limited_count > 0: At least one GitHub app exists but is rate-limited. The task retries using earliest_retry_after_seconds from the API response, or falls back to get_seconds_to_next_hour() (minimum 60 seconds).
  • If rate_limited_count == 0: No apps are configured or all are suspended. Returns None gracefully.

Why This Matters

These exceptions are expected states for some customers:

  • They may not have a GitHub App installed
  • They may be using OAuth tokens that have expired
  • GitHub may be temporarily rate-limiting their app

Previously, these bubbled up as unhandled exceptions. Now they:

  • ✅ Automatically retry when rate-limited (instead of failing)
  • ✅ Don't create separate Sentry error issues
  • ✅ Still appear as breadcrumbs in traces
  • ✅ Still get logged for observability

Total Impact

This PR eliminates approximately ~1M Sentry events/month from expected bot configuration states and adds automatic retry for rate-limited scenarios.


Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. In 2022 this entity acquired Codecov and as result Sentry is going to need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.


Note

Unifies provider-service fetching and error handling across worker tasks with rate-limit-aware retries and richer logging/breadcrumbs.

  • Adds BaseCodecovTask.get_provider_service() to centralize handling of NoConfiguredAppsAvailable, OwnerWithoutValidBotError, RepositoryWithoutValidBotError, Torngit* errors, including breadcrumb emission and contextual logging
  • Updates sync_repos and sync_teams to use the centralized helper; gracefully no-op when no provider service is available
  • Enhances commit_update, preprocess_upload, and upload_finisher to retry when apps are rate-limited and return errors when apps are suspended/unavailable; adds corresponding breadcrumbs
  • Extends NoConfiguredAppsAvailable with earliest_retry_after_seconds; retry delay uses this value or falls back to get_seconds_to_next_hour() (min 60s)
  • Broad test coverage added/updated for new behaviors and logging; minor log/message clarifications

Written by Cursor Bugbot for commit f3dcdea. This will update automatically on new commits. Configure here.

@sentry
Copy link

sentry bot commented Jan 12, 2026

Codecov Report

❌ Patch coverage is 94.44444% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.35%. Comparing base (6e3603b) to head (f3dcdea).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
apps/worker/tasks/sync_repos.py 71.42% 2 Missing ⚠️
apps/worker/tasks/sync_teams.py 50.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #649      +/-   ##
==========================================
- Coverage   93.35%   93.35%   -0.01%     
==========================================
  Files        1292     1292              
  Lines       47128    47188      +60     
  Branches     1567     1567              
==========================================
+ Hits        43996    44052      +56     
- Misses       2823     2827       +4     
  Partials      309      309              
Flag Coverage Δ
apiunit 96.55% <ø> (ø)
workerintegration 59.04% <41.66%> (-0.10%) ⬇️
workerunit 91.23% <81.94%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@codecov-notifications
Copy link

codecov-notifications bot commented Jan 12, 2026

Codecov Report

❌ Patch coverage is 94.44444% with 4 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
apps/worker/tasks/sync_repos.py 71.42% 2 Missing ⚠️
apps/worker/tasks/sync_teams.py 50.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@drazisil-codecov drazisil-codecov requested a review from a team January 14, 2026 13:05
@drazisil-codecov drazisil-codecov force-pushed the joebecher/handle-expected-bot-errors-as-warnings branch from a76563b to 4834d5d Compare January 14, 2026 14:32
@drazisil-codecov drazisil-codecov changed the title fix(worker): handle expected bot errors as warnings instead of errors fix(worker): add retry for rate-limited GitHub apps and handle bot errors gracefully Jan 16, 2026
…or rate limits

Add get_provider_service() to BaseCodecovTask for unified handling of GitHub app
availability errors. This replaces duplicated error handling across tasks with a
single wrapper that:

- Retries when GitHub apps are rate-limited (using API retry-after or next hour)
- Returns None gracefully when apps are suspended/unavailable
- Handles OwnerWithoutValidBotError and RepositoryWithoutValidBotError uniformly
- Includes proper logging context and breadcrumb tracking

Updates sync_repos, sync_teams, commit_update, preprocess_upload, and
upload_finisher to use the new centralized method.

Fixes:
- WORKER-TRS (~391k events) - NoConfiguredAppsAvailable in UploadFinisher
- WORKER-P4H (~375k events) - OwnerWithoutValidBotError in SyncRepos
- WORKER-NVD (~124k events) - NoConfiguredAppsAvailable in commit_update
- WORKER-NVE (~119k events) - NoConfiguredAppsAvailable in preprocess_upload
@drazisil-codecov drazisil-codecov force-pushed the joebecher/handle-expected-bot-errors-as-warnings branch from 3f4ef3c to ae83fb6 Compare January 16, 2026 17:11
@drazisil-codecov drazisil-codecov changed the title fix(worker): add retry for rate-limited GitHub apps and handle bot errors gracefully feat(worker): centralize provider service error handling with retry for rate limits Jan 16, 2026
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

…ception

The exception handler in base.py accesses exp.earliest_retry_after_seconds
but this attribute was never defined on the exception class. This caused
an AttributeError at runtime when GitHub apps were rate-limited.

Adds the optional parameter with a default of None, which allows the
existing fallback logic (get_seconds_to_next_hour()) to work correctly.
The get_provider_service method uses commit.repoid when a commit is
provided, so tests need to set mock_commit.repoid to match the expected
values in breadcrumb task assertions.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if exp.rate_limited_count > 0:
# At least one GitHub app is available but rate-limited. Retry after
# waiting until the next hour (minimum 1 minute delay).
retry_delay_seconds = max(60, get_seconds_to_next_hour())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate limit retry ignores API-provided retry-after time

Medium Severity

The duplicated NoConfiguredAppsAvailable exception handling in commit_update.py, preprocess_upload.py, and upload_finisher.py calculates retry delay using only get_seconds_to_next_hour(), ignoring the earliest_retry_after_seconds field from the exception. The centralized get_provider_service method in base.py correctly checks this field first. This inconsistency means tasks may retry too early (wasting API calls and hitting rate limits again) or unnecessarily late, depending on what the API recommends.

Additional Locations (2)

Fix in Cursor Fix in Web

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 16, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing joebecher/handle-expected-bot-errors-as-warnings (f3dcdea) with main (b75c63d)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (5ea839e) during the generation of this report, so b75c63d was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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.

2 participants