Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions .github/skills/review-pr-comments/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
name: review-pr-comments
description: This is used to review comments on an active pull request and decide whether to accept, iterate, or reject the changes suggested in each comment.
---
We have received comments on the current active pull request. Together, we will go through each comment one by one and discuss whether to accept the change, iterate on it, or reject the change.

## Steps to follow:

1. Fetch the active pull request: If available, use the `activePullRequest` tool from the `GitHub Pull Requests` toolset to get the details of the active pull request including the comments. If not, use the GitHub MCP server or GitHub CLI to get the details of the active pull request. Fetch both top level comments and inline comments.
2. Present a list of the comments with a one-sentence summary of each.
3. One at a time, present each comment in full detail and ask me whether to accept, iterate, or reject the change. Provide your recommendation for each comment based on best practices, code quality, and project guidelines. Await user's decision before proceeding to the next comment. DO NOT make any changes to the code or files until I have responded with my decision for each comment.
4. If the decision is to accept or iterate, make the necessary code changes to address the comment. If the decision is to reject, provide a brief explanation of why the change was not made.
5. Wait for user to affirm completion of any code changes made before moving to the next comment.
6. Reply to each comment on the pull request with the outcome of our discussion (accepted, iterated, or rejected) along with any relevant explanations.


## How to reply to PR review comments

This guide explains how to reply directly to inline review comments on GitHub pull requests.

### API Endpoint

To reply to an inline PR comment, use:

```http
POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies
```

With body:

```json
{
"body": "Your reply message"
}
```

### Using gh CLI

```bash
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies \
-X POST \
-f body="Your reply message"
```

### Workflow

1. **Get PR comments**: First fetch the PR review comments to get their IDs:

```bash
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments
```

2. **Identify comment IDs**: Each comment has an `id` field. For threaded comments, use the root comment's `id`.

3. **Post replies**: For each comment you want to reply to:

```bash
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies \
-X POST \
-f body="Fixed in commit abc123"
```

### Example Replies

For accepted changes:

- "Fixed in {commit_sha}"
- "Accepted - fixed in {commit_sha}"

For rejected changes:

- "Rejected - {reason}"
- "Won't fix - {explanation}"

For questions:

- "Good catch, addressed in {commit_sha}"

## Notes

- The `comment_id` is the numeric ID from the comment object, NOT the `node_id`
- Replies appear as threaded responses under the original comment
- You can reply to any comment, including bot comments (like Copilot reviews)

### Resolving Conversations

To resolve (mark as resolved) PR review threads, use the GraphQL API:

1. **Get thread IDs**: Query for unresolved threads:

```bash
gh api graphql -f query='
query {
repository(owner: "{owner}", name: "{repo}") {
pullRequest(number: {pull_number}) {
reviewThreads(first: 50) {
nodes {
id
isResolved
comments(first: 1) {
nodes { body path }
}
}
}
}
}
}'
```

2. **Resolve threads**: Use the `resolveReviewThread` mutation:

```bash
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "PRRT_xxx"}) {
thread { isResolved }
}
}'
```

3. **Resolve multiple threads at once**:

```bash
gh api graphql -f query='
mutation {
t1: resolveReviewThread(input: {threadId: "PRRT_xxx"}) { thread { isResolved } }
t2: resolveReviewThread(input: {threadId: "PRRT_yyy"}) { thread { isResolved } }
}'
```

The thread ID starts with `PRRT_` and can be found in the GraphQL query response.

Note: This skill can be removed once the GitHub MCP server has added built-in support for replying to PR review comments and resolving threads.
See:
https://github.com/github/github-mcp-server/issues/1323
https://github.com/github/github-mcp-server/issues/1768
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ jobs:
echo "resource_group_name=$(terraform output -raw AZURE_RESOURCE_GROUP)" >> "$GITHUB_OUTPUT"
echo "container_registry_name=$(terraform output -raw AZURE_CONTAINER_REGISTRY_NAME)" >> "$GITHUB_OUTPUT"
echo "container_registry_endpoint=$(terraform output -raw AZURE_CONTAINER_REGISTRY_ENDPOINT)" >> "$GITHUB_OUTPUT"
echo "api_url=$(terraform output -raw apiUrl)" >> "$GITHUB_OUTPUT"
echo "api_url=$(terraform output -raw api_url)" >> "$GITHUB_OUTPUT"

# -----------------------------------------------------------------------
# Deploy — build image, push, update container app (push to main only)
Expand Down
44 changes: 44 additions & 0 deletions api/alembic/versions/0016_drop_redundant_indexes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Drop redundant submission indexes.

Revision ID: 0006
Revises: 0005
Create Date: 2025-07-18

Removes 3 overlapping indexes on the submissions table:
- ix_submissions_user_phase_validated (partial index, covered by user_phase_req)
- ix_submissions_user_updated_at (no query uses just user_id + updated_at)
- ix_submissions_user_req_verified_updated (over-specific, covered by user_req_latest)
"""

from alembic import op

revision = "0016_drop_redundant_indexes"
down_revision = "0015_add_ci_status_submission_type"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.drop_index("ix_submissions_user_phase_validated", table_name="submissions")
op.drop_index("ix_submissions_user_updated_at", table_name="submissions")
op.drop_index("ix_submissions_user_req_verified_updated", table_name="submissions")


def downgrade() -> None:
op.create_index(
"ix_submissions_user_req_verified_updated",
"submissions",
["user_id", "requirement_id", "verification_completed", "updated_at"],
)
op.create_index(
"ix_submissions_user_updated_at",
"submissions",
["user_id", "updated_at"],
)
# Partial index — PostgreSQL-specific
op.create_index(
"ix_submissions_user_phase_validated",
"submissions",
["user_id", "phase_id"],
postgresql_where="is_validated",
)
100 changes: 0 additions & 100 deletions api/assets/Logo-03.svg

This file was deleted.

4 changes: 2 additions & 2 deletions api/core/azure_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
wait_exponential,
)

AZURE_TOKEN_TIMEOUT = 30
from core.config import get_settings

_AZURE_RETRY_ATTEMPTS = 3
_AZURE_RETRY_MIN_WAIT = 1 # seconds
Expand Down Expand Up @@ -91,7 +91,7 @@ async def get_token() -> str:
"""
credential = await get_credential()
try:
async with asyncio.timeout(AZURE_TOKEN_TIMEOUT):
async with asyncio.timeout(get_settings().db_timeout):
return await asyncio.to_thread(_get_token_sync, credential)
except TimeoutError:
# Reset credential on timeout in case it's in a bad state
Expand Down
84 changes: 0 additions & 84 deletions api/core/cache.py

This file was deleted.

Loading
Loading