Adds a new Claude Code skill that enables reading PR review comments and posting replies on Gitea/Forgejo instances. Documents both the REST API approach for reading reviews and the web endpoint approach for thread replies, with fallback to top-level comments when thread replies aren't possible due to authentication limitations. Implements bead: nixos-configs-vru
7.7 KiB
description
| 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
teaCLI 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:
# 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:
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:
# 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)
# 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 tocontent: The reply messagepath: File pathline: Line numberside:proposedororiginalsingle_review:trueorigin: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)
- Log in to Gitea in your browser
- Open browser developer tools and copy cookies
- Use the session cookies with curl
# 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:
# 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:
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:
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
-
Set up environment:
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" -
List all pending review comments:
# 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"' -
Get detailed comments for a review:
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---"' -
Respond using top-level comment (most reliable):
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 submittedCOMMENT- General comment without approval/rejectionAPPROVE- Approving the changesREQUEST_CHANGES- Requesting changes before merge
Limitations
-
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
-
CSRF tokens: The web endpoint for thread replies requires CSRF tokens, which expire and need to be fetched from the page.
-
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 --commentsto see all comments - Use
tea open pulls/$PR_NUMBERto open the PR in browser for manual thread replies - Consider using
tea pr approve $PR_NUMBERafter addressing all comments
See Also
- Gitea API Documentation: https://docs.gitea.com/api/1.20/
teaCLI: https://gitea.com/gitea/tea