feat: integrate structured GitHub issue forms and prefilled feedback URLs
This commit is contained in:
1 parent
1ff8a44f92
commit
ae6ae99eeb
11 files changed
+250
-20
No files matched your search
@@ -0,0 +1,79 @@
|
||||
name: 问题反馈
|
||||
description: 功能表现和预期不一致,或出现报错。
|
||||
title: "[Bug] "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
请填写下面的必填项。GitHub Issue 公开可见,不要附上密码、Token、实例地址或笔记正文。
|
||||
|
||||
系统信息在「设置 → 系统信息」,点「复制信息」后粘贴。Linux 请另外写上发行版、桌面环境,以及 Wayland 或 X11。桌面端如果停在崩溃恢复页,请写上恢复页出现前正在做什么。
|
||||
- type: dropdown
|
||||
id: client
|
||||
attributes:
|
||||
label: 出现问题的客户端
|
||||
description: Which client is affected?
|
||||
multiple: true
|
||||
options:
|
||||
- Web
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux
|
||||
- Android
|
||||
- iOS
|
||||
- Browser extension
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: 发生了什么
|
||||
description: 实际看到的结果、报错原文。What did you see, including the exact error text?
|
||||
placeholder: 例如:点击分享后按钮一直转圈,控制台出现 TypeError。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: 怎样复现
|
||||
description: 按顺序写出操作。Steps to reproduce, in order.
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: 期望的结果
|
||||
description: 你认为这一步应该发生什么。What did you expect?
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: 系统信息
|
||||
description: 粘贴「设置 → 系统信息」里复制的内容。应用内反馈会自动填入。Paste the copied system information.
|
||||
placeholder: |
|
||||
- 客户端版本: v1.93.0
|
||||
- 系统: macOS
|
||||
- 实例构建: v1.93.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: diagnostics
|
||||
attributes:
|
||||
label: 诊断信息
|
||||
description: 应用在崩溃或同步失败时会自动填入。手动提交时留空。Filled automatically for crash and sync reports.
|
||||
validations:
|
||||
required: false
|
||||
- type: upload
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: 截图或录屏
|
||||
description: 有界面异常时附上。Add a screenshot or screen recording when the issue is visible.
|
||||
validations:
|
||||
required: false
|
||||
accept: ".png,.jpg,.jpeg,.gif,.webp,.mp4,.mov,.webm"
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -0,0 +1,67 @@
|
||||
name: 部署与连接
|
||||
description: 自托管实例无法安装、更新或连接。
|
||||
title: "[Deploy] "
|
||||
labels: ["question"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
先看仓库文档里的 Cloudflare 或 Docker 部署说明。仍然失败时再提交。
|
||||
|
||||
GitHub Issue 公开可见。不要附上密码、Token、实例地址或笔记正文。需要对照地址时,维护者会在评论里单独询问。
|
||||
- type: dropdown
|
||||
id: deploy-method
|
||||
attributes:
|
||||
label: 部署方式
|
||||
description: How is this instance deployed?
|
||||
multiple: false
|
||||
options:
|
||||
- Cloudflare 一键部署
|
||||
- Cloudflare 手动部署
|
||||
- Docker
|
||||
- 官方 Demo
|
||||
- 不确定
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: client
|
||||
attributes:
|
||||
label: 出问题的客户端
|
||||
description: Which client cannot connect? 纯服务端问题时选你用来访问的那个端。
|
||||
multiple: true
|
||||
options:
|
||||
- Web
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux
|
||||
- Android
|
||||
- iOS
|
||||
- Browser extension
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: 发生了什么
|
||||
description: 实际看到的结果、报错原文。What did you see, including the exact error text?
|
||||
placeholder: 例如:桌面端登录一直显示 network_unreachable,浏览器打开同一地址可以登录。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: 已经试过什么
|
||||
description: 包括文档中的哪一步、命令输出,以及是否用浏览器对照过。What have you already tried?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: 系统信息
|
||||
description: 能打开应用时,粘贴「设置 → 系统信息」里复制的内容。应用还打不开时,写上实例版本、数据库后端和部署平台。
|
||||
placeholder: |
|
||||
- 实例构建: v1.93.0
|
||||
- 数据库后端: D1
|
||||
- 部署平台: Cloudflare
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,52 @@
|
||||
name: 功能建议
|
||||
description: 希望增加或调整一个能力。
|
||||
title: "[Feature] "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
请写清现在办不到什么,以及你希望怎么做。GitHub Issue 公开可见,不要附上密码、Token、实例地址或笔记正文。
|
||||
|
||||
系统信息用来确认当前版本是否已经支持。在「设置 → 系统信息」点「复制信息」后粘贴。
|
||||
- type: dropdown
|
||||
id: client
|
||||
attributes:
|
||||
label: 用在哪个端
|
||||
description: Which client should have this?
|
||||
multiple: true
|
||||
options:
|
||||
- Web
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux
|
||||
- Android
|
||||
- iOS
|
||||
- Browser extension
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: 想要的能力
|
||||
description: 做成之后,你可以完成哪件现在做不到的事。What should become possible?
|
||||
placeholder: 例如:在手机上把一篇笔记从 Markdown 切回富文本继续改。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: 现在怎么做
|
||||
description: 你目前的做法,以及具体卡在哪一步。How do you handle this today, and where does it break down?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: 系统信息
|
||||
description: 粘贴「设置 → 系统信息」里复制的内容。应用内反馈会自动填入。Paste the copied system information.
|
||||
placeholder: |
|
||||
- 客户端版本: v1.93.0
|
||||
- 系统: Android
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,4 +1,9 @@
|
||||
const GITHUB_NEW_ISSUE_URL = "https://github.com/tianma-if/edgeever/issues/new";
|
||||
const DESKTOP_CLIENT_BY_PLATFORM = {
|
||||
darwin: "macOS",
|
||||
win32: "Windows",
|
||||
linux: "Linux",
|
||||
};
|
||||
// Keep the prefilled GitHub URL below common browser/server URL limits while
|
||||
// retaining the first useful frames from renderer stacks.
|
||||
const MAX_DIAGNOSTIC_TEXT_LENGTH = 1_200;
|
||||
@@ -45,21 +50,20 @@ export const buildDesktopDiagnosticIssueUrl = ({ diagnostic, systemInfo }) => {
|
||||
gpuFeatures: sanitizeDesktopDiagnosticText(systemInfo.gpuFeatures),
|
||||
};
|
||||
const title = `[Crash] Desktop renderer failure (${safeSystemInfo.platform} ${safeSystemInfo.architecture})`;
|
||||
const systemInfoText = Object.entries(safeSystemInfo)
|
||||
.filter(([, value]) => value)
|
||||
.map(([key, value]) => `- ${key}: ${value}`)
|
||||
.join("\n");
|
||||
const client = DESKTOP_CLIENT_BY_PLATFORM[safeSystemInfo.platform] ?? "";
|
||||
const makeUrl = (reportDiagnostic) => {
|
||||
const body = [
|
||||
"## What happened",
|
||||
"",
|
||||
"<!-- Please describe what you were doing immediately before EdgeEver showed the recovery screen. -->",
|
||||
"",
|
||||
"## Automatically captured diagnostics",
|
||||
"",
|
||||
"```json",
|
||||
JSON.stringify({ diagnostic: reportDiagnostic, systemInfo: safeSystemInfo }, null, 2),
|
||||
"```",
|
||||
"",
|
||||
"> This report was generated locally and common URLs, credentials, and home-directory names were redacted. GitHub Issues are public; please review the report before submitting it and do not add private note content, passwords, tokens, or instance URLs.",
|
||||
].join("\n");
|
||||
return `${GITHUB_NEW_ISSUE_URL}?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
|
||||
const params = new URLSearchParams({
|
||||
template: "bug.yml",
|
||||
title,
|
||||
"system-info": systemInfoText,
|
||||
diagnostics: JSON.stringify({ diagnostic: reportDiagnostic, systemInfo: safeSystemInfo }, null, 2),
|
||||
});
|
||||
if (client) params.set("client", client);
|
||||
return `${GITHUB_NEW_ISSUE_URL}?${params.toString()}`;
|
||||
};
|
||||
|
||||
const fullUrl = makeUrl(normalized);
|
||||
|
||||
@@ -52,10 +52,14 @@ describe("desktop crash diagnostics", () => {
|
||||
});
|
||||
const url = new URL(issueUrl);
|
||||
expect(url.origin + url.pathname).toBe("https://github.com/tianma-if/edgeever/issues/new");
|
||||
expect(url.searchParams.get("template")).toBe("bug.yml");
|
||||
expect(url.searchParams.get("client")).toBe("macOS");
|
||||
expect(url.searchParams.get("title")).toContain("darwin x64");
|
||||
expect(url.searchParams.get("body")).toContain('"appVersion": "1.31.0"');
|
||||
expect(url.searchParams.get("body")).toContain("Intel UHD Graphics 630");
|
||||
expect(url.searchParams.get("body")).not.toContain("private.example.com");
|
||||
expect(url.searchParams.get("system-info")).toContain("- appVersion: 1.31.0");
|
||||
expect(url.searchParams.get("diagnostics")).toContain('"appVersion": "1.31.0"');
|
||||
expect(url.searchParams.get("diagnostics")).toContain("Intel UHD Graphics 630");
|
||||
expect(url.searchParams.get("diagnostics")).not.toContain("private.example.com");
|
||||
expect(url.searchParams.get("system-info")).not.toContain("private.example.com");
|
||||
expect(issueUrl.length).toBeLessThan(8_000);
|
||||
});
|
||||
|
||||
|
||||
@@ -784,6 +784,7 @@ struct SettingsView: View {
|
||||
let notice = english
|
||||
? "The following information was generated by EdgeEver to help diagnose the issue."
|
||||
: "以下信息由 EdgeEver 自动生成,可帮助定位问题。"
|
||||
let info = systemInfoText(includeLocalOnly: false)
|
||||
let body = """
|
||||
## \(heading)
|
||||
|
||||
@@ -796,13 +797,15 @@ struct SettingsView: View {
|
||||
\(notice)
|
||||
|
||||
```text
|
||||
\(systemInfoText(includeLocalOnly: false))
|
||||
\(info)
|
||||
```
|
||||
"""
|
||||
var components = URLComponents(string: "https://github.com/tianma-if/edgeever/issues/new")
|
||||
components?.queryItems = [
|
||||
URLQueryItem(name: "title", value: english ? "[Feedback] " : "[反馈] "),
|
||||
URLQueryItem(name: "body", value: body),
|
||||
URLQueryItem(name: "system-info", value: info),
|
||||
URLQueryItem(name: "client", value: "iOS"),
|
||||
]
|
||||
return components?.url
|
||||
}
|
||||
|
||||
@@ -819,5 +819,6 @@ const buildMobileFeedbackUrl = (
|
||||
? "The following information was generated by EdgeEver to help diagnose the issue."
|
||||
: "以下信息由 EdgeEver 自动生成,可帮助定位问题。",
|
||||
titlePrefix: english ? "[Feedback] " : "[反馈] ",
|
||||
client: "Android",
|
||||
});
|
||||
};
|
||||
@@ -24,6 +24,9 @@ describe("GitHub feedback URL", () => {
|
||||
expect(body).toContain("## Diagnostics");
|
||||
expect(body).toContain('"errorCode":"memo_not_found"');
|
||||
expect(body).toContain("- Version: v1.46.0");
|
||||
expect(url.searchParams.get("system-info")).toContain("- Version: v1.46.0");
|
||||
expect(url.searchParams.get("template")).toBe("bug.yml");
|
||||
expect(url.searchParams.get("diagnostics")).toContain('"errorCode":"memo_not_found"');
|
||||
expect(body.indexOf("## Diagnostics")).toBeLessThan(body.indexOf("## System information"));
|
||||
});
|
||||
});
|
||||
@@ -14,6 +14,7 @@ export const buildGitHubFeedbackUrl = ({
|
||||
systemInfoHeading,
|
||||
systemInfoNotice,
|
||||
titlePrefix,
|
||||
client,
|
||||
}: {
|
||||
contentHeading: string;
|
||||
contentPrompt: string;
|
||||
@@ -27,7 +28,9 @@ export const buildGitHubFeedbackUrl = ({
|
||||
systemInfoHeading: string;
|
||||
systemInfoNotice: string;
|
||||
titlePrefix: string;
|
||||
client?: string;
|
||||
}) => {
|
||||
const systemInfoText = systemInfo.map((item) => `- ${item.label}: ${item.value}`).join("\n");
|
||||
const body = [
|
||||
`## ${contentHeading}`,
|
||||
"",
|
||||
@@ -46,9 +49,19 @@ export const buildGitHubFeedbackUrl = ({
|
||||
`## ${systemInfoHeading}`,
|
||||
"",
|
||||
`<!-- ${systemInfoNotice} -->`,
|
||||
...systemInfo.map((item) => `- ${item.label}: ${item.value}`),
|
||||
systemInfoText,
|
||||
"",
|
||||
`> ${privacyNotice}`,
|
||||
].join("\n");
|
||||
return `${GITHUB_NEW_ISSUE_URL}?title=${encodeURIComponent(titlePrefix)}&body=${encodeURIComponent(body)}`;
|
||||
const params = new URLSearchParams({
|
||||
title: titlePrefix,
|
||||
body,
|
||||
"system-info": systemInfoText,
|
||||
});
|
||||
if (diagnostics) {
|
||||
params.set("template", "bug.yml");
|
||||
params.set("diagnostics", diagnostics.text);
|
||||
}
|
||||
if (client) params.set("client", client);
|
||||
return `${GITHUB_NEW_ISSUE_URL}?${params.toString()}`;
|
||||
};
|
||||
@@ -24,5 +24,8 @@ describe("buildGitHubFeedbackUrl", () => {
|
||||
expect(url.searchParams.get("body")).toContain("- 版本号: v0.5.0");
|
||||
expect(url.searchParams.get("body")).toContain("- 系统: Android 16");
|
||||
expect(url.searchParams.get("body")).toContain("> 请勿提交隐私信息");
|
||||
expect(url.searchParams.get("system-info")).toContain("- 版本号: v0.5.0");
|
||||
expect(url.searchParams.get("system-info")).toContain("- 系统: Android 16");
|
||||
expect(url.searchParams.get("template")).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user