fix(copilot): Use state field instead of status for task lifecycle#110793
fix(copilot): Use state field instead of status for task lifecycle#110793
state field instead of status for task lifecycle#110793Conversation
The GitHub Copilot Tasks API returns lifecycle values (queued, in_progress, completed, failed, timed_out) in the `state` field, while `status` is always an empty string. Our polling code was checking `status == "completed"` which was never true, causing Copilot tasks to stay stuck in RUNNING state after completion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/vTbrRfjeNDN7BIW1Jh2qaJrZCaAHBqqDMPUB-etq3w8
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Model field name doesn't match real API response
- Renamed the model field from
last_updated_attoupdated_atto match the real GitHub Copilot API response shape that the test mock uses.
- Renamed the model field from
Or push these changes by commenting:
@cursor push 3f7e5a5018
Preview (3f7e5a5018)
diff --git a/src/sentry/integrations/github_copilot/models.py b/src/sentry/integrations/github_copilot/models.py
--- a/src/sentry/integrations/github_copilot/models.py
+++ b/src/sentry/integrations/github_copilot/models.py
@@ -77,7 +77,7 @@
session_count: int | None = None
artifacts: list[GithubCopilotArtifact] | None = None
archived_at: str | None = None
- last_updated_at: str | None = None
+ updated_at: str | None = None
created_at: str | None = None
sessions: list[GithubCopilotSession] | None = NoneThis Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| repo_id: int | None = None | ||
| status: str | None = None # queued, in_progress, completed, failed, timed_out | ||
| status: str | None = None | ||
| state: str | None = None # queued, in_progress, completed, failed, timed_out |
There was a problem hiding this comment.
Model field name doesn't match real API response
Low Severity
The test mock was updated from "last_updated_at" to "updated_at" to match the real Copilot API response shape, but the GithubCopilotTask model field is still named last_updated_at. Since Pydantic ignores unknown fields by default, the API's updated_at value is silently dropped and last_updated_at will always be None when parsing real API responses. This is the same class of bug this PR fixes for status/state — just for a different field.
Additional Locations (1)
#110793) The GitHub Copilot Tasks API returns task lifecycle values (`queued`, `in_progress`, `completed`, `failed`, `timed_out`) in the `state` field, while the `status` field is always an empty string. Our polling code was checking `task_status.status == "completed"` which was never true, so Copilot tasks would stay stuck in RUNNING state forever after completion — the PR URL and completion state were never synced back to Sentry. Validated by hitting the live Copilot API: created a task, polled until completion, and confirmed that `state` carries the lifecycle values while `status` is always `""`. The partner API spec we were given listed `status` as the field, but the actual API uses `state`. Changes: - Add `state` field to `GithubCopilotTask` model (keep `status` for forward-compat) - Switch polling logic to check `task_status.state` instead of `task_status.status` - Update test mocks to match real API response shapes (`state`, `in_progress`, `github_resource`, `updated_at`) Agent transcript: https://claudescope.sentry.dev/share/7RfoUCo3OmihUbUrznGRpJ0bE9LXTfcbFamSXhLirtc



The GitHub Copilot Tasks API returns task lifecycle values (
queued,in_progress,completed,failed,timed_out) in thestatefield, while thestatusfield is always an empty string. Our polling code was checkingtask_status.status == "completed"which was never true, so Copilot tasks would stay stuck in RUNNING state forever after completion — the PR URL and completion state were never synced back to Sentry.Validated by hitting the live Copilot API: created a task, polled until completion, and confirmed that
statecarries the lifecycle values whilestatusis always"". The partner API spec we were given listedstatusas the field, but the actual API usesstate.Changes:
statefield toGithubCopilotTaskmodel (keepstatusfor forward-compat)task_status.stateinstead oftask_status.statusstate,in_progress,github_resource,updated_at)Agent transcript: https://claudescope.sentry.dev/share/7RfoUCo3OmihUbUrznGRpJ0bE9LXTfcbFamSXhLirtc