mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-10-25 17:36:32 +08:00
init
This commit is contained in:
commit
6649f2e2fc
550 files changed
+264532
No files matched your search
@@ -0,0 +1,140 @@
|
||||
name: "报告 Bug"
|
||||
description: "代码出现了非预期的问题、崩溃或报错"
|
||||
title: "[Bug]: "
|
||||
labels: ["type: bug", "status: needs info"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
请提供尽可能详细的信息,帮助我们快速定位和修复问题。
|
||||
- type: input
|
||||
id: confirm-unique
|
||||
attributes:
|
||||
label: 确认唯一性
|
||||
description: 请输入:我已确认没有相同问题出现
|
||||
placeholder: 我已确认没有相同问题出现
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: standard-operation
|
||||
attributes:
|
||||
label: 这是标准操作流程下出现的问题吗?
|
||||
description: 确认你是按照正常方式使用,而不是非常规操作
|
||||
options:
|
||||
- 是,标准操作
|
||||
- 否,非标准操作
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: code-issue-confirm
|
||||
attributes:
|
||||
label: 你确认这真的是我们的代码导致的吗?
|
||||
description: 请仔细思考,排除网络、系统、第三方服务等外部因素
|
||||
options:
|
||||
- 是,确认是代码问题
|
||||
- 不确定
|
||||
- 否,可能是其他原因
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: pre-check
|
||||
attributes:
|
||||
label: 基础确认
|
||||
options:
|
||||
- label: 我使用的是最新版本
|
||||
required: true
|
||||
- label: 我已阅读过相关文档
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: 使用平台
|
||||
description: 选择出现问题的平台
|
||||
options:
|
||||
- Windows
|
||||
- macOS
|
||||
- Linux
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: 问题严重程度
|
||||
description: 这个问题对你的使用造成了多大影响?
|
||||
options:
|
||||
- 严重崩溃或数据丢失(无法使用)
|
||||
- 核心功能受影响(在下一个常规发布中必须修复)
|
||||
- 边缘场景或轻微问题(等待空闲时修复)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 问题描述
|
||||
description: 清晰描述你遇到的问题,包括实际发生了什么
|
||||
placeholder: 例如:当我点击发送按钮时,应用程序崩溃并显示白屏
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: 复现步骤
|
||||
description: 提供详细的操作步骤,让我们能够重现这个问题
|
||||
placeholder: |
|
||||
1. 打开应用并登录账号
|
||||
2. 进入聊天页面
|
||||
3. 点击发送按钮
|
||||
4. 观察到应用崩溃
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: 预期行为
|
||||
description: 描述你期望的正确行为应该是什么样的
|
||||
placeholder: 例如:点击发送按钮后,消息应该正常发送并显示在聊天窗口中
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: 实际行为
|
||||
description: 描述实际发生的错误行为
|
||||
placeholder: 例如:点击后应用直接崩溃,显示白屏
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: 错误日志或截图
|
||||
description: 粘贴控制台错误信息、崩溃日志,或拖入截图
|
||||
placeholder: 请粘贴完整的错误堆栈信息
|
||||
render: shell
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: 操作系统版本
|
||||
description: 例如:Windows 11 24H2、macOS 15.0、Ubuntu 24.04
|
||||
placeholder: Windows 11 24H2
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: app-version
|
||||
attributes:
|
||||
label: 应用版本
|
||||
description: 在关于页面或设置中查看版本号
|
||||
placeholder: v1.2.3
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: architecture
|
||||
attributes:
|
||||
label: 系统架构
|
||||
description: 例如:x64、arm64
|
||||
placeholder: x64
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: 补充信息
|
||||
description: 其他可能有助于定位问题的信息
|
||||
placeholder: 例如:这个问题是在某次更新后开始出现的,或者只在特定网络环境下出现
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -0,0 +1,75 @@
|
||||
name: "文档反馈"
|
||||
description: "文档存在错别字、描述不清晰或缺少必要的示例"
|
||||
title: "[Docs]: "
|
||||
labels: ["type: docs"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
优秀的文档和代码一样重要。感谢你帮助我们完善文档!
|
||||
- type: input
|
||||
id: confirm-unique
|
||||
attributes:
|
||||
label: 确认唯一性
|
||||
description: 请输入:我已确认没有相同问题出现
|
||||
placeholder: 我已确认没有相同问题出现
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: 文档类型
|
||||
description: 问题出现在哪类文档中?
|
||||
options:
|
||||
- README 或项目说明
|
||||
- 安装部署文档
|
||||
- 使用教程
|
||||
- API 文档
|
||||
- 开发者文档
|
||||
- 其他
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: doc-link
|
||||
attributes:
|
||||
label: 文档位置
|
||||
description: 提供文档的 URL 或文件路径
|
||||
placeholder: 例如:docs/installation.md 或 https://github.com/xxx/xxx/wiki/xxx
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: issue-type
|
||||
attributes:
|
||||
label: 问题类型
|
||||
description: 文档存在什么问题?
|
||||
options:
|
||||
- 错别字或语法错误
|
||||
- 内容过时或不准确
|
||||
- 描述不清晰或有歧义
|
||||
- 缺少必要的示例代码
|
||||
- 缺少重要的说明或警告
|
||||
- 链接失效或错误
|
||||
- 其他
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: issue-desc
|
||||
attributes:
|
||||
label: 问题描述
|
||||
description: 详细说明文档中存在的问题
|
||||
placeholder: 例如:第 3 步中的命令拼写错误,应该是 "npm install" 而不是 "npm instal"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: 修改建议
|
||||
description: 你认为应该如何修改?
|
||||
placeholder: 例如:建议将"安装依赖"部分补充完整的命令示例,并说明不同操作系统的差异
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: 补充说明
|
||||
description: 其他需要补充的信息
|
||||
@@ -0,0 +1,92 @@
|
||||
name: "功能与体验优化"
|
||||
description: "对现有的功能逻辑进行优化,或改进用户体验"
|
||||
title: "[Enhancement]: "
|
||||
labels: ["type: enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
持续优化是项目进步的动力!请告诉我们哪个现有功能可以做得更好。
|
||||
- type: input
|
||||
id: confirm-unique
|
||||
attributes:
|
||||
label: 确认唯一性
|
||||
description: 请输入:我已确认没有相同问题出现
|
||||
placeholder: 我已确认没有相同问题出现
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: confirm-beneficial
|
||||
attributes:
|
||||
label: 确认有益性
|
||||
description: 请输入:我确认这真的对应用有益
|
||||
placeholder: 我确认这真的对应用有益
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: pre-check
|
||||
attributes:
|
||||
label: 提交前确认
|
||||
options:
|
||||
- label: 这是对现有功能的改进,而不是全新功能
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: category
|
||||
attributes:
|
||||
label: 优化类别
|
||||
description: 这个优化主要属于哪个方面?
|
||||
options:
|
||||
- 性能优化(速度、内存、资源占用)
|
||||
- 交互体验(操作流程、界面布局)
|
||||
- 视觉设计(样式、动画、美观度)
|
||||
- 易用性(降低使用门槛、减少操作步骤)
|
||||
- 稳定性(减少崩溃、提高可靠性)
|
||||
- 其他
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: target
|
||||
attributes:
|
||||
label: 目标功能或模块
|
||||
description: 你希望优化的具体功能或页面是哪个?
|
||||
placeholder: 例如:聊天页面的消息加载、设置页面的布局、文件上传功能
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: current-behavior
|
||||
attributes:
|
||||
label: 当前表现
|
||||
description: 描述当前功能的不足之处或存在的问题
|
||||
placeholder: 例如:消息列表滚动时会出现明显卡顿,加载 100 条消息需要 3 秒
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: improvement
|
||||
attributes:
|
||||
label: 优化建议
|
||||
description: 详细说明你的优化方案和预期效果
|
||||
placeholder: 例如:建议使用虚拟滚动技术,只渲染可见区域的消息,预计可将加载时间缩短到 0.5 秒以内
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: benefits
|
||||
attributes:
|
||||
label: 优化收益
|
||||
description: 这个优化会带来什么具体好处?
|
||||
placeholder: 例如:提升 80% 的加载速度、减少 50% 的内存占用、降低用户操作步骤从 5 步到 2 步
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: impact
|
||||
attributes:
|
||||
label: 影响范围
|
||||
description: 这个优化会影响哪些用户或场景?
|
||||
placeholder: 例如:所有用户在查看历史消息时都会受益,尤其是群聊消息较多的场景
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: 参与贡献
|
||||
options:
|
||||
- label: 我愿意提交 Pull Request 来实现这个优化
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,85 @@
|
||||
name: "全新功能请求"
|
||||
description: "提议一个目前项目中完全没有的新特性"
|
||||
title: "[Feature]: "
|
||||
labels: ["type: feature"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢你为项目提供新想法!详细的需求描述能极大提高该功能被采纳的几率。
|
||||
- type: input
|
||||
id: confirm-unique
|
||||
attributes:
|
||||
label: 确认唯一性
|
||||
description: 请输入:我已确认没有相同问题出现
|
||||
placeholder: 我已确认没有相同问题出现
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: confirm-useful
|
||||
attributes:
|
||||
label: 确认实用性
|
||||
description: 请输入:我认为这会对大部分人都有用
|
||||
placeholder: 我认为这会对大部分人都有用
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: pre-check
|
||||
attributes:
|
||||
label: 提交前确认
|
||||
options:
|
||||
- label: 这是一个全新的功能,而不是对现有功能的改进
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: 功能优先级
|
||||
description: 你认为这个功能有多重要?
|
||||
options:
|
||||
- 高优先级(核心功能缺失,严重影响使用体验)
|
||||
- 中优先级(有助于提升使用体验)
|
||||
- 低优先级(锦上添花的功能)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: 问题或痛点
|
||||
description: 【为什么需要】你现在做某件事遇到了什么困难?缺少什么能力?
|
||||
placeholder: 例如:目前无法批量导出聊天记录,每次只能手动复制单条消息,处理 100 条消息需要半小时
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: 期望的解决方案
|
||||
description: 【怎么实现】详细描述功能的操作流程、界面位置、可选参数等
|
||||
placeholder: 例如:在聊天窗口右键菜单添加"导出记录",点击后弹窗可选时间范围、导出格式(TXT/JSON)、筛选用户,最后保存到本地
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: use-case
|
||||
attributes:
|
||||
label: 使用场景
|
||||
description: 【什么时候用】你会在哪些具体情况下使用这个功能?
|
||||
placeholder: 例如:每周五整理工作讨论记录;保存客户沟通记录作为合同依据;备份重要群聊内容
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: 替代方案
|
||||
description: 你目前使用什么临时方案?或者有没有考虑过其他实现方式?
|
||||
placeholder: 例如:目前只能手动截图或逐条复制粘贴
|
||||
- type: textarea
|
||||
id: reference
|
||||
attributes:
|
||||
label: 参考示例
|
||||
description: 其他应用中是否有类似功能可以参考?
|
||||
placeholder: 例如:聊天记录导出功能、Telegram 的导出数据功能
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: 参与贡献
|
||||
options:
|
||||
- label: 我愿意提交 Pull Request 来实现这个功能
|
||||
@@ -0,0 +1,77 @@
|
||||
name: "使用答疑"
|
||||
description: "关于如何配置、如何使用项目的求助"
|
||||
title: "[Question]: "
|
||||
labels: ["type: question"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
在提问之前,请确保你已经仔细阅读过我们的官方文档。
|
||||
- type: input
|
||||
id: confirm-unique
|
||||
attributes:
|
||||
label: 确认唯一性
|
||||
description: 请输入:我已确认没有相同问题出现
|
||||
placeholder: 我已确认没有相同问题出现
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: pre-check
|
||||
attributes:
|
||||
label: 提交前确认
|
||||
options:
|
||||
- label: 我已阅读过相关文档
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: question-type
|
||||
attributes:
|
||||
label: 问题类型
|
||||
description: 你的问题属于哪个方面?
|
||||
options:
|
||||
- 安装部署问题
|
||||
- 配置相关问题
|
||||
- 功能使用问题
|
||||
- API 调用问题
|
||||
- 错误排查问题
|
||||
- 其他
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: 问题描述
|
||||
description: 清晰描述你遇到的问题或疑问
|
||||
placeholder: 例如:我在 Windows 系统上安装后无法启动应用,双击图标没有任何反应
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: attempts
|
||||
attributes:
|
||||
label: 已尝试的方法
|
||||
description: 你已经尝试过哪些解决方法?
|
||||
placeholder: 例如:我尝试过重新安装、以管理员身份运行、关闭防火墙,但问题依然存在
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: 运行环境
|
||||
description: 提供你的系统环境信息
|
||||
placeholder: |
|
||||
操作系统:Windows 11
|
||||
应用版本:v1.2.3
|
||||
系统架构:x64
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: code-snippet
|
||||
attributes:
|
||||
label: 相关配置或代码
|
||||
description: 如果涉及配置或代码问题,请粘贴相关内容
|
||||
placeholder: 粘贴你的配置文件或代码片段
|
||||
render: javascript
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: 截图或日志
|
||||
description: 如有必要,请提供截图或错误日志
|
||||
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: "dev"
|
||||
@@ -0,0 +1,306 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
retry_cmd() {
|
||||
local attempts="$1"
|
||||
local delay_seconds="$2"
|
||||
shift 2
|
||||
|
||||
local i
|
||||
local exit_code
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
if "$@"; then
|
||||
return 0
|
||||
else
|
||||
exit_code=$?
|
||||
fi
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Command failed (attempt $i/$attempts, exit=$exit_code): $*" >&2
|
||||
echo "Retrying in ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Command failed after $attempts attempts: $*" >&2
|
||||
return "$exit_code"
|
||||
}
|
||||
|
||||
capture_cmd_with_retry() {
|
||||
local result_var="$1"
|
||||
local attempts="$2"
|
||||
local delay_seconds="$3"
|
||||
shift 3
|
||||
|
||||
local i
|
||||
local output=""
|
||||
local exit_code=1
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
if output="$("$@" 2>/dev/null)"; then
|
||||
printf -v "$result_var" "%s" "$output"
|
||||
return 0
|
||||
else
|
||||
exit_code=$?
|
||||
fi
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Capture command failed (attempt $i/$attempts, exit=$exit_code): $*" >&2
|
||||
echo "Retrying in ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Capture command failed after $attempts attempts: $*" >&2
|
||||
return "$exit_code"
|
||||
}
|
||||
|
||||
wait_for_release_id() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
local attempts="${3:-12}"
|
||||
local delay_seconds="${4:-2}"
|
||||
|
||||
local i
|
||||
local release_id
|
||||
local release_api_url
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
release_id="$(gh api "repos/$repo/releases/tags/$tag" --jq '.id' 2>/dev/null || true)"
|
||||
if [[ "$release_id" =~ ^[0-9]+$ ]]; then
|
||||
echo "$release_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
release_id="$(gh release view "$tag" --repo "$repo" --json databaseId --jq '.databaseId // empty' 2>/dev/null || true)"
|
||||
if [[ "$release_id" =~ ^[0-9]+$ ]]; then
|
||||
echo "$release_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
release_api_url="$(gh release view "$tag" --repo "$repo" --json apiUrl --jq '.apiUrl // empty' 2>/dev/null || true)"
|
||||
if [[ "$release_api_url" =~ /releases/([0-9]+)$ ]]; then
|
||||
echo "${BASH_REMATCH[1]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Release id for tag '$tag' is not ready yet (attempt $i/$attempts), retrying in ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Unable to fetch release id for tag '$tag' after $attempts attempts." >&2
|
||||
gh release view "$tag" --repo "$repo" --json databaseId,id,isDraft,isPrerelease,url 2>/dev/null || true
|
||||
gh api "repos/$repo/releases/tags/$tag" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}' 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
|
||||
settle_release_state() {
|
||||
local repo="$1"
|
||||
local release_id="$2"
|
||||
local tag="$3"
|
||||
local attempts="${4:-12}"
|
||||
local delay_seconds="${5:-2}"
|
||||
local endpoint="repos/$repo/releases/tags/$tag"
|
||||
|
||||
local i
|
||||
local draft_state
|
||||
local prerelease_state
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
gh release edit "$tag" --repo "$repo" --draft=false --prerelease >/dev/null 2>&1 || true
|
||||
gh api --method PATCH "repos/$repo/releases/$release_id" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
|
||||
draft_state="$(gh api "$endpoint" --jq '.draft' 2>/dev/null || gh release view "$tag" --repo "$repo" --json isDraft --jq '.isDraft' 2>/dev/null || echo true)"
|
||||
prerelease_state="$(gh api "$endpoint" --jq '.prerelease' 2>/dev/null || gh release view "$tag" --repo "$repo" --json isPrerelease --jq '.isPrerelease' 2>/dev/null || echo false)"
|
||||
if [ "$draft_state" = "false" ] && [ "$prerelease_state" = "true" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Release '$tag' state not settled yet (attempt $i/$attempts), retrying in ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Failed to settle release state for tag '$tag'." >&2
|
||||
gh release view "$tag" --repo "$repo" --json isDraft,isPrerelease,url 2>/dev/null || true
|
||||
gh api "$endpoint" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}' 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
|
||||
print_release_state() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
|
||||
gh api "repos/$repo/releases/tags/$tag" --jq '{isDraft: .draft, isPrerelease: .prerelease, url: .html_url}' 2>/dev/null \
|
||||
|| gh release view "$tag" --repo "$repo" --json isDraft,isPrerelease,url --jq '{isDraft: .isDraft, isPrerelease: .isPrerelease, url: .url}'
|
||||
}
|
||||
|
||||
wait_for_release_absent() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
local attempts="${3:-12}"
|
||||
local delay_seconds="${4:-2}"
|
||||
|
||||
local i
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Release '$tag' still exists (attempt $i/$attempts), waiting ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
return 0
|
||||
done
|
||||
|
||||
echo "Release '$tag' still exists after waiting." >&2
|
||||
gh release view "$tag" --repo "$repo" --json url,isDraft,isPrerelease 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_git_tag_absent() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
local attempts="${3:-12}"
|
||||
local delay_seconds="${4:-2}"
|
||||
|
||||
local i
|
||||
for ((i = 1; i <= attempts; i++)); do
|
||||
if gh api "repos/$repo/git/ref/tags/$tag" >/dev/null 2>&1; then
|
||||
if [ "$i" -lt "$attempts" ]; then
|
||||
echo "Git tag '$tag' still exists (attempt $i/$attempts), waiting ${delay_seconds}s..." >&2
|
||||
sleep "$delay_seconds"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
return 0
|
||||
done
|
||||
|
||||
echo "Git tag '$tag' still exists after waiting." >&2
|
||||
gh api "repos/$repo/git/ref/tags/$tag" --jq '{ref: .ref, object: .object.sha}' 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
|
||||
recreate_fixed_prerelease() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
local target_branch="$3"
|
||||
local release_title="$4"
|
||||
local release_notes="$5"
|
||||
|
||||
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
|
||||
retry_cmd 5 3 gh release delete "$tag" --repo "$repo" --yes --cleanup-tag
|
||||
fi
|
||||
|
||||
wait_for_release_absent "$repo" "$tag" 12 2
|
||||
|
||||
if gh api "repos/$repo/git/ref/tags/$tag" >/dev/null 2>&1; then
|
||||
retry_cmd 5 2 gh api --method DELETE "repos/$repo/git/refs/tags/$tag"
|
||||
fi
|
||||
|
||||
wait_for_git_tag_absent "$repo" "$tag" 12 2
|
||||
|
||||
local created="false"
|
||||
local i
|
||||
for ((i = 1; i <= 6; i++)); do
|
||||
if gh release create "$tag" --repo "$repo" --title "$release_title" --notes "$release_notes" --prerelease --target "$target_branch"; then
|
||||
created="true"
|
||||
break
|
||||
fi
|
||||
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
|
||||
echo "Release '$tag' appears to exist after create failure; continue to settle state." >&2
|
||||
created="true"
|
||||
break
|
||||
fi
|
||||
if [ "$i" -lt 6 ]; then
|
||||
echo "Create release '$tag' failed (attempt $i/6), retrying in 3s..." >&2
|
||||
sleep 3
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$created" != "true" ]; then
|
||||
echo "Failed to create release '$tag'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local release_id
|
||||
release_id="$(wait_for_release_id "$repo" "$tag" 12 2)"
|
||||
settle_release_state "$repo" "$release_id" "$tag" 12 2
|
||||
}
|
||||
|
||||
upload_release_assets_with_retry() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
shift 2
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "No release assets provided for upload." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
wait_for_release_id "$repo" "$tag" 12 2 >/dev/null
|
||||
retry_cmd 5 3 gh release upload "$tag" "$@" --repo "$repo" --clobber
|
||||
}
|
||||
|
||||
upload_generated_update_ymls() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
local minimum_version="$3"
|
||||
shift 3
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "No update yml asset names provided." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -d release ]; then
|
||||
echo "::error::release directory was not generated."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local found="false"
|
||||
local asset_name
|
||||
local yml_path
|
||||
for asset_name in "$@"; do
|
||||
yml_path="$(find release -type f -name "$asset_name" -print -quit)"
|
||||
if [ -z "$yml_path" ]; then
|
||||
echo "::warning::$asset_name was not generated under release/."
|
||||
continue
|
||||
fi
|
||||
|
||||
found="true"
|
||||
if ! grep -q '^minimumVersion:' "$yml_path"; then
|
||||
echo "minimumVersion: $minimum_version" >> "$yml_path"
|
||||
fi
|
||||
retry_cmd 5 3 gh release upload "$tag" --repo "$repo" "$yml_path" --clobber
|
||||
done
|
||||
|
||||
if [ "$found" != "true" ]; then
|
||||
echo "::error::None of the expected update yml assets were generated: $*"
|
||||
echo "::group::Generated release files"
|
||||
find release -maxdepth 2 -type f -print || true
|
||||
echo "::endgroup::"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
upload_generated_release_files() {
|
||||
local repo="$1"
|
||||
local tag="$2"
|
||||
|
||||
if [ ! -d release ]; then
|
||||
echo "::error::release directory was not generated."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local assets=()
|
||||
while IFS= read -r asset_path; do
|
||||
assets+=("$asset_path")
|
||||
done < <(find release -maxdepth 1 -type f ! -name '*.yml' -print)
|
||||
|
||||
if [ "${#assets[@]}" -eq 0 ]; then
|
||||
echo "::error::No release assets were generated under release/."
|
||||
echo "::group::Generated release files"
|
||||
find release -maxdepth 2 -type f -print || true
|
||||
echo "::endgroup::"
|
||||
return 1
|
||||
fi
|
||||
|
||||
upload_release_assets_with_retry "$repo" "$tag" "${assets[@]}"
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
name: Build and Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/
|
||||
|
||||
jobs:
|
||||
prepare-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Prepare GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG=${GITHUB_REF_NAME}
|
||||
REPO=${{ github.repository }}
|
||||
if gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then
|
||||
echo "Release $TAG already exists."
|
||||
else
|
||||
gh release create "$TAG" --repo "$REPO" --title "${TAG#v}" --notes "Release $TAG" --target "$GITHUB_SHA"
|
||||
fi
|
||||
|
||||
release-mac-arm64:
|
||||
runs-on: macos-14
|
||||
needs: prepare-release
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
- name: Install Dependencies
|
||||
run: npm install --ignore-scripts
|
||||
|
||||
- name: Sync version with tag
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
echo "Syncing package.json version to $VERSION"
|
||||
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='$VERSION';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')"
|
||||
|
||||
- name: Build Frontend & Type Check
|
||||
shell: bash
|
||||
run: |
|
||||
npx tsc
|
||||
npx vite build
|
||||
|
||||
- name: Package and Publish macOS arm64 (unsigned DMG + ZIP)
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CSC_IDENTITY_AUTO_DISCOVERY: "false"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export ELECTRON_BUILDER_BINARIES_MIRROR="https://github.com/electron-userland/electron-builder-binaries/releases/download/"
|
||||
echo "Using ELECTRON_BUILDER_BINARIES_MIRROR=$ELECTRON_BUILDER_BINARIES_MIRROR"
|
||||
if ! npx electron-builder --mac dmg zip --arm64 --publish never '--config.npmRebuild=false'; then
|
||||
echo "::warning::DMG packaging failed (hdiutil instability on runner). Retrying with ZIP only."
|
||||
npx electron-builder --mac zip --arm64 --publish never '--config.npmRebuild=false'
|
||||
fi
|
||||
|
||||
- name: Inject minimumVersion into latest yml
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/scripts/release-utils.sh
|
||||
TAG=${GITHUB_REF_NAME}
|
||||
REPO=${{ github.repository }}
|
||||
MINIMUM_VERSION="4.1.7"
|
||||
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
|
||||
upload_generated_release_files "$REPO" "$TAG"
|
||||
upload_generated_update_ymls "$REPO" "$TAG" "$MINIMUM_VERSION" latest-mac.yml latest-arm64-mac.yml
|
||||
|
||||
release-linux:
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-release
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Sync version with tag
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
echo "Syncing package.json version to $VERSION"
|
||||
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='$VERSION';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')"
|
||||
|
||||
- name: Build Frontend & Type Check
|
||||
shell: bash
|
||||
run: |
|
||||
npx tsc
|
||||
npx vite build
|
||||
|
||||
- name: Package and Publish Linux
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
npx electron-builder --linux --publish never
|
||||
|
||||
- name: Inject minimumVersion into latest yml
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/scripts/release-utils.sh
|
||||
TAG=${GITHUB_REF_NAME}
|
||||
REPO=${{ github.repository }}
|
||||
MINIMUM_VERSION="4.1.7"
|
||||
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
|
||||
upload_generated_release_files "$REPO" "$TAG"
|
||||
upload_generated_update_ymls "$REPO" "$TAG" "$MINIMUM_VERSION" latest-linux.yml
|
||||
|
||||
release:
|
||||
runs-on: windows-latest
|
||||
needs: prepare-release
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Sync version with tag
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
echo "Syncing package.json version to $VERSION"
|
||||
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='$VERSION';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')"
|
||||
|
||||
- name: Build Frontend & Type Check
|
||||
shell: bash
|
||||
run: |
|
||||
npx tsc
|
||||
npx vite build
|
||||
|
||||
- name: Package and Publish
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
npx electron-builder --win nsis --x64 --publish never '--config.artifactName=${productName}-${version}-x64-Setup.${ext}'
|
||||
|
||||
- name: Inject minimumVersion into latest yml
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/scripts/release-utils.sh
|
||||
TAG=${GITHUB_REF_NAME}
|
||||
REPO=${{ github.repository }}
|
||||
MINIMUM_VERSION="4.1.7"
|
||||
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
|
||||
upload_generated_release_files "$REPO" "$TAG"
|
||||
upload_generated_update_ymls "$REPO" "$TAG" "$MINIMUM_VERSION" latest.yml
|
||||
|
||||
release-windows-arm64:
|
||||
runs-on: windows-latest
|
||||
needs: prepare-release
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Sync version with tag
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
echo "Syncing package.json version to $VERSION"
|
||||
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='$VERSION';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')"
|
||||
|
||||
- name: Build Frontend & Type Check
|
||||
shell: bash
|
||||
run: |
|
||||
npx tsc
|
||||
npx vite build
|
||||
|
||||
- name: Package and Publish Windows arm64
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
npx electron-builder --win nsis --arm64 --publish never '--config.publish.channel=latest-arm64' '--config.artifactName=${productName}-${version}-arm64-Setup.${ext}'
|
||||
|
||||
- name: Inject minimumVersion into latest yml
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/scripts/release-utils.sh
|
||||
TAG=${GITHUB_REF_NAME}
|
||||
REPO=${{ github.repository }}
|
||||
MINIMUM_VERSION="4.1.7"
|
||||
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
|
||||
upload_generated_release_files "$REPO" "$TAG"
|
||||
upload_generated_update_ymls "$REPO" "$TAG" "$MINIMUM_VERSION" latest-arm64.yml
|
||||
|
||||
update-release-notes:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- release-mac-arm64
|
||||
- release-linux
|
||||
- release
|
||||
- release-windows-arm64
|
||||
|
||||
steps:
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Generate release notes with platform download links
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/scripts/release-utils.sh
|
||||
|
||||
TAG="$GITHUB_REF_NAME"
|
||||
REPO="$GITHUB_REPOSITORY"
|
||||
RELEASE_PAGE="https://github.com/$REPO/releases/tag/$TAG"
|
||||
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
|
||||
|
||||
capture_cmd_with_retry ASSETS_JSON 8 3 gh release view "$TAG" --repo "$REPO" --json assets
|
||||
|
||||
pick_asset() {
|
||||
local pattern="$1"
|
||||
echo "$ASSETS_JSON" | jq -r --arg p "$pattern" '[.assets[].name | select(test($p))][0] // ""'
|
||||
}
|
||||
|
||||
WINDOWS_ASSET="$(echo "$ASSETS_JSON" | jq -r '[.assets[].name | select(test("x64.*\\.exe$"))][0] // ""')"
|
||||
if [ -z "$WINDOWS_ASSET" ]; then
|
||||
WINDOWS_ASSET="$(echo "$ASSETS_JSON" | jq -r '[.assets[].name | select(test("\\.exe$")) | select(test("arm64") | not)][0] // ""')"
|
||||
fi
|
||||
WINDOWS_ARM64_ASSET="$(echo "$ASSETS_JSON" | jq -r '[.assets[].name | select(test("arm64.*\\.exe$"))][0] // ""')"
|
||||
MAC_ASSET="$(pick_asset "\\.dmg$")"
|
||||
if [ -z "$MAC_ASSET" ]; then
|
||||
MAC_ASSET="$(pick_asset "arm64\\.zip$")"
|
||||
fi
|
||||
LINUX_TAR_ASSET="$(pick_asset "\\.tar\\.gz$")"
|
||||
LINUX_APPIMAGE_ASSET="$(pick_asset "\\.AppImage$")"
|
||||
|
||||
build_link() {
|
||||
local name="$1"
|
||||
if [ -n "$name" ]; then
|
||||
echo "https://github.com/$REPO/releases/download/$TAG/$name"
|
||||
fi
|
||||
}
|
||||
|
||||
WINDOWS_URL="$(build_link "$WINDOWS_ASSET")"
|
||||
WINDOWS_ARM64_URL="$(build_link "$WINDOWS_ARM64_ASSET")"
|
||||
MAC_URL="$(build_link "$MAC_ASSET")"
|
||||
LINUX_TAR_URL="$(build_link "$LINUX_TAR_ASSET")"
|
||||
LINUX_APPIMAGE_URL="$(build_link "$LINUX_APPIMAGE_ASSET")"
|
||||
|
||||
cat > release_notes.md <<EOF
|
||||
## 更新日志
|
||||
修复了一些已知问题
|
||||
|
||||
## 查看更多日志/获取最新动态
|
||||
[点击加入 Telegram 频道](https://t.me/weflow_cc)
|
||||
|
||||
## 下载
|
||||
- Windows x64(Win10+): [点击下载](${WINDOWS_URL:-$RELEASE_PAGE})
|
||||
- Windows arm64: [点击下载](${WINDOWS_ARM64_URL:-$RELEASE_PAGE})
|
||||
- macOS(M系列芯片): [点击下载](${MAC_URL:-$RELEASE_PAGE})
|
||||
- Linux (.tar.gz): [点击下载](${LINUX_TAR_URL:-$RELEASE_PAGE})
|
||||
- Linux (.AppImage): [点击下载](${LINUX_APPIMAGE_URL:-$RELEASE_PAGE})
|
||||
|
||||
## macOS 安装提示
|
||||
- 如果被系统提示已损坏,你需要在终端执行以下命令去除隔离标记:
|
||||
- \`xattr -dr com.apple.quarantine "/Applications/WeFlow.app"\`
|
||||
- 执行后重新打开 WeFlow。
|
||||
|
||||
> 如果某个平台链接暂时未生成,可进入[完整发布页]($RELEASE_PAGE)查看全部资源
|
||||
EOF
|
||||
|
||||
retry_cmd 5 3 gh release edit "$TAG" --repo "$REPO" --notes-file release_notes.md
|
||||
|
||||
deploy-aur:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [release-linux]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- name: Check AUR credentials
|
||||
id: aur-credentials
|
||||
shell: bash
|
||||
env:
|
||||
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
run: |
|
||||
if [ -z "${AUR_SSH_PRIVATE_KEY}" ]; then
|
||||
echo "::notice::AUR_SSH_PRIVATE_KEY is not configured; skipping AUR publish."
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Checkout code
|
||||
if: steps.aur-credentials.outputs.enabled == 'true'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Update PKGBUILD version
|
||||
if: steps.aur-credentials.outputs.enabled == 'true'
|
||||
run: |
|
||||
NEW_VER=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
||||
sed -i "s/^pkgver=.*/pkgver=${NEW_VER}/" resources/installer/linux/PKGBUILD
|
||||
sed -i "s/^pkgrel=.*/pkgrel=1/" resources/installer/linux/PKGBUILD
|
||||
|
||||
- name: Publish AUR package
|
||||
if: steps.aur-credentials.outputs.enabled == 'true'
|
||||
uses: KSXGitHub/github-actions-deploy-aur@master
|
||||
with:
|
||||
pkgname: weflow
|
||||
pkgbuild: resources/installer/linux/PKGBUILD
|
||||
updpkgsums: true
|
||||
assets: |
|
||||
resources/installer/linux/weflow.desktop
|
||||
resources/installer/linux/icon.png
|
||||
resources/installer/linux/.gitignore
|
||||
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_username: H3CoF6
|
||||
commit_email: h3cof6@gmail.com
|
||||
ssh_keyscan_types: ed25519
|
||||
Reference in new issue
Block a user