---
description: Manage and respond to Gitea/Forgejo PR review comments
---

# Gitea PR Review Comments

This skill enables reading PR review comments and posting inline thread replies on Gitea/Forgejo instances.

## Prerequisites

- `tea` CLI configured with a Gitea/Forgejo instance
- Access token from tea config: `~/.config/tea/config.yml`
- Repository must be a Gitea/Forgejo remote (not GitHub)

## Configuration

Get the Gitea instance URL and token from tea config:

```bash
# Get the default login URL and token
yq -r '.logins[] | select(.name == "default") | .url' ~/.config/tea/config.yml
yq -r '.logins[] | select(.name == "default") | .token' ~/.config/tea/config.yml
```

Or if you have a specific login name:
```bash
yq -r '.logins[] | select(.name == "YOUR_LOGIN") | .url' ~/.config/tea/config.yml
yq -r '.logins[] | select(.name == "YOUR_LOGIN") | .token' ~/.config/tea/config.yml
```

## Commands

### 1. List PR Review Comments

Fetch all reviews and their comments for a PR:

```bash
# Set environment variables
GITEA_URL="https://git.johnogle.info"
TOKEN="<your-token>"
OWNER="<repo-owner>"
REPO="<repo-name>"
PR_NUMBER="<pr-number>"

# Get all reviews for the PR
curl -s -H "Authorization: token $TOKEN" \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" | jq

# Get comments for a specific review
REVIEW_ID="<review-id>"
curl -s -H "Authorization: token $TOKEN" \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments" | jq
```

### 2. View All Review Comments (Combined)

```bash
# Get all reviews and their comments in one view
curl -s -H "Authorization: token $TOKEN" \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" | \
  jq -r '.[] | "Review \(.id) by \(.user.login): \(.state)\n  Body: \(.body)"'

# For each review, show inline comments
for REVIEW_ID in $(curl -s -H "Authorization: token $TOKEN" \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" | jq -r '.[].id'); do
  echo "=== Review $REVIEW_ID comments ==="
  curl -s -H "Authorization: token $TOKEN" \
    "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments" | \
    jq -r '.[] | "[\(.path):\(.line)] \(.body)"'
done
```

### 3. Reply to Review Comments (Web Endpoint Method)

The Gitea REST API does not support replying to review comment threads. The web UI uses a different endpoint:

```
POST /{owner}/{repo}/pulls/{pr_number}/files/reviews/comments
Content-Type: multipart/form-data
```

**Required form fields:**
- `reply`: Review ID to reply to
- `content`: The reply message
- `path`: File path
- `line`: Line number
- `side`: `proposed` or `original`
- `single_review`: `true`
- `origin`: `timeline`
- `_csrf`: CSRF token (required for web endpoint)

**Authentication Challenge:**
This endpoint requires session-based authentication, not API tokens. Options:

#### Option A: Use Browser Session (Recommended)

1. Log in to Gitea in your browser
2. Open browser developer tools and copy cookies
3. Use the session cookies with curl

```bash
# First, get CSRF token from the PR page
CSRF=$(curl -s -c cookies.txt -b cookies.txt \
  "$GITEA_URL/$OWNER/$REPO/pulls/$PR_NUMBER/files" | \
  grep -oP 'name="_csrf" value="\K[^"]+')

# Post the reply
curl -s -b cookies.txt \
  -F "reply=$REVIEW_ID" \
  -F "content=Your reply message here" \
  -F "path=$FILE_PATH" \
  -F "line=$LINE_NUMBER" \
  -F "side=proposed" \
  -F "single_review=true" \
  -F "origin=timeline" \
  -F "_csrf=$CSRF" \
  "$GITEA_URL/$OWNER/$REPO/pulls/$PR_NUMBER/files/reviews/comments"
```

#### Option B: Create Top-Level Comment (Fallback)

If thread replies are not critical, use the API to create a top-level comment:

```bash
# Create a top-level comment mentioning the review context
curl -s -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"body\": \"Re: @reviewer's comment on $FILE_PATH:$LINE_NUMBER\n\nYour reply here\"}" \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/issues/$PR_NUMBER/comments"
```

Or use tea CLI:
```bash
tea comment $PR_NUMBER "Re: @reviewer's comment on $FILE_PATH:$LINE_NUMBER

Your reply here"
```

### 4. Submit a New Review

Create a new review with inline comments:

```bash
curl -s -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Overall review comments",
    "event": "COMMENT",
    "comments": [
      {
        "path": "path/to/file.py",
        "body": "Comment on this line",
        "new_position": 10
      }
    ]
  }' \
  "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews"
```

Event types: `COMMENT`, `APPROVE`, `REQUEST_CHANGES`

## Workflow Example

### Reading and Responding to Reviews

1. **Set up environment**:
   ```bash
   export GITEA_URL=$(yq -r '.logins[] | select(.name == "default") | .url' ~/.config/tea/config.yml)
   export TOKEN=$(yq -r '.logins[] | select(.name == "default") | .token' ~/.config/tea/config.yml)
   export OWNER="johno"
   export REPO="nixos-configs"
   export PR_NUMBER="5"
   ```

2. **List all pending review comments**:
   ```bash
   # Get reviews
   curl -s -H "Authorization: token $TOKEN" \
     "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews" | \
     jq -r '.[] | select(.state == "REQUEST_CHANGES" or .state == "COMMENT") |
       "Review \(.id) by \(.user.login) (\(.state)):\n\(.body)\n"'
   ```

3. **Get detailed comments for a review**:
   ```bash
   REVIEW_ID="2"
   curl -s -H "Authorization: token $TOKEN" \
     "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments" | \
     jq -r '.[] | "File: \(.path):\(.line)\nComment: \(.body)\nID: \(.id)\n---"'
   ```

4. **Respond using top-level comment** (most reliable):
   ```bash
   tea comment $PR_NUMBER "Addressing review feedback:

   - File \`path/to/file.py\` line 10: Fixed the issue by...
   - File \`other/file.py\` line 25: Updated as suggested..."
   ```

## API Reference

### Endpoints

| Action | Method | Endpoint |
|--------|--------|----------|
| List reviews | GET | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews` |
| Get review | GET | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}` |
| Get review comments | GET | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments` |
| Create review | POST | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews` |
| Submit review | POST | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}` |
| Delete review | DELETE | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}` |
| Create issue comment | POST | `/api/v1/repos/{owner}/{repo}/issues/{index}/comments` |

### Review States

- `PENDING` - Draft review not yet submitted
- `COMMENT` - General comment without approval/rejection
- `APPROVE` - Approving the changes
- `REQUEST_CHANGES` - Requesting changes before merge

## Limitations

1. **Thread replies**: The Gitea REST API does not support replying directly to review comment threads. This is a known limitation. Workarounds:
   - Use top-level comments with context
   - Use the web UI manually for thread replies
   - Implement session-based authentication to use the web endpoint

2. **CSRF tokens**: The web endpoint for thread replies requires CSRF tokens, which expire and need to be fetched from the page.

3. **Session auth**: API tokens work for REST API but not for web endpoints that require session cookies.

## Tips

- Always quote file paths and line numbers when responding via top-level comments
- Use `tea pr view $PR_NUMBER --comments` to see all comments
- Use `tea open pulls/$PR_NUMBER` to open the PR in browser for manual thread replies
- Consider using `tea pr approve $PR_NUMBER` after addressing all comments

## See Also

- Gitea API Documentation: https://docs.gitea.com/api/1.20/
- `tea` CLI: https://gitea.com/gitea/tea
