@@ -0,0 +1,66 @@
|
||||
name: Renovate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0/30 * * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
RENOVATE_VERSION: "41.146.8"
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Renovate Run
|
||||
env:
|
||||
DOCKER_HOST: tcp://dockerproxy:2375
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_ENDPOINT: https://git.trez.wtf/api/v1
|
||||
RENOVATE_TOKEN: ${{ secrets.RENOVATE_BOT_TOKEN }}
|
||||
LOG_LEVEL: ${{ vars.RENOVATE_LOG_LEVEL }}
|
||||
RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_TOKEN }}
|
||||
RENOVATE_CONFIG_FILE: renovate.json
|
||||
RENOVATE_REPOSITORIES: trez/ultima-ai
|
||||
RENOVATE_HOST_RULES: |
|
||||
[
|
||||
{
|
||||
"description": "Docker Hub authentication",
|
||||
"hostType": "docker",
|
||||
"matchHost": "docker.io",
|
||||
"username": "${{ secrets.DOCKERHUB_USER }}",
|
||||
"password": "${{ secrets.DOCKERHUB_PASSWORD }}"
|
||||
},
|
||||
{
|
||||
"description": "GitHub Container Registry (GHCR)",
|
||||
"hostType": "docker",
|
||||
"matchHost": "ghcr.io",
|
||||
"username": "${{ secrets.GHCR_USER }}",
|
||||
"password": "${{ secrets.GHCR_LOGIN_TOKEN }}"
|
||||
},
|
||||
{
|
||||
"description": "Self-hosted Gitea Docker Registry",
|
||||
"hostType": "docker",
|
||||
"matchHost": "git.trez.wtf",
|
||||
"username": "${{ secrets.BOT_GITEA_USER }}",
|
||||
"password": "${{ secrets.BOT_GITEA_PASSWORD }}"
|
||||
}
|
||||
]
|
||||
run: |
|
||||
docker run --rm \
|
||||
-e RENOVATE_PLATFORM \
|
||||
-e RENOVATE_ENDPOINT \
|
||||
-e RENOVATE_TOKEN \
|
||||
-e LOG_LEVEL \
|
||||
-e RENOVATE_GITHUB_COM_TOKEN \
|
||||
-e RENOVATE_CONFIG_FILE \
|
||||
-e RENOVATE_REPOSITORIES \
|
||||
-e RENOVATE_HOST_RULES \
|
||||
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
|
||||
-w ${GITHUB_WORKSPACE} \
|
||||
renovate/renovate:${{ env.RENOVATE_VERSION }}-full
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Charish Patel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,72 @@
|
||||
# PR Commenter Diff-Aware Action
|
||||
|
||||
A GitHub Action to automatically post comments to pull requests on **GitHub** or **Gitea**, based on a `git diff`. Supports:
|
||||
|
||||
- Inline comments per changed line
|
||||
- Multiline comment templates
|
||||
- Cross-platform support (GitHub and Gitea)
|
||||
- Diff-aware commenting, automatically detecting added lines
|
||||
- Default comment template with optional overrides
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **GitHub & Gitea support**: Works seamlessly on both platforms.
|
||||
- **Diff-aware**: Parses a `git diff` to determine which lines were added.
|
||||
- **Inline comments**: Comments appear directly on changed lines in PRs.
|
||||
- **Multiline templates**: Supports `{line}` for single line and `{lines}` for all added lines in a file.
|
||||
- **Reusable**: Works as a composite action and can be called from any workflow.
|
||||
|
||||
---
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
|-------|-------------|----------|---------|
|
||||
| `platform` | Target platform: `github` or `gitea` | yes | `github` |
|
||||
| `token` | API token for authentication | yes | - |
|
||||
| `api_url` | Gitea API URL (only required for Gitea, e.g., `https://gitea.example.com/api/v1`) | no | - |
|
||||
| `repo_owner` | Repository owner (user/org) | yes | - |
|
||||
| `repo_name` | Repository name | yes | - |
|
||||
| `pr_index` | PR number (GitHub) or index (Gitea) | yes | - |
|
||||
| `diff` | Git diff to parse (generated via `git diff`) | yes | - |
|
||||
| `comment_template` | Multiline template for comment body. Use `{line}` for a single line and `{lines}` for all added lines in the file | yes | `Auto-comment: changed line -> {line}` |
|
||||
|
||||
---
|
||||
|
||||
## Example Usage
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
comment-pr-diff:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Generate git diff
|
||||
id: gitdiff
|
||||
run: |
|
||||
git fetch origin main
|
||||
git diff origin/main > diff.txt
|
||||
|
||||
- name: Post diff-aware comments to GitHub PR
|
||||
uses: ./ # path to this action
|
||||
with:
|
||||
platform: github
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo_owner: ${{ github.repository_owner }}
|
||||
repo_name: ${{ github.event.repository.name }}
|
||||
pr_index: ${{ github.event.pull_request.number }}
|
||||
diff: ${{ steps.gitdiff.outputs.diff }}
|
||||
comment_template: |
|
||||
Auto-comment on file:
|
||||
---
|
||||
Changed line: {line}
|
||||
Full added lines in this file:
|
||||
{lines}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
name: "PR Commenter Diff-Aware"
|
||||
description: "Post comments to changed lines in a PR based on a git diff, for GitHub or Gitea. Supports multiline templates."
|
||||
author: "Trez.One"
|
||||
|
||||
branding:
|
||||
icon: "paperclip"
|
||||
color: "blue"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: pip install requests
|
||||
|
||||
- name: Run PR commenter
|
||||
run: python git-auto-comment.py
|
||||
shell: python
|
||||
env:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
TOKEN: ${{ inputs.token }}
|
||||
API_URL: ${{ inputs.api_url }}
|
||||
REPO_OWNER: ${{ inputs.repo_owner }}
|
||||
REPO_NAME: ${{ inputs.repo_name }}
|
||||
PR_INDEX: ${{ inputs.pr_index }}
|
||||
DIFF: ${{ inputs.diff }}
|
||||
COMMENT_TEMPLATE: ${{ inputs.comment_template }}
|
||||
|
||||
inputs:
|
||||
platform:
|
||||
description: "Target platform: github or gitea"
|
||||
required: true
|
||||
default: "github"
|
||||
token:
|
||||
description: "API token for authentication"
|
||||
required: true
|
||||
api_url:
|
||||
description: "Gitea API URL (only required for Gitea, e.g., https://gitea.example.com/api/v1)"
|
||||
required: false
|
||||
repo_owner:
|
||||
description: "Repository owner (user/org)"
|
||||
required: true
|
||||
repo_name:
|
||||
description: "Repository name"
|
||||
required: true
|
||||
pr_index:
|
||||
description: "PR number (GitHub) or index (Gitea)"
|
||||
required: true
|
||||
diff:
|
||||
description: "Git diff to parse, in standard format (generated via git diff)"
|
||||
required: true
|
||||
comment_template:
|
||||
description: |
|
||||
Multiline template for comment body.
|
||||
Use placeholders:
|
||||
- {line} → replaced by single changed line
|
||||
- {lines} → replaced by all added lines in the file
|
||||
required: true
|
||||
default: "Auto-comment: changed line -> {line}"
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
import requests
|
||||
|
||||
platform = os.environ.get("PLATFORM", "github").lower()
|
||||
token = os.environ["TOKEN"]
|
||||
owner = os.environ["REPO_OWNER"]
|
||||
repo = os.environ["REPO_NAME"]
|
||||
pr_index = os.environ["PR_INDEX"]
|
||||
api_url = os.environ.get("API_URL")
|
||||
diff_text = os.environ.get("DIFF")
|
||||
comment_template = os.environ.get("COMMENT_TEMPLATE", "")
|
||||
|
||||
if not diff_text:
|
||||
print("No diff provided", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Parse diff
|
||||
diff_files = {}
|
||||
current_file = None
|
||||
new_line_num = None
|
||||
|
||||
for line in diff_text.splitlines():
|
||||
if line.startswith("+++ b/"):
|
||||
current_file = line[6:].strip()
|
||||
diff_files[current_file] = []
|
||||
new_line_num = 0
|
||||
elif line.startswith("@@"):
|
||||
m = re.match(r"@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@", line)
|
||||
if m:
|
||||
new_line_num = int(m.group(1)) - 1
|
||||
elif line.startswith("+") and not line.startswith("+++"):
|
||||
new_line_num += 1
|
||||
content = line[1:]
|
||||
diff_files[current_file].append((new_line_num, content))
|
||||
elif not line.startswith("-"):
|
||||
new_line_num += 1
|
||||
|
||||
# Post comments
|
||||
for file_path, lines in diff_files.items():
|
||||
if not lines:
|
||||
continue
|
||||
all_lines_content = "\n".join([line_content for _, line_content in lines])
|
||||
for line_number, line_content in lines:
|
||||
body = comment_template.replace("{line}", line_content).replace("{lines}", all_lines_content)
|
||||
|
||||
if platform == "github":
|
||||
url = f"https://api.github.com/repos/{owner}/{repo}/issues/{pr_index}/comments"
|
||||
payload = {"body": body}
|
||||
if file_path and line_number:
|
||||
url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_index}/comments"
|
||||
payload.update({
|
||||
"body": body,
|
||||
"path": file_path,
|
||||
"position": line_number
|
||||
})
|
||||
elif platform == "gitea":
|
||||
if not api_url:
|
||||
print("Gitea API URL required", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
url = f"{api_url}/repos/{owner}/{repo}/pulls/{pr_index}/comments"
|
||||
payload = {"body": body}
|
||||
if file_path and line_number:
|
||||
payload.update({
|
||||
"path": file_path,
|
||||
"position": line_number
|
||||
})
|
||||
else:
|
||||
print(f"Unsupported platform: {platform}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"token {token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
resp = requests.post(url, headers=headers, json=payload)
|
||||
if resp.status_code in (201, 200):
|
||||
print(f"Comment posted on {file_path}:{line_number}")
|
||||
else:
|
||||
print(f"Failed to post comment on {file_path}:{line_number} ({resp.status_code})", file=sys.stderr)
|
||||
print(resp.text, file=sys.stderr)
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["local>trez/renovate-config"],
|
||||
"enabledManagers": ["python"]
|
||||
}
|
||||
Reference in New Issue
Block a user