chore: workflow cleanup

This commit is contained in:
zhom
2026-05-23 14:22:45 +04:00
parent d664e5cde6
commit 375530e358
2 changed files with 20 additions and 52 deletions
@@ -1,4 +1,4 @@
name: Duplicate Issue Check name: Issue Compliance Check
on: on:
issues: issues:
@@ -12,7 +12,7 @@ env:
MODEL: z-ai/glm-5.1 MODEL: z-ai/glm-5.1
jobs: jobs:
check-duplicates: check-compliance:
if: github.repository == 'zhom/donutbrowser' && github.event.action == 'opened' if: github.repository == 'zhom/donutbrowser' && github.event.action == 'opened'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -21,29 +21,16 @@ jobs:
- name: Gather context - name: Gather context
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }} ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_BODY: ${{ github.event.issue.body }} ISSUE_BODY: ${{ github.event.issue.body }}
run: | run: |
printf '%s' "$ISSUE_TITLE" > /tmp/issue-title.txt printf '%s' "$ISSUE_TITLE" > /tmp/issue-title.txt
printf '%s' "${ISSUE_BODY:-}" > /tmp/issue-body.txt printf '%s' "${ISSUE_BODY:-}" > /tmp/issue-body.txt
# Pull up to 150 open/closed issues for the LLM to compare against.
# Exclude the issue under inspection and any PRs (gh issue list does
# this naturally).
gh issue list \
--repo "$GITHUB_REPOSITORY" \
--state all \
--limit 150 \
--json number,title,state,body \
--jq "[.[] | select(.number != $ISSUE_NUMBER) | {number, title, state, body: (.body[:400] // \"\")}]" \
> /tmp/existing-issues.json
- name: Build prompt - name: Build prompt
run: | run: |
cat > /tmp/system.txt <<'PROMPT' cat > /tmp/system.txt <<'PROMPT'
You are reviewing a new GitHub issue for two things — template compliance and possible duplicates. Return ONLY a single JSON object, no prose, no markdown fences. You are reviewing a new GitHub issue for template compliance. Return ONLY a single JSON object, no prose, no markdown fences.
Project: Donut Browser. There are three valid templates: Project: Donut Browser. There are three valid templates:
- Bug Report (Description + Operating System + Donut Browser version + Which browser is affected + Steps to reproduce + Error logs/screenshots fields) - Bug Report (Description + Operating System + Donut Browser version + Which browser is affected + Steps to reproduce + Error logs/screenshots fields)
@@ -59,22 +46,14 @@ jobs:
Do NOT flag for missing optional fields, missing screenshots, short titles, or stylistic issues. Be conservative. Do NOT flag for missing optional fields, missing screenshots, short titles, or stylistic issues. Be conservative.
## Duplicates — flag candidates ONLY when at least one of these is true
- Same error message, exception, or symptom
- Same feature being requested
- Same root cause area (e.g. "proxy disconnects on Camoufox/Windows")
Prefer false negatives over false positives. Two issues about Wayfern are not duplicates if they are about different features.
## Output schema ## Output schema
{ {
"is_compliant": true | false, "is_compliant": true | false,
"non_compliance_reasons": ["short bullet", ...], "non_compliance_reasons": ["short bullet", ...]
"duplicates": [{"number": 123, "reason": "short reason"}]
} }
Empty arrays are fine. If there is nothing to flag, return: If there is nothing to flag, return:
{"is_compliant": true, "non_compliance_reasons": [], "duplicates": []} {"is_compliant": true, "non_compliance_reasons": []}
PROMPT PROMPT
- name: Call OpenRouter - name: Call OpenRouter
@@ -86,13 +65,12 @@ jobs:
--rawfile system_prompt /tmp/system.txt \ --rawfile system_prompt /tmp/system.txt \
--rawfile title /tmp/issue-title.txt \ --rawfile title /tmp/issue-title.txt \
--rawfile body /tmp/issue-body.txt \ --rawfile body /tmp/issue-body.txt \
--rawfile existing /tmp/existing-issues.json \
'{ '{
model: $model, model: $model,
messages: [ messages: [
{ role: "system", content: $system_prompt }, { role: "system", content: $system_prompt },
{ role: "user", { role: "user",
content: ("New issue title: " + $title + "\n\nNew issue body:\n" + $body + "\n\nExisting issues (JSON array):\n" + $existing) } content: ("New issue title: " + $title + "\n\nNew issue body:\n" + $body) }
], ],
response_format: { type: "json_object" } response_format: { type: "json_object" }
}') }')
@@ -108,9 +86,9 @@ jobs:
# to a noop result so the workflow doesn't fail the issue author's run. # to a noop result so the workflow doesn't fail the issue author's run.
sed -E 's/^```(json)?$//; s/```$//' /tmp/raw.txt > /tmp/result.json sed -E 's/^```(json)?$//; s/```$//' /tmp/raw.txt > /tmp/result.json
if ! jq -e . /tmp/result.json >/dev/null 2>&1; then if ! jq -e . /tmp/result.json >/dev/null 2>&1; then
echo "::warning::Model returned non-JSON; treating as no-op" echo "::warning::Model returned non-JSON; treating as compliant"
cat /tmp/raw.txt cat /tmp/raw.txt
echo '{"is_compliant": true, "non_compliance_reasons": [], "duplicates": []}' > /tmp/result.json echo '{"is_compliant": true, "non_compliance_reasons": []}' > /tmp/result.json
fi fi
echo "Result:" echo "Result:"
cat /tmp/result.json cat /tmp/result.json
@@ -122,7 +100,6 @@ jobs:
r = json.load(open('/tmp/result.json')) r = json.load(open('/tmp/result.json'))
compliant = bool(r.get('is_compliant', True)) compliant = bool(r.get('is_compliant', True))
reasons = r.get('non_compliance_reasons') or [] reasons = r.get('non_compliance_reasons') or []
dups = r.get('duplicates') or []
parts = [] parts = []
if not compliant: if not compliant:
@@ -134,25 +111,11 @@ jobs:
parts.append(f'- {reason}') parts.append(f'- {reason}')
parts.append('') parts.append('')
parts.append('Please edit this issue to address the above within **24 hours**, or it will be automatically closed.') parts.append('Please edit this issue to address the above within **24 hours**, or it will be automatically closed.')
if dups:
if parts:
parts.append('')
parts.append('---')
parts.append('This issue might duplicate existing reports. Please check:')
for d in dups:
num = d.get('number')
reason = d.get('reason', '').strip()
if num:
parts.append(f'- #{num}{" — " + reason if reason else ""}')
if not compliant:
parts.append('') parts.append('')
parts.append('If you believe this was flagged incorrectly, please let a maintainer know.') parts.append('If you believe this was flagged incorrectly, please let a maintainer know.')
comment = '\n'.join(parts).strip() comment = '\n'.join(parts).strip()
open('/tmp/comment.md', 'w').write(comment) open('/tmp/comment.md', 'w').write(comment)
# Expose flags for downstream steps via GITHUB_OUTPUT-style write.
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
fh.write(f'has_comment={"true" if comment else "false"}\n') fh.write(f'has_comment={"true" if comment else "false"}\n')
fh.write(f'non_compliant={"true" if not compliant else "false"}\n') fh.write(f'non_compliant={"true" if not compliant else "false"}\n')
+11 -6
View File
@@ -102,12 +102,14 @@ jobs:
its API, MCP server, and the bundled `donut-sync` self-hosted server. its API, MCP server, and the bundled `donut-sync` self-hosted server.
- **Wayfern** — a Chromium fork maintained by zhom (the same maintainer). Wayfern - **Wayfern** — a Chromium fork maintained by zhom (the same maintainer). Wayfern
bugs are in-scope here unless they are obviously upstream Chromium issues. bugs are in-scope here unless they are obviously upstream Chromium issues.
- **Camoufox** — a Firefox fork by daijro. The maintainer of THIS repo does NOT - **Camoufox** — a Firefox fork by daijro, used by Donut but maintained in a
contribute to Camoufox and CANNOT fix bugs in it. separate repository. Bugs about Camoufox's *internal* behavior are outside
the scope of this project.
- Bugs about Camoufox's *internal* behavior (page rendering, JS engine, - Bugs about Camoufox's *internal* behavior (page rendering, JS engine,
dropdowns, form widgets, fingerprinting *as Camoufox implements it*, dropdowns, form widgets, fingerprinting *as Camoufox implements it*,
checkbox/radio quirks) are UPSTREAM ONLY. Redirect to checkbox/radio quirks) are out of scope here. Ask the user to first
https://github.com/daijro/camoufox/issues. search https://github.com/daijro/camoufox/issues for a matching report,
and if they don't find one, to open it there themselves.
- Bugs about how Donut *launches, configures, or downloads* Camoufox are - Bugs about how Donut *launches, configures, or downloads* Camoufox are
in-scope here. in-scope here.
- **Forks of Wayfern or Camoufox** (e.g. CloverLabsAI, VulpineOS) are NOT - **Forks of Wayfern or Camoufox** (e.g. CloverLabsAI, VulpineOS) are NOT
@@ -146,7 +148,10 @@ jobs:
dismiss as "known issue" / "expected" / "false positive in Tauri apps". Ask dismiss as "known issue" / "expected" / "false positive in Tauri apps". Ask
which exact version was the last working one and what changed. which exact version was the last working one and what changed.
- **Out-of-scope (upstream Camoufox)**: report is about Camoufox's own - **Out-of-scope (upstream Camoufox)**: report is about Camoufox's own
behavior. Redirect, do not collect logs. behavior. Tell the user it's outside the scope of this project and ask
them to search the Camoufox repo and, if no matching issue exists, file
one there. Do NOT say the maintainer doesn't contribute / can't fix it
— keep it strictly about project scope. Do not collect logs.
- **Fork-support request**: asks the maintainer to support an alternative - **Fork-support request**: asks the maintainer to support an alternative
Wayfern/Camoufox fork. Acknowledge in one neutral sentence — do NOT call it Wayfern/Camoufox fork. Acknowledge in one neutral sentence — do NOT call it
"clear", "reasonable", "well-thought-out", etc. "clear", "reasonable", "well-thought-out", etc.
@@ -342,7 +347,7 @@ jobs:
The triage classification (`triage.classification`) determines the response shape: The triage classification (`triage.classification`) determines the response shape:
- `bug-in-scope`: ask for what is missing using the user's reported OS log path. Be concrete about how to obtain logs. - `bug-in-scope`: ask for what is missing using the user's reported OS log path. Be concrete about how to obtain logs.
- `bug-upstream-camoufox`: redirect ONLY. One sentence acknowledging, then a sentence saying this is a Camoufox-internal issue and the maintainer of this repo does not contribute to Camoufox; ask the user to file at https://github.com/daijro/camoufox/issues. Do NOT ask for Donut logs. Stop after that. - `bug-upstream-camoufox`: redirect ONLY. One sentence acknowledging, then say this is outside the scope of this project — ask the user to first search https://github.com/daijro/camoufox/issues for a matching report and, if none exists, to open one there themselves. Do NOT phrase it as "the maintainer does not contribute" or anything personal — keep it strictly about scope. Do NOT ask for Donut logs. Stop after that.
- `bug-template-violation` or `ai-generated-junk`: politely ask the user to refile using the bug-report template (the Operating System, Donut Browser version, Which browser, Steps to reproduce, Error logs sections). If they cited "documentation" from any non-`donutbrowser.com`/non-`github.com/zhom` URL (e.g. context7, deepwiki), gently note that those are AI-generated third-party summaries and the only authoritative sources are this repo and donutbrowser.com. - `bug-template-violation` or `ai-generated-junk`: politely ask the user to refile using the bug-report template (the Operating System, Donut Browser version, Which browser, Steps to reproduce, Error logs sections). If they cited "documentation" from any non-`donutbrowser.com`/non-`github.com/zhom` URL (e.g. context7, deepwiki), gently note that those are AI-generated third-party summaries and the only authoritative sources are this repo and donutbrowser.com.
- `feature-request`: one neutral sentence acknowledging, then ask only what is genuinely needed (concrete use case, whether a workaround would suffice). Do NOT validate. - `feature-request`: one neutral sentence acknowledging, then ask only what is genuinely needed (concrete use case, whether a workaround would suffice). Do NOT validate.
- `fork-request`: one neutral sentence acknowledging the request. Note that this would substantially increase support burden and the maintainer evaluates such requests on a case-by-case basis. Ask whether the alternative fork supports all platforms the user uses (macOS / Windows / Linux). No "clear enhancement" language. - `fork-request`: one neutral sentence acknowledging the request. Note that this would substantially increase support burden and the maintainer evaluates such requests on a case-by-case basis. Ask whether the alternative fork supports all platforms the user uses (macOS / Windows / Linux). No "clear enhancement" language.