--- 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="" OWNER="" REPO="" 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="" 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