Skip to content

Commit 4d149ca

Browse files
authored
Merge branch 'DIYgod:master' into master
2 parents c6f3e7b + 6ab5cf6 commit 4d149ca

14 files changed

Lines changed: 1164 additions & 395 deletions

File tree

.github/prompts/pr_review_rules.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# PR Review Rules for RSSHub
2+
3+
You are reviewing pull requests for RSSHub.
4+
5+
Only report **clear and actionable** violations in changed lines/files. Do not report speculative or uncertain issues.
6+
7+
## Route Metadata and Docs
8+
9+
1. `example` must start with `/` and be a working RSSHub route path.
10+
2. Route name must not repeat namespace name.
11+
3. In radar rules, `source` must be a relative host/path (no `https://`, no hash/query matching).
12+
4. In radar rules, `target` must match the route path and declared params.
13+
5. Namespace `url` should not include protocol prefix.
14+
6. Use a single category in `categories`.
15+
7. `parameters` keys must match real path parameters.
16+
8. Keep route/docs lists in alphabetical order when touching sorted files.
17+
9. Do not modify default values or working examples unless they are broken.
18+
19+
## Data Handling and Feed Quality
20+
21+
10. Use `cache.tryGet()` (from `@/utils/cache`) for detail fetching in loops; cache processed result instead of raw HTML.
22+
11. `description` should contain article content only; do not duplicate `title`, `author`, `pubDate`, or tags.
23+
12. Extract tags/categories into `category` field.
24+
13. Use `parseDate()` for date fields when source provides time.
25+
14. Do not set fake dates (`new Date()` fallback) when source has no valid time.
26+
15. Keep each item `link` unique; feed-level `link` should be human-readable (not raw API endpoint).
27+
16. Do not trim/truncate title/content manually.
28+
29+
## API and Requesting
30+
31+
17. Prefer official API endpoints over scraping when available.
32+
18. Fetch first page only; do not add custom pagination behavior.
33+
19. Use common parameter `limit` instead of custom limit/query filtering.
34+
20. Prefer path parameters over custom query parameters for route config.
35+
21. Use RSSHub built-in UA behavior; when browser-like headers are needed, use `config.trueUA` instead of hardcoded UA strings.
36+
37+
## Code Style and Maintainability
38+
39+
22. Use `camelCase` naming.
40+
23. Use `import type { ... }` for type-only imports.
41+
24. Keep imports sorted.
42+
25. Use JSX-based rendering (`renderToString` and template components) for custom HTML rendering patterns used by RSSHub.
43+
26. Avoid unnecessary changes outside PR scope.
44+
45+
## Reporting Format
46+
47+
- Report only violated rules.
48+
- Each bullet should include: file path, problem, and concrete fix.
49+
- Group repeated issues across files into one concise bullet when possible.
50+
- If no rule is clearly violated, do not comment.

.github/prompts/similar_issues.prompt.yml

Lines changed: 0 additions & 46 deletions
This file was deleted.

.github/workflows/docker-release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ jobs:
107107
108108
- name: Build and push Docker image (ordinary version)
109109
id: build-and-push
110-
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
110+
uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1
111111
with:
112112
context: .
113113
tags: ${{ steps.image-name-ordinary.outputs.tags }}
@@ -160,7 +160,7 @@ jobs:
160160
161161
- name: Build and push Docker image (Chromium-bundled version)
162162
id: build-and-push-chromium
163-
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
163+
uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1
164164
with:
165165
context: .
166166
build-args: PUPPETEER_SKIP_DOWNLOAD=0

.github/workflows/docker-test-cont.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ jobs:
121121
122122
- name: Pull Request Labeler
123123
if: ${{ failure() }}
124-
uses: actions-cool/issues-helper@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
124+
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
125125
with:
126126
actions: 'add-labels'
127127
token: ${{ secrets.GITHUB_TOKEN }}
@@ -161,7 +161,7 @@ jobs:
161161
>> "${GITHUB_OUTPUT}"
162162
163163
- name: Pull Request Labeler
164-
uses: actions-cool/issues-helper@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
164+
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
165165
with:
166166
actions: 'add-labels'
167167
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/docker-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
flavor: latest=true
4141

4242
- name: Build Docker image
43-
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
43+
uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1
4444
with:
4545
context: .
4646
build-args: PUPPETEER_SKIP_DOWNLOAD=0 # also test bundling Chromium
@@ -55,7 +55,7 @@ jobs:
5555

5656
- name: Pull Request Labeler
5757
if: ${{ failure() }}
58-
uses: actions-cool/issues-helper@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
58+
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
5959
with:
6060
actions: 'add-labels'
6161
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/pr-review.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: pr-review
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, reopened, synchronize, ready_for_review]
6+
workflow_dispatch:
7+
inputs:
8+
pr_number:
9+
description: Pull request number to review manually
10+
required: true
11+
type: number
12+
13+
jobs:
14+
review-pr:
15+
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 10
18+
permissions:
19+
contents: read
20+
issues: write
21+
pull-requests: write
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
26+
- name: Set up Bun
27+
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
28+
29+
- name: Install opencode
30+
run: curl -fsSL https://opencode.ai/install | bash
31+
32+
- name: Review PR with rules
33+
env:
34+
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
35+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
GITHUB_REPOSITORY: ${{ github.repository }}
37+
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr_number }}
38+
OPENCODE_PERMISSION: |
39+
{
40+
"bash": {
41+
"*": "deny",
42+
"gh auth*": "allow",
43+
"gh pr*": "allow",
44+
"gh api*": "allow"
45+
},
46+
"webfetch": "deny"
47+
}
48+
run: |
49+
if [ -z "$PR_NUMBER" ]; then
50+
echo "pr_number is required"
51+
exit 1
52+
fi
53+
54+
RULES=$(cat .github/prompts/pr_review_rules.md)
55+
56+
opencode run -m ${{ vars.OPENCODE_MODEL }} "A pull request has been created or updated in this repository.
57+
58+
Pull request number:
59+
$PR_NUMBER
60+
61+
Repository:
62+
$GITHUB_REPOSITORY
63+
64+
Your task:
65+
1. Use GitHub CLI commands to inspect this PR's metadata and code changes.
66+
2. Review only based on the following rules.
67+
3. Report only clear and actionable violations from changed files.
68+
4. If no clear violations are found, do not comment.
69+
70+
Review rules:
71+
$RULES
72+
73+
Required behavior:
74+
- Keep feedback concise and grouped by rule.
75+
- Include file path and a concrete fix suggestion for each issue.
76+
- Ignore uncertain or low-confidence findings.
77+
- Avoid duplicate comments.
78+
79+
Comment protocol:
80+
- Use marker: <!-- pr-auto-review -->
81+
- Check existing comments in issue comments for this marker.
82+
- If a marker comment exists, update it with latest findings.
83+
- Otherwise create a new PR comment.
84+
- If there are no findings and marker comment exists, edit marker comment to a short pass status.
85+
86+
Suggested comment format:
87+
<!-- pr-auto-review -->
88+
## Auto Review
89+
- [Rule] file: issue + suggestion
90+
91+
For no findings:
92+
<!-- pr-auto-review -->
93+
## Auto Review
94+
No clear rule violations found in the current diff.
95+
96+
Use only gh commands and repository data."
Lines changed: 54 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,71 @@
1-
name: Similar Issues via AI MCP
1+
name: duplicate-issues
22

33
on:
44
issues:
55
types: [opened]
6+
workflow_dispatch:
7+
inputs:
8+
issue_number:
9+
description: Issue number to check manually
10+
required: true
11+
type: number
612

713
jobs:
8-
find-similar:
14+
check-duplicates:
15+
runs-on: ubuntu-latest
916
permissions:
1017
contents: read
1118
issues: write
12-
models: read
13-
runs-on: ubuntu-slim
1419
steps:
15-
- name: Check out repository
20+
- name: Checkout repository
1621
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1722

18-
- name: Prepare prompt variables
19-
id: prepare_input
20-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
21-
with:
22-
script: |
23-
const issue = context.payload.issue || {};
24-
const title = issue.title || '';
25-
const body = issue.body || '';
26-
const indent = ' ';
27-
// Indent subsequent lines so YAML block scalar indentation remains valid
28-
const bodyIndented = body.replace(/\n/g, '\n' + indent);
29-
core.setOutput('issue_title_json', JSON.stringify(title));
30-
core.setOutput('issue_body_indented_json', JSON.stringify(bodyIndented));
31-
core.setOutput('issue_number', issue.number);
23+
- name: Set up Bun
24+
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
3225

33-
- name: Find similar issues with AI (MCP)
34-
id: inference
35-
uses: actions/ai-inference@a380166897b5408b8fb7dddd148142794cb5624a # v2.0.6
36-
with:
37-
prompt-file: ./.github/prompts/similar_issues.prompt.yml
38-
input: |
39-
issue_title: ${{ steps.prepare_input.outputs.issue_title_json }}
40-
issue_body: ${{ steps.prepare_input.outputs.issue_body_indented_json }}
41-
issue_number: ${{ steps.prepare_input.outputs.issue_number }}
42-
repository: ${{ github.repository }}
43-
enable-github-mcp: true
44-
# Inference token can use GITHUB_TOKEN. MCP specifically requires a PAT.
45-
token: ${{ secrets.GITHUB_TOKEN }}
46-
github-mcp-token: ${{ secrets.USER_PAT }}
47-
max-tokens: 8000
26+
- name: Install opencode
27+
run: curl -fsSL https://opencode.ai/install | bash
4828

49-
- name: Prepare comment body
50-
id: prepare
51-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
29+
- name: Check for duplicate issues
5230
env:
53-
AI_RESPONSE: ${{ steps.inference.outputs.response }}
54-
with:
55-
script: |
56-
let data;
57-
try {
58-
data = JSON.parse(process.env.AI_RESPONSE || '{}');
59-
} catch (e) {
60-
core.setOutput('has_matches', 'false');
61-
return;
31+
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
ISSUE_NUMBER: ${{ github.event.issue.number || inputs.issue_number }}
34+
OPENCODE_PERMISSION: |
35+
{
36+
"bash": {
37+
"*": "deny",
38+
"gh issue*": "allow"
39+
},
40+
"webfetch": "deny"
6241
}
63-
const matches = Array.isArray(data.matches) ? data.matches.filter(m => m.number !== context.payload.issue.number) : [];
64-
if (!matches.length) {
65-
core.setOutput('has_matches', 'false');
66-
return;
67-
}
68-
const lines = [];
69-
lines.push('I found similar issues that might help:');
70-
for (const m of matches.slice(0, 3)) {
71-
const num = m.number != null ? `#${m.number}` : '';
72-
const title = m.title || 'Untitled';
73-
const url = m.url || '';
74-
const score = typeof m.similarity_score === 'number' ? ` (similarity: ${m.similarity_score.toFixed(2)})` : '';
75-
lines.push(`- ${url}${score}`.trim());
76-
}
77-
core.setOutput('has_matches', 'true');
78-
core.setOutput('comment_body', lines.join('\n'));
42+
run: |
43+
if [ -z "$ISSUE_NUMBER" ]; then
44+
echo "issue_number is required"
45+
exit 1
46+
fi
47+
48+
opencode run -m ${{ vars.OPENCODE_MODEL }} "A new issue has been created:'
49+
50+
Issue number:
51+
$ISSUE_NUMBER
52+
53+
Lookup this issue and search through existing issues (excluding #$ISSUE_NUMBER) in this repository to find any potential duplicates of this new issue.
54+
Consider:
55+
1. Similar titles or descriptions
56+
2. Same error messages or symptoms
57+
3. Related functionality or components
58+
4. Similar feature requests
59+
60+
If you find any potential duplicates, please comment on the new issue with:
61+
- A brief explanation of why it might be a duplicate
62+
- Links to the potentially duplicate issues
63+
- A suggestion to check those issues first
64+
65+
Use this format for the comment:
66+
'This issue might be a duplicate of existing issues. Please check:
67+
- #[issue_number]: [brief description of similarity]
68+
69+
Feel free to ignore if none of these address your specific case.'
7970
80-
- name: Comment similar issues
81-
if: steps.prepare.outputs.has_matches == 'true'
82-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
83-
with:
84-
script: |
85-
const body = ${{ toJson(steps.prepare.outputs.comment_body) }};
86-
await github.rest.issues.createComment({
87-
owner: context.repo.owner,
88-
repo: context.repo.repo,
89-
issue_number: context.payload.issue.number,
90-
body
91-
});
71+
If no clear duplicates are found, do not comment."

0 commit comments

Comments
 (0)