openyida 0.1.2 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -38
- package/bin/yida.js +164 -761
- package/lib/babel-transform/index.js +244 -0
- package/lib/babel-transform/jsx-utils.js +89 -0
- package/lib/check-update.js +72 -0
- package/lib/copy.js +258 -0
- package/lib/create-app.js +174 -0
- package/lib/create-form.js +2244 -0
- package/lib/create-page.js +89 -0
- package/lib/env.js +164 -0
- package/lib/get-page-config.js +102 -0
- package/lib/get-schema.js +76 -0
- package/lib/login.js +323 -0
- package/lib/publish.js +610 -0
- package/lib/save-share-config.js +268 -0
- package/lib/update-form-config.js +237 -0
- package/lib/utils.js +443 -0
- package/lib/verify-short-url.js +279 -0
- package/package.json +20 -7
- package/project/.cache/demo-schema.json +2353 -0
- package/project/pages/src/demo-birthday-game.js +833 -0
- package/project/pages/src/demo-future-vision-2026.js +1102 -0
- package/project/pages/src/demo-salary-calculator.js +904 -0
- package/project/prd/demo-birthday-game.md +39 -0
- package/project/prd/demo-future-vision-2026.md +78 -0
- package/project/prd/demo-salary-calculator.md +101 -0
- package/scripts/postinstall.js +114 -0
- package/yida-skills/SKILL.md +273 -0
- package/yida-skills/reference/association-form-field.md +469 -0
- package/yida-skills/reference/employee-field.md +17 -0
- package/yida-skills/reference/model-api.md +73 -0
- package/yida-skills/reference/serial-number-field.md +132 -0
- package/yida-skills/reference/yida-api.md +1208 -0
- package/yida-skills/skills/yida-app/SKILL.md +394 -0
- package/yida-skills/skills/yida-create-app/SKILL.md +158 -0
- package/yida-skills/skills/yida-create-form-page/SKILL.md +598 -0
- package/yida-skills/skills/yida-create-page/SKILL.md +103 -0
- package/yida-skills/skills/yida-custom-page/SKILL.md +533 -0
- package/yida-skills/skills/yida-get-schema/SKILL.md +90 -0
- package/yida-skills/skills/yida-login/SKILL.md +200 -0
- package/yida-skills/skills/yida-logout/SKILL.md +58 -0
- package/yida-skills/skills/yida-page-config/SKILL.md +261 -0
- package/yida-skills/skills/yida-publish-page/SKILL.md +113 -0
- package/.eslintrc.json +0 -25
- package/.github/workflows/ci.yml +0 -123
- package/.github/workflows/publish.yml +0 -105
- package/.github/workflows/update-contributors.yml +0 -151
- package/.openclaw/skills/yida-issue/SKILL.md +0 -27
- package/.openclaw/skills/yida-issue/scripts/create-issue.js +0 -317
- package/CLAUDE.md +0 -168
- package/CONTRIBUTING.md +0 -59
- package/install-skills.ps1 +0 -162
- package/install-skills.sh +0 -175
- package/pages/dist/.gitkeep +0 -0
- package/pages/src/.gitkeep +0 -0
- package/prd/salary-calculator.md +0 -15
- package/tests/cli.test.js +0 -930
- package/tests/install.test.js +0 -277
- package/tests/yida-issue.test.js +0 -314
- /package/{config.json → project/config.json} +0 -0
- /package/{.cache → project/pages/dist}/.gitkeep +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yida-publish-page
|
|
3
|
+
description: 宜搭自定义页面发布技能,将 JSX 源码经 Babel 编译、UglifyJS 压缩后构建 Schema,并通过 saveFormSchema 接口部署到宜搭平台。
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility:
|
|
6
|
+
- opencode
|
|
7
|
+
- claude-code
|
|
8
|
+
metadata:
|
|
9
|
+
audience: developers
|
|
10
|
+
workflow: yida-deployment
|
|
11
|
+
version: 1.0.0
|
|
12
|
+
tags:
|
|
13
|
+
- yida
|
|
14
|
+
- low-code
|
|
15
|
+
- deploy
|
|
16
|
+
- babel
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# 宜搭页面发布技能
|
|
20
|
+
|
|
21
|
+
## 概述
|
|
22
|
+
|
|
23
|
+
本技能提供宜搭自定义页面的完整发布流程:源码编译 → Schema 构建 → 读取登录态(按需触发登录)→ 接口发布。
|
|
24
|
+
|
|
25
|
+
## 何时使用
|
|
26
|
+
|
|
27
|
+
当以下场景发生时使用此技能:
|
|
28
|
+
- 用户需要将开发好的自定义页面发布到宜搭平台
|
|
29
|
+
- 用户修改了页面代码,需要重新部署
|
|
30
|
+
- 开发流程中的最后一步:发布页面
|
|
31
|
+
|
|
32
|
+
## 使用示例
|
|
33
|
+
|
|
34
|
+
### 示例 1:发布自定义页面
|
|
35
|
+
**场景**:将 JSX 源码编译并发布到宜搭
|
|
36
|
+
**命令**:
|
|
37
|
+
```bash
|
|
38
|
+
node <skill_root>/yida-publish-page/scripts/publish.js APP_XXX FORM-XXX pages/src/my-page.js
|
|
39
|
+
```
|
|
40
|
+
**输出**:
|
|
41
|
+
```json
|
|
42
|
+
{"success":true,"formUuid":"FORM-XXX","version":0}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 使用方式
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd <skill_root>/yida-publish/scripts
|
|
49
|
+
npm install # 首次需要安装依赖
|
|
50
|
+
node publish.js <appType> <formUuid> <源文件路径>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**参数说明**:
|
|
54
|
+
|
|
55
|
+
| 参数 | 说明 | 示例 |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `appType` | 应用 ID | `APP_E0MZ4VB75ZMB1BIGNVT4` |
|
|
58
|
+
| `formUuid` | 自定义页面 ID | `FORM-XXX` |
|
|
59
|
+
| `源文件路径` | 源码文件路径(相对于项目根目录) | `pages/src/xxx.js` |
|
|
60
|
+
|
|
61
|
+
> `baseUrl` 无需手动传入,脚本会自动从 `.cache/cookies.json` 读取登录态(若不存在或接口返回 302,则自动触发扫码登录),并从中读取 `base_url`。
|
|
62
|
+
|
|
63
|
+
**示例**:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
node publish.js APP_XXX FORM-XXXXXX pages/src/xxx.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 工作流程
|
|
70
|
+
|
|
71
|
+
1. **编译源码**:通过 `@ali/vu-babel-transform` 将 JSX 转换为 ES5,再通过 UglifyJS 压缩
|
|
72
|
+
2. **构建 Schema**:通过代码动态构建完整的 Schema JSON,将编译后的 `source` 和 `compiled` 填入 `actions.module`
|
|
73
|
+
3. **读取登录态**:读取项目根目录的 `.cache/cookies.json`;若不存在则自动调用 `login.py` 触发扫码登录
|
|
74
|
+
4. **发布 Schema**:通过 HTTP POST 调用 `saveFormSchema` 接口保存 Schema;根据响应体 `errorCode` 自动处理异常(详见 `yida-login` 技能文档「错误处理机制」章节)
|
|
75
|
+
5. **更新表单配置**:调用 `updateFormConfig` 接口,设置 `MINI_RESOURCE` 配置为 `8`;同样根据响应体 `errorCode` 自动处理异常
|
|
76
|
+
|
|
77
|
+
> **注意**:发布目标地址由 `.cache/cookies.json` 中保存的 `base_url` 决定(即登录后浏览器实际跳转到的域名),而非 `config.json` 中的 `loginUrl`。详见 `yida-login` 技能文档。
|
|
78
|
+
> **注意**:当发布页面碰到组织 corpId 不匹配 或 "您当前未在「xxx」组织内" 时,可以询问是否创建新的应用发布。
|
|
79
|
+
|
|
80
|
+
## 前置依赖
|
|
81
|
+
|
|
82
|
+
- Node.js 16+
|
|
83
|
+
- Python 3.12+(用于调用 yida-login)
|
|
84
|
+
- playwright(Python 版,yida-login 依赖)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd <skill_root>/yida-publish-page/scripts && npm install
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 文件结构
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
yida-publish/
|
|
94
|
+
├── SKILL.md # 本文档
|
|
95
|
+
└── scripts/
|
|
96
|
+
├── publish.js # 发布主脚本(Node.js,内含 Schema 动态构建逻辑)
|
|
97
|
+
├── package.json # Node.js 依赖声明
|
|
98
|
+
└── node_modules/ # 依赖包(npm install 后生成)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 接口说明
|
|
102
|
+
|
|
103
|
+
`saveFormSchema` 和 `updateFormConfig` 接口的完整参数、返回值和错误处理机制,请参考 `../../reference/yida-api.md` 文档中的「表单设计类 API」章节。
|
|
104
|
+
|
|
105
|
+
> **注意**:自定义页面发布时,`updateFormConfig` 的 `value` 参数固定为 `8`(区别于表单页面的 `0`)。
|
|
106
|
+
|
|
107
|
+
## 与其他技能配合
|
|
108
|
+
|
|
109
|
+
- **`yida-login`**:登录态失效时自动调用(Cookie 持久化,首次或 302 时需扫码)
|
|
110
|
+
- **`yida-custom-page`**:**编写源码前必须先加载此 skill**,严格按照其开发规范编写代码(禁止使用 React Hooks)
|
|
111
|
+
- **`yida-app`**:完整应用开发流程的最后一步
|
|
112
|
+
|
|
113
|
+
> ⚠️ **重要警告**:宜搭自定义页面使用类组件模式,**禁止使用 React Hooks**(useState/useEffect)。发布前必须确保代码已加载 `yida-custom-page` skill 并遵循其开发规范。
|
package/.eslintrc.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"browser": true,
|
|
4
|
-
"es2021": true,
|
|
5
|
-
"node": true
|
|
6
|
-
},
|
|
7
|
-
"extends": "eslint:recommended",
|
|
8
|
-
"parserOptions": {
|
|
9
|
-
"ecmaVersion": "latest",
|
|
10
|
-
"sourceType": "module"
|
|
11
|
-
},
|
|
12
|
-
"rules": {
|
|
13
|
-
"indent": ["error", 2],
|
|
14
|
-
"linebreak-style": ["error", "unix"],
|
|
15
|
-
"quotes": ["error", "single"],
|
|
16
|
-
"semi": ["error", "always"],
|
|
17
|
-
"no-unused-vars": "warn",
|
|
18
|
-
"no-console": "off"
|
|
19
|
-
},
|
|
20
|
-
"ignorePatterns": [
|
|
21
|
-
"*.compile.js",
|
|
22
|
-
"node_modules/",
|
|
23
|
-
"build/"
|
|
24
|
-
]
|
|
25
|
-
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [main]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
# ── 安装脚本集成测试(三平台)────────────────────────────────────────
|
|
11
|
-
install-test:
|
|
12
|
-
name: Install Script (${{ matrix.os }})
|
|
13
|
-
runs-on: ${{ matrix.os }}
|
|
14
|
-
strategy:
|
|
15
|
-
fail-fast: false
|
|
16
|
-
matrix:
|
|
17
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
18
|
-
|
|
19
|
-
steps:
|
|
20
|
-
- name: Checkout code
|
|
21
|
-
uses: actions/checkout@v4
|
|
22
|
-
|
|
23
|
-
# ── Mac / Linux ──────────────────────────────────────────────────
|
|
24
|
-
- name: Install Skills (Mac/Linux)
|
|
25
|
-
if: runner.os != 'Windows'
|
|
26
|
-
run: bash install-skills.sh --global
|
|
27
|
-
|
|
28
|
-
- name: Verify Skills installed (Mac/Linux)
|
|
29
|
-
if: runner.os != 'Windows'
|
|
30
|
-
run: |
|
|
31
|
-
if [ ! -d ".claude/skills/skills" ]; then
|
|
32
|
-
echo "❌ Skills 目录不存在:.claude/skills/skills"
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
skill_count=$(ls -d .claude/skills/skills/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
36
|
-
if [ "$skill_count" -eq 0 ]; then
|
|
37
|
-
echo "❌ 未找到任何已安装的 Skill"
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
40
|
-
echo "✅ Skills 安装验证通过,共 ${skill_count} 个"
|
|
41
|
-
|
|
42
|
-
- name: Verify shell script syntax (Mac/Linux)
|
|
43
|
-
if: runner.os != 'Windows'
|
|
44
|
-
run: sh -n install-skills.sh && echo "✅ install-skills.sh 语法检查通过"
|
|
45
|
-
|
|
46
|
-
# ── Windows ──────────────────────────────────────────────────────
|
|
47
|
-
- name: Install Skills (Windows)
|
|
48
|
-
if: runner.os == 'Windows'
|
|
49
|
-
shell: pwsh
|
|
50
|
-
run: |
|
|
51
|
-
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
|
|
52
|
-
.\install-skills.ps1 --global
|
|
53
|
-
|
|
54
|
-
- name: Verify Skills installed (Windows)
|
|
55
|
-
if: runner.os == 'Windows'
|
|
56
|
-
shell: pwsh
|
|
57
|
-
run: |
|
|
58
|
-
$skillsPath = ".claude\skills\skills"
|
|
59
|
-
if (-not (Test-Path $skillsPath)) {
|
|
60
|
-
Write-Host "❌ Skills 目录不存在:$skillsPath"
|
|
61
|
-
exit 1
|
|
62
|
-
}
|
|
63
|
-
$skillCount = (Get-ChildItem -Path $skillsPath -Directory).Count
|
|
64
|
-
if ($skillCount -eq 0) {
|
|
65
|
-
Write-Host "❌ 未找到任何已安装的 Skill"
|
|
66
|
-
exit 1
|
|
67
|
-
}
|
|
68
|
-
Write-Host "✅ Skills 安装验证通过,共 $skillCount 个"
|
|
69
|
-
|
|
70
|
-
- name: Verify PowerShell script syntax (Windows)
|
|
71
|
-
if: runner.os == 'Windows'
|
|
72
|
-
shell: pwsh
|
|
73
|
-
run: |
|
|
74
|
-
$errors = $null
|
|
75
|
-
$null = [System.Management.Automation.Language.Parser]::ParseFile(
|
|
76
|
-
(Resolve-Path "install-skills.ps1").Path, [ref]$null, [ref]$errors
|
|
77
|
-
)
|
|
78
|
-
if ($errors.Count -gt 0) {
|
|
79
|
-
$errors | ForEach-Object { Write-Host "❌ $_" }
|
|
80
|
-
exit 1
|
|
81
|
-
}
|
|
82
|
-
Write-Host "✅ install-skills.ps1 语法检查通过"
|
|
83
|
-
|
|
84
|
-
# ── 单元测试与代码质量(ubuntu)──────────────────────────────────────
|
|
85
|
-
test:
|
|
86
|
-
name: Unit Tests
|
|
87
|
-
runs-on: ubuntu-latest
|
|
88
|
-
needs: install-test
|
|
89
|
-
|
|
90
|
-
steps:
|
|
91
|
-
- name: Checkout code
|
|
92
|
-
uses: actions/checkout@v4
|
|
93
|
-
|
|
94
|
-
- name: Install Skills
|
|
95
|
-
run: bash install-skills.sh --global
|
|
96
|
-
|
|
97
|
-
- name: Setup Node.js
|
|
98
|
-
uses: actions/setup-node@v4
|
|
99
|
-
with:
|
|
100
|
-
node-version: '20'
|
|
101
|
-
|
|
102
|
-
- name: Validate JavaScript syntax
|
|
103
|
-
run: |
|
|
104
|
-
for file in .claude/skills/skills/*/scripts/*.js; do
|
|
105
|
-
[ -f "$file" ] || continue
|
|
106
|
-
node --check "$file" || exit 1
|
|
107
|
-
done
|
|
108
|
-
|
|
109
|
-
- name: Validate JSON files
|
|
110
|
-
run: |
|
|
111
|
-
find . -name "*.json" -path "./.claude/skills/skills/*" | while read -r file; do
|
|
112
|
-
node -e "JSON.parse(require('fs').readFileSync(process.argv[1]))" -- "$file" || exit 1
|
|
113
|
-
echo " ✅ $file"
|
|
114
|
-
done
|
|
115
|
-
|
|
116
|
-
- name: Install dependencies
|
|
117
|
-
run: npm install
|
|
118
|
-
|
|
119
|
-
- name: Run tests
|
|
120
|
-
run: npm test
|
|
121
|
-
|
|
122
|
-
- name: Run tests with coverage
|
|
123
|
-
run: npm run test:coverage
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
# ── 发布前:三平台安装脚本验证 ────────────────────────────────────────
|
|
10
|
-
pre-publish-check:
|
|
11
|
-
name: Pre-publish Check (${{ matrix.os }})
|
|
12
|
-
runs-on: ${{ matrix.os }}
|
|
13
|
-
strategy:
|
|
14
|
-
fail-fast: true
|
|
15
|
-
matrix:
|
|
16
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
-
|
|
18
|
-
steps:
|
|
19
|
-
- name: Checkout code
|
|
20
|
-
uses: actions/checkout@v4
|
|
21
|
-
|
|
22
|
-
- name: Install Skills (Mac/Linux)
|
|
23
|
-
if: runner.os != 'Windows'
|
|
24
|
-
run: bash install-skills.sh --global
|
|
25
|
-
|
|
26
|
-
- name: Verify Skills installed (Mac/Linux)
|
|
27
|
-
if: runner.os != 'Windows'
|
|
28
|
-
run: |
|
|
29
|
-
skill_count=$(ls -d .claude/skills/skills/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
30
|
-
[ "$skill_count" -gt 0 ] && echo "✅ Skills 安装验证通过,共 ${skill_count} 个" || (echo "❌ 未找到任何已安装的 Skill" && exit 1)
|
|
31
|
-
|
|
32
|
-
- name: Install Skills (Windows)
|
|
33
|
-
if: runner.os == 'Windows'
|
|
34
|
-
shell: pwsh
|
|
35
|
-
run: |
|
|
36
|
-
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
|
|
37
|
-
.\install-skills.ps1 --global
|
|
38
|
-
|
|
39
|
-
- name: Verify Skills installed (Windows)
|
|
40
|
-
if: runner.os == 'Windows'
|
|
41
|
-
shell: pwsh
|
|
42
|
-
run: |
|
|
43
|
-
$skillCount = (Get-ChildItem -Path ".claude\skills\skills" -Directory -ErrorAction SilentlyContinue).Count
|
|
44
|
-
if ($skillCount -gt 0) { Write-Host "✅ Skills 安装验证通过,共 $skillCount 个" } else { Write-Host "❌ 未找到任何已安装的 Skill"; exit 1 }
|
|
45
|
-
|
|
46
|
-
# ── 发布到 npm ────────────────────────────────────────────────────────
|
|
47
|
-
publish:
|
|
48
|
-
name: Publish to npm
|
|
49
|
-
runs-on: ubuntu-latest
|
|
50
|
-
needs: pre-publish-check
|
|
51
|
-
permissions:
|
|
52
|
-
contents: write # 用于创建 GitHub Release
|
|
53
|
-
|
|
54
|
-
steps:
|
|
55
|
-
- name: Checkout code
|
|
56
|
-
uses: actions/checkout@v4
|
|
57
|
-
|
|
58
|
-
- name: Setup Node.js
|
|
59
|
-
uses: actions/setup-node@v4
|
|
60
|
-
with:
|
|
61
|
-
node-version: '20'
|
|
62
|
-
registry-url: 'https://registry.npmjs.org'
|
|
63
|
-
|
|
64
|
-
- name: Install Skills
|
|
65
|
-
run: bash install-skills.sh --global
|
|
66
|
-
|
|
67
|
-
- name: Install dependencies
|
|
68
|
-
run: npm install
|
|
69
|
-
|
|
70
|
-
- name: Run tests
|
|
71
|
-
run: npm test
|
|
72
|
-
|
|
73
|
-
- name: Verify package version matches tag
|
|
74
|
-
run: |
|
|
75
|
-
PKG_VERSION="v$(node -p "require('./package.json').version")"
|
|
76
|
-
TAG_VERSION="${GITHUB_REF_NAME}"
|
|
77
|
-
echo "package.json 版本:$PKG_VERSION"
|
|
78
|
-
echo "Tag 版本:$TAG_VERSION"
|
|
79
|
-
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
80
|
-
echo "❌ package.json 版本($PKG_VERSION)与 tag($TAG_VERSION)不一致,请先更新 package.json"
|
|
81
|
-
exit 1
|
|
82
|
-
fi
|
|
83
|
-
echo "✅ 版本一致,准备发布"
|
|
84
|
-
|
|
85
|
-
- name: Publish to npm
|
|
86
|
-
run: npm publish --access public
|
|
87
|
-
env:
|
|
88
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
89
|
-
|
|
90
|
-
- name: Create GitHub Release
|
|
91
|
-
uses: softprops/action-gh-release@v2
|
|
92
|
-
with:
|
|
93
|
-
tag_name: ${{ github.ref_name }}
|
|
94
|
-
name: ${{ github.ref_name }}
|
|
95
|
-
body: |
|
|
96
|
-
## 安装
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npm install -g openyida
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 更新日志
|
|
103
|
-
|
|
104
|
-
请查看 [CHANGELOG](https://github.com/openyida/openyida/commits/main) 了解本版本变更详情。
|
|
105
|
-
generate_release_notes: true
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
name: Update Contributors
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [closed]
|
|
6
|
-
branches: [main]
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
update-contributors:
|
|
11
|
-
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
permissions:
|
|
14
|
-
contents: write
|
|
15
|
-
|
|
16
|
-
steps:
|
|
17
|
-
- name: Checkout code
|
|
18
|
-
uses: actions/checkout@v4
|
|
19
|
-
with:
|
|
20
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
21
|
-
fetch-depth: 0
|
|
22
|
-
|
|
23
|
-
- name: Update README contributors
|
|
24
|
-
env:
|
|
25
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
-
REPO: ${{ github.repository }}
|
|
27
|
-
run: |
|
|
28
|
-
python3 - <<'PYEOF'
|
|
29
|
-
import subprocess
|
|
30
|
-
import json
|
|
31
|
-
import re
|
|
32
|
-
import sys
|
|
33
|
-
import os
|
|
34
|
-
|
|
35
|
-
repo = os.environ["REPO"]
|
|
36
|
-
print("📋 获取仓库所有贡献者...")
|
|
37
|
-
|
|
38
|
-
# 从 GitHub API 获取所有贡献者(gh cli 支持自动分页)
|
|
39
|
-
result = subprocess.run(
|
|
40
|
-
["gh", "api", f"repos/{repo}/contributors?per_page=100&anon=false", "--paginate"],
|
|
41
|
-
capture_output=True, text=True
|
|
42
|
-
)
|
|
43
|
-
if result.returncode != 0:
|
|
44
|
-
print(f"⚠️ 获取贡献者失败: {result.stderr}")
|
|
45
|
-
sys.exit(0)
|
|
46
|
-
|
|
47
|
-
# gh --paginate 返回多个 JSON 数组拼接,需要合并
|
|
48
|
-
raw = result.stdout.strip()
|
|
49
|
-
all_contributors = []
|
|
50
|
-
for chunk in re.findall(r'\[.*?\]', raw, re.DOTALL):
|
|
51
|
-
try:
|
|
52
|
-
all_contributors.extend(json.loads(chunk))
|
|
53
|
-
except json.JSONDecodeError:
|
|
54
|
-
pass
|
|
55
|
-
|
|
56
|
-
if not all_contributors:
|
|
57
|
-
print("⚠️ 未获取到贡献者数据,跳过更新")
|
|
58
|
-
sys.exit(0)
|
|
59
|
-
|
|
60
|
-
print(f"✅ 共获取到 {len(all_contributors)} 位贡献者")
|
|
61
|
-
|
|
62
|
-
# 读取当前 README
|
|
63
|
-
with open("README.md", "r", encoding="utf-8") as f:
|
|
64
|
-
readme_content = f.read()
|
|
65
|
-
|
|
66
|
-
# 提取 README 中已有的贡献者用户名(小写,去重)
|
|
67
|
-
existing_users = set(
|
|
68
|
-
u.lower() for u in re.findall(r'href="https://github\.com/([^"]+)"', readme_content)
|
|
69
|
-
)
|
|
70
|
-
print(f"=== 当前 README 中已有贡献者 ===")
|
|
71
|
-
for u in sorted(existing_users):
|
|
72
|
-
print(f" - {u}")
|
|
73
|
-
|
|
74
|
-
# 机器人账号关键词(跳过)
|
|
75
|
-
bot_patterns = re.compile(r'\[bot\]|dependabot|github-actions|renovate|actions-user', re.IGNORECASE)
|
|
76
|
-
|
|
77
|
-
# 找出新贡献者,按贡献数量排序(API 返回已按贡献数降序)
|
|
78
|
-
new_html_parts = []
|
|
79
|
-
for contributor in all_contributors:
|
|
80
|
-
login = contributor.get("login", "")
|
|
81
|
-
avatar_url = contributor.get("avatar_url", "")
|
|
82
|
-
html_url = contributor.get("html_url", f"https://github.com/{login}")
|
|
83
|
-
|
|
84
|
-
if not login:
|
|
85
|
-
continue
|
|
86
|
-
|
|
87
|
-
# 跳过机器人
|
|
88
|
-
if bot_patterns.search(login):
|
|
89
|
-
print(f" 🤖 跳过机器人: {login}")
|
|
90
|
-
continue
|
|
91
|
-
|
|
92
|
-
# 跳过已在 README 中的贡献者
|
|
93
|
-
if login.lower() in existing_users:
|
|
94
|
-
print(f" ⏭️ 已存在: {login}")
|
|
95
|
-
continue
|
|
96
|
-
|
|
97
|
-
print(f" ✨ 新贡献者: {login}")
|
|
98
|
-
# 构建头像 HTML(与现有格式完全一致)
|
|
99
|
-
# 强制将版本参数替换为 v=4,修复旧账号可能返回 v=3 的问题(issue #31)
|
|
100
|
-
avatar_url_v4 = re.sub(r'\?v=\d+', '?v=4', avatar_url)
|
|
101
|
-
avatar_48 = f"{avatar_url_v4}&s=48"
|
|
102
|
-
new_html_parts.append(
|
|
103
|
-
f'<a href="{html_url}"><img src="{avatar_48}" width="48" height="48" alt="{login}" title="{login}"/></a>'
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
if not new_html_parts:
|
|
107
|
-
print("\n✅ 没有新贡献者需要添加,README 无需更新")
|
|
108
|
-
sys.exit(0)
|
|
109
|
-
|
|
110
|
-
print(f"\n📝 添加 {len(new_html_parts)} 位新贡献者到 README...")
|
|
111
|
-
|
|
112
|
-
# 在 contributors 区域的 </p> 前插入新贡献者头像
|
|
113
|
-
# README 中 contributors 区域格式:
|
|
114
|
-
# ### 贡献者
|
|
115
|
-
# <p align="left">
|
|
116
|
-
# <a href="..."><img .../></a> ...
|
|
117
|
-
# </p>
|
|
118
|
-
new_html_str = " " + " ".join(new_html_parts)
|
|
119
|
-
|
|
120
|
-
pattern = r'(### 贡献者.*?<p align="left">)(.*?)(</p>)'
|
|
121
|
-
|
|
122
|
-
def replacer(m):
|
|
123
|
-
existing_block = m.group(2).rstrip()
|
|
124
|
-
return m.group(1) + existing_block + new_html_str + "\n" + m.group(3)
|
|
125
|
-
|
|
126
|
-
updated_content = re.sub(pattern, replacer, readme_content, flags=re.DOTALL)
|
|
127
|
-
|
|
128
|
-
if updated_content == readme_content:
|
|
129
|
-
print("⚠️ 未找到 contributors 区域(### 贡献者 + <p align=\"left\">),跳过更新")
|
|
130
|
-
sys.exit(0)
|
|
131
|
-
|
|
132
|
-
with open("README.md", "w", encoding="utf-8") as f:
|
|
133
|
-
f.write(updated_content)
|
|
134
|
-
|
|
135
|
-
print("✅ README.md 已更新")
|
|
136
|
-
PYEOF
|
|
137
|
-
|
|
138
|
-
- name: Commit and push if changed
|
|
139
|
-
run: |
|
|
140
|
-
git config user.name "github-actions[bot]"
|
|
141
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
142
|
-
|
|
143
|
-
if git diff --quiet README.md; then
|
|
144
|
-
echo "✅ README.md 无变化,无需提交"
|
|
145
|
-
exit 0
|
|
146
|
-
fi
|
|
147
|
-
|
|
148
|
-
git add README.md
|
|
149
|
-
git commit -m "chore: 自动更新 README contributors [skip ci]"
|
|
150
|
-
git push origin main
|
|
151
|
-
echo "🚀 已推送更新到 main 分支"
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: yida-issue
|
|
3
|
-
description: 一句话给 OpenYida 提需求,自动判断路由到 openyida/openyida 还是 openyida/yida-skills,并创建格式规范的 GitHub Issue。触发词:给 OpenYida 提需求、提个 issue、报个 bug、希望支持 xxx、建议 xxx。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 一句话提需求
|
|
7
|
-
|
|
8
|
-
用自然语言描述需求,自动路由到正确仓库并创建 GitHub Issue。
|
|
9
|
-
|
|
10
|
-
## 路由规则
|
|
11
|
-
|
|
12
|
-
| 关键词/场景 | 目标仓库 |
|
|
13
|
-
|---|---|
|
|
14
|
-
| CLI、命令行、安装、CI/CD、贡献者、npm | `openyida/openyida` |
|
|
15
|
-
| 登录、创建应用/页面/表单、发布、Schema、宜搭 API | `openyida/yida-skills` |
|
|
16
|
-
| 无法判断 | 提示用户手动指定 `--repo` |
|
|
17
|
-
|
|
18
|
-
## 使用方式
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
node scripts/create-issue.js "<需求描述>" [--repo openyida|yida-skills] [--type feature|bug] [--dry-run]
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## 前置依赖
|
|
25
|
-
|
|
26
|
-
- Node.js ≥ 16
|
|
27
|
-
- GitHub CLI(`gh`)已安装并已登录(`gh auth login`)
|