Skip to content

Conversation

@Akkikens
Copy link
Contributor

@Akkikens Akkikens commented Dec 22, 2025

- Add /webhooks/github endpoint with signature verification
- Implement pull_request event handler with support for:
  - opened: create Asana task
  - assigned/unassigned/edited: sync assignees
  - closed: mark task complete
  - reopened: reopen task
  - synchronize: no-op
- Add structured logging and plan objects for observability
- Implement Asana task creation with GitHub login to Asana email mapping
- Add task lookup by GitHub URL (custom field + notes fallback)
- Implement task assignment and completion updates
- Add PR description update with Asana task link
- Use Asana Roster Project for user mapping
- Integrate Datadog metrics client
- Track counters: tasks_created, tasks_completed, tasks_reopened, assign_updates, noops, mapping_failures
- Track latency histograms for webhook processing and Asana API calls
- Emit structured metrics with tags for filtering
- Implement exponential backoff with jitter (500ms-8s, max 3 retries)
- Handle HTTP 429 rate limits with Retry-After header support
- Retry on 5xx server errors, fail fast on 4xx client errors
- Add dead-letter logging and metrics for exhausted retries
- Wrap all Asana write operations with retry decorator
- Add environment variables: GITHUB_WEBHOOK_SECRET, ASANA_PAT, ASANA_WORKSPACE_GID, ASANA_PROJECT_GID
- Register webhook router in FastAPI app
- Configure Docker Compose for local development
- Add Terraform variables and Kubernetes secrets for deployment
- Add asana>=5.2.2 for Asana API client
- Add httpx>=0.28.1 for async HTTP requests
- Add tenacity>=8.2.3 for retry logic with exponential backoff
- Exclude test_webhook_*.sh scripts
- Exclude WEBHOOK_DESIGN.md and PHASE*.md documentation files
- Update docstring to document all supported PR actions
- Add try/except for JSON parsing errors
- Wrap pull_request handler in try/except to prevent 500s
- Return structured dead-letter response on unexpected errors
- Add metrics for dead-letter webhook errors
- Move _resolve_assignee to top-level imports (remove inline imports)
- Update docstring to reflect all supported PR actions
- Improve code clarity and maintainability
- Add ASANA_RETRY_MAX_ATTEMPTS, ASANA_RETRY_INITIAL_DELAY_MS, ASANA_RETRY_MAX_DELAY_MS to config
- Update all retry_with_backoff calls to use config values
- Enable runtime tuning of retry behavior without code changes
- Document all emitted metrics with descriptions
- Clarify difference between sync.latency_ms and webhook.latency_ms
- Improve observability documentation for dashboards
- Add comment about regex robustness in PR description updates
- Fix import order in retry.py (move asyncio to top)
- Remove unused time import
- Add requests>=2.31.0 to dependencies
- Required for _get_github_to_asana_mapping function
- Prevents ImportError that causes mapping failures
- remove tasks_created increment (already done in pr_handler)
- remove assign_updates increment (already done in pr_handler)
- remove tasks_completed/tasks_reopened increments (already done in pr_handler)
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +377 to +378
def _update_assignee():
tasks_api.update_task({"data": task_data}, task_gid, {})

Choose a reason for hiding this comment

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

P1 Badge Fix argument order when updating task assignee

In update_task_assignee the call to TasksApi.update_task passes the request body first and the task GID second (update_task({"data": task_data}, task_gid, {})), but the Asana client expects update_task(task_gid, body, opts). This argument reversal raises a TypeError before any HTTP call is made, so every assigned/unassigned/edited webhook exhausts retries and dead-letters instead of updating the task assignee.

Useful? React with 👍 / 👎.

Comment on lines +430 to +431
def _update_completed():
tasks_api.update_task({"data": task_data}, task_gid, {})

Choose a reason for hiding this comment

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

P1 Badge Correct update_task invocation for completion status

Similarly in update_task_completed the call tasks_api.update_task({"data": task_data}, task_gid, {}) supplies the payload before the task GID, which does not match the Asana client signature (task_gid first). This causes completion/reopen webhook actions to fail locally with argument errors and eventually dead-letter after retries, leaving Asana tasks never marked completed or reopened.

Useful? React with 👍 / 👎.

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