issuekit 0.1.5__tar.gz → 0.1.6__tar.gz
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.
- {issuekit-0.1.5 → issuekit-0.1.6}/LICENSE +21 -21
- {issuekit-0.1.5 → issuekit-0.1.6}/PKG-INFO +7 -5
- {issuekit-0.1.5 → issuekit-0.1.6}/README.md +5 -3
- {issuekit-0.1.5 → issuekit-0.1.6}/pyproject.toml +1 -1
- {issuekit-0.1.5 → issuekit-0.1.6}/scripts/release.sh +168 -168
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/__init__.py +1 -1
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/agent_skills.py +73 -55
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/agents/__init__.py +5 -5
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/agents/registry.py +52 -52
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/SKILL.md +379 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/agents/openai.yaml +3 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/automation-loop.md +36 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/contract-drift.md +26 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/data-isolation.md +46 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/database-evidence.md +57 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/domains/generic-domain.md +18 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/execution-context.md +90 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/failure-analysis.md +14 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/preparation-protocol.md +113 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/test-model.md +97 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/references/testcase-schema.md +122 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/scripts/validate_fixture_plan.py +62 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-business-test/scripts/validate_testcase_document.py +121 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-change/SKILL.md +59 -59
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-change/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-coding/SKILL.md +132 -132
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-coding/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-design/SKILL.md +117 -117
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-design/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-knowledge/SKILL.md +158 -158
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-knowledge/agents/openai.yaml +4 -4
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-merge/SKILL.md +74 -0
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-merge/agents/openai.yaml +4 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-release/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-require/SKILL.md +128 -128
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-require/agents/openai.yaml +4 -4
- issuekit-0.1.6/src/issuekit/bundled_skills/issuekit-review/SKILL.md +152 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-review/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-test/SKILL.md +79 -78
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-test/agents/openai.yaml +4 -4
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/cli.py +118 -118
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/commands/init.py +184 -191
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/commands/upgrade.py +57 -57
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/templates.py +17 -17
- issuekit-0.1.6/tests/test_agent_skills.py +41 -0
- issuekit-0.1.5/src/issuekit/bundled_skills/issuekit-review/SKILL.md +0 -89
- {issuekit-0.1.5 → issuekit-0.1.6}/.gitignore +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_skills/issuekit-release/SKILL.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_templates/code-review.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_templates/release-note.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_templates/requirement.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_templates/technical-design.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/bundled_templates/test-plan.md +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/commands/__init__.py +0 -0
- {issuekit-0.1.5 → issuekit-0.1.6}/src/issuekit/knowledge/__init__.py +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: issuekit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: AI 辅助开发的 Issue 全生命周期工具。从需求分析到代码审核,由你的 AI 编程助手驱动。
|
|
5
5
|
Project-URL: Homepage, https://github.com/xsg22/issue-kit
|
|
6
6
|
Project-URL: Repository, https://github.com/xsg22/issue-kit
|
|
@@ -44,9 +44,10 @@ IssueKit 为 AI 辅助开发提供结构化的工作流。它提供一组 Skills
|
|
|
44
44
|
| 4. 测试方案 | `$issuekit-test` | 黑盒业务测试 + 白盒单测/接口测试用例 |
|
|
45
45
|
| 5. 发布准备 | `$issuekit-release` | 生成发布文档,创建 Pull Request |
|
|
46
46
|
| 6. 代码审核 | `$issuekit-review` | 多维度交叉验证(需求、方案、质量) |
|
|
47
|
+
| 7. 代码合并 | `$issuekit-merge` | 理解改动背景,保全各分支有效能力,以门禁保障合并结果 |
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
另有 `$issuekit-knowledge` 生成项目上下文摘要、`$issuekit-change` 管理需求与方案变更,以及 `$issuekit-business-test` 设计并编排真实业务验收,共 10 个 Skill。
|
|
50
51
|
|
|
51
52
|
## 安装
|
|
52
53
|
|
|
@@ -116,6 +117,7 @@ AI 助手按技术文档的开发步骤逐步实现,完成后自动交叉校
|
|
|
116
117
|
$issuekit-test # 生成测试方案
|
|
117
118
|
$issuekit-release # 生成发布文档 + 创建 PR
|
|
118
119
|
$issuekit-review # 多维度代码审核
|
|
120
|
+
$issuekit-merge # 保全各分支有效能力,完成代码集成
|
|
119
121
|
```
|
|
120
122
|
|
|
121
123
|
## `init` 做了什么
|
|
@@ -130,7 +132,7 @@ $issuekit-review # 多维度代码审核
|
|
|
130
132
|
- Codex → `.agents/skills/`
|
|
131
133
|
- GitHub Copilot → `.github/skills/`
|
|
132
134
|
|
|
133
|
-
每个 Skill 包含 `SKILL.md
|
|
135
|
+
每个 Skill 包含 `SKILL.md`(指令),并按需携带 `references/`、`scripts/` 和 `assets/`;Codex 还会安装 `agents/openai.yaml` 元数据。
|
|
134
136
|
|
|
135
137
|
## 更新模板与 Skills(已 init 的项目)
|
|
136
138
|
|
|
@@ -201,4 +203,4 @@ issues/ # Issue 文档(默认目录,可通过 --issues
|
|
|
201
203
|
|
|
202
204
|
## 许可证
|
|
203
205
|
|
|
204
|
-
MIT
|
|
206
|
+
MIT
|
|
@@ -15,9 +15,10 @@ IssueKit 为 AI 辅助开发提供结构化的工作流。它提供一组 Skills
|
|
|
15
15
|
| 4. 测试方案 | `$issuekit-test` | 黑盒业务测试 + 白盒单测/接口测试用例 |
|
|
16
16
|
| 5. 发布准备 | `$issuekit-release` | 生成发布文档,创建 Pull Request |
|
|
17
17
|
| 6. 代码审核 | `$issuekit-review` | 多维度交叉验证(需求、方案、质量) |
|
|
18
|
+
| 7. 代码合并 | `$issuekit-merge` | 理解改动背景,保全各分支有效能力,以门禁保障合并结果 |
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
另有 `$issuekit-knowledge` 生成项目上下文摘要、`$issuekit-change` 管理需求与方案变更,以及 `$issuekit-business-test` 设计并编排真实业务验收,共 10 个 Skill。
|
|
21
22
|
|
|
22
23
|
## 安装
|
|
23
24
|
|
|
@@ -87,6 +88,7 @@ AI 助手按技术文档的开发步骤逐步实现,完成后自动交叉校
|
|
|
87
88
|
$issuekit-test # 生成测试方案
|
|
88
89
|
$issuekit-release # 生成发布文档 + 创建 PR
|
|
89
90
|
$issuekit-review # 多维度代码审核
|
|
91
|
+
$issuekit-merge # 保全各分支有效能力,完成代码集成
|
|
90
92
|
```
|
|
91
93
|
|
|
92
94
|
## `init` 做了什么
|
|
@@ -101,7 +103,7 @@ $issuekit-review # 多维度代码审核
|
|
|
101
103
|
- Codex → `.agents/skills/`
|
|
102
104
|
- GitHub Copilot → `.github/skills/`
|
|
103
105
|
|
|
104
|
-
每个 Skill 包含 `SKILL.md
|
|
106
|
+
每个 Skill 包含 `SKILL.md`(指令),并按需携带 `references/`、`scripts/` 和 `assets/`;Codex 还会安装 `agents/openai.yaml` 元数据。
|
|
105
107
|
|
|
106
108
|
## 更新模板与 Skills(已 init 的项目)
|
|
107
109
|
|
|
@@ -172,4 +174,4 @@ issues/ # Issue 文档(默认目录,可通过 --issues
|
|
|
172
174
|
|
|
173
175
|
## 许可证
|
|
174
176
|
|
|
175
|
-
MIT
|
|
177
|
+
MIT
|
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# PyPI 发布(纯 shell,不依赖额外 Python 发布脚本)
|
|
3
|
-
#
|
|
4
|
-
# 依赖:pip install -e ".[release]" ;凭据见 ~/.pypirc 或 TWINE_* 环境变量
|
|
5
|
-
#
|
|
6
|
-
# 用法:
|
|
7
|
-
# ./scripts/release.sh patch|minor|major # 升版并发布
|
|
8
|
-
# ./scripts/release.sh --set 1.0.0 # 指定版本并发布
|
|
9
|
-
# ./scripts/release.sh # 不升版,按当前版本构建并上传
|
|
10
|
-
# ./scripts/release.sh patch --dry-run --repository testpypi
|
|
11
|
-
#
|
|
12
|
-
set -euo pipefail
|
|
13
|
-
|
|
14
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
-
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
16
|
-
cd "$ROOT"
|
|
17
|
-
|
|
18
|
-
PYPROJECT="$ROOT/pyproject.toml"
|
|
19
|
-
INIT_PY="$ROOT/src/issuekit/__init__.py"
|
|
20
|
-
|
|
21
|
-
usage() {
|
|
22
|
-
cat <<'EOF'
|
|
23
|
-
PyPI 发布:./scripts/release.sh [patch|minor|major] [选项]
|
|
24
|
-
|
|
25
|
-
选项:
|
|
26
|
-
--set VERSION 指定版本(x.y.z)
|
|
27
|
-
--repository NAME pypi(默认)或 testpypi
|
|
28
|
-
--skip-tests 跳过 pytest
|
|
29
|
-
--dry-run 构建并检查,不上传
|
|
30
|
-
-h, --help 显示本说明
|
|
31
|
-
EOF
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
read_pyproject_version() {
|
|
35
|
-
grep -E '^version[[:space:]]*=' "$PYPROJECT" | head -1 \
|
|
36
|
-
| sed -E 's/^version[[:space:]]*=[[:space:]]*"([^"]*)".*/\1/'
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
write_versions() {
|
|
40
|
-
local v="$1"
|
|
41
|
-
local tmp
|
|
42
|
-
tmp="$(mktemp)"
|
|
43
|
-
sed "s/^version = \".*\"/version = \"${v}\"/" "$PYPROJECT" >"$tmp" && mv "$tmp" "$PYPROJECT"
|
|
44
|
-
tmp="$(mktemp)"
|
|
45
|
-
sed "s/^__version__[[:space:]]*=[[:space:]]*\".*\"/__version__ = \"${v}\"/" "$INIT_PY" >"$tmp" && mv "$tmp" "$INIT_PY"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
bump_semver() {
|
|
49
|
-
local ver="$1" kind="$2"
|
|
50
|
-
local major minor patch
|
|
51
|
-
if [[ ! "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
52
|
-
echo "无法自动升版(仅支持纯 x.y.z,请用 --set):$ver" >&2
|
|
53
|
-
exit 1
|
|
54
|
-
fi
|
|
55
|
-
IFS='.' read -r major minor patch <<<"$ver"
|
|
56
|
-
case "$kind" in
|
|
57
|
-
patch) patch=$((patch + 1)) ;;
|
|
58
|
-
minor) minor=$((minor + 1)); patch=0 ;;
|
|
59
|
-
major) major=$((major + 1)); minor=0; patch=0 ;;
|
|
60
|
-
*) echo "invalid bump: $kind" >&2; exit 1 ;;
|
|
61
|
-
esac
|
|
62
|
-
echo "${major}.${minor}.${patch}"
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
BUMP=""
|
|
66
|
-
SET_VERSION=""
|
|
67
|
-
REPOSITORY="pypi"
|
|
68
|
-
SKIP_TESTS=0
|
|
69
|
-
DRY_RUN=0
|
|
70
|
-
|
|
71
|
-
# 首参 patch|minor|major 快捷方式
|
|
72
|
-
if [[ "${1:-}" =~ ^(patch|minor|major)$ ]]; then
|
|
73
|
-
BUMP="$1"
|
|
74
|
-
shift
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
while [[ $# -gt 0 ]]; do
|
|
78
|
-
case "$1" in
|
|
79
|
-
--set)
|
|
80
|
-
SET_VERSION="${2:?--set 需要版本号}"
|
|
81
|
-
shift 2
|
|
82
|
-
;;
|
|
83
|
-
--repository)
|
|
84
|
-
REPOSITORY="${2:?--repository 需要 pypi 或 testpypi}"
|
|
85
|
-
shift 2
|
|
86
|
-
;;
|
|
87
|
-
--skip-tests) SKIP_TESTS=1; shift ;;
|
|
88
|
-
--dry-run) DRY_RUN=1; shift ;;
|
|
89
|
-
-h|--help) usage; exit 0 ;;
|
|
90
|
-
*)
|
|
91
|
-
echo "未知参数: $1" >&2
|
|
92
|
-
usage >&2
|
|
93
|
-
exit 1
|
|
94
|
-
;;
|
|
95
|
-
esac
|
|
96
|
-
done
|
|
97
|
-
|
|
98
|
-
if [[ -n "$BUMP" && -n "$SET_VERSION" ]]; then
|
|
99
|
-
echo "不要同时使用升版档位与 --set" >&2
|
|
100
|
-
exit 1
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
CURRENT="$(read_pyproject_version)"
|
|
104
|
-
NEW_VERSION=""
|
|
105
|
-
|
|
106
|
-
if [[ -n "$BUMP" ]]; then
|
|
107
|
-
NEW_VERSION="$(bump_semver "$CURRENT" "$BUMP")"
|
|
108
|
-
elif [[ -n "$SET_VERSION" ]]; then
|
|
109
|
-
if [[ ! "$SET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
110
|
-
echo "--set 仅支持 x.y.z 格式: $SET_VERSION" >&2
|
|
111
|
-
exit 1
|
|
112
|
-
fi
|
|
113
|
-
NEW_VERSION="$SET_VERSION"
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
if [[ -n "$NEW_VERSION" ]]; then
|
|
117
|
-
write_versions "$NEW_VERSION"
|
|
118
|
-
echo "Version: ${CURRENT} -> ${NEW_VERSION}"
|
|
119
|
-
else
|
|
120
|
-
echo "Version: ${CURRENT} (unchanged)"
|
|
121
|
-
fi
|
|
122
|
-
|
|
123
|
-
if [[ "$SKIP_TESTS" -eq 0 ]]; then
|
|
124
|
-
if ! python -c "import pytest" 2>/dev/null; then
|
|
125
|
-
echo "未检测到 pytest,正在安装发布依赖: pip install -e \".[release]\""
|
|
126
|
-
python -m pip install -q -e ".[release]"
|
|
127
|
-
fi
|
|
128
|
-
echo "+ python -m pytest"
|
|
129
|
-
# 退出码 5 = 未收集到测试(旧版 pytest 或未开 suppress_no_test_exit_code 时仍视为可继续发布)
|
|
130
|
-
set +e
|
|
131
|
-
python -m pytest
|
|
132
|
-
pytest_ec=$?
|
|
133
|
-
set -e
|
|
134
|
-
if [[ "$pytest_ec" -ne 0 && "$pytest_ec" -ne 5 ]]; then
|
|
135
|
-
exit "$pytest_ec"
|
|
136
|
-
fi
|
|
137
|
-
if [[ "$pytest_ec" -eq 5 ]]; then
|
|
138
|
-
echo "提示: pytest 未收集到任何测试(退出码 5),继续构建与上传。" >&2
|
|
139
|
-
fi
|
|
140
|
-
fi
|
|
141
|
-
|
|
142
|
-
echo "+ clean dist/build artifacts"
|
|
143
|
-
rm -rf dist build ./*.egg-info src/issuekit.egg-info 2>/dev/null || true
|
|
144
|
-
|
|
145
|
-
echo "+ python -m build"
|
|
146
|
-
python -m build
|
|
147
|
-
|
|
148
|
-
echo "+ twine check dist/*"
|
|
149
|
-
python -m twine check dist/*
|
|
150
|
-
|
|
151
|
-
# 使用 -r pypi|testpypi(勿用 --repository-url),Twine 才会按名称读取 ~/.pypirc 里对应段落及凭据
|
|
152
|
-
if [[ "$REPOSITORY" == "testpypi" ]]; then
|
|
153
|
-
TWINE_REPO=( -r testpypi )
|
|
154
|
-
else
|
|
155
|
-
TWINE_REPO=( -r pypi )
|
|
156
|
-
fi
|
|
157
|
-
|
|
158
|
-
VER_FOR_MSG="${NEW_VERSION:-$CURRENT}"
|
|
159
|
-
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
160
|
-
echo "+ (dry-run) skipping: python -m twine upload ${TWINE_REPO[*]} dist/*"
|
|
161
|
-
echo "Done (dry-run)."
|
|
162
|
-
exit 0
|
|
163
|
-
fi
|
|
164
|
-
|
|
165
|
-
echo "+ python -m twine upload ${TWINE_REPO[*]} dist/*"
|
|
166
|
-
python -m twine upload "${TWINE_REPO[@]}" dist/*
|
|
167
|
-
|
|
168
|
-
echo "Uploaded to ${REPOSITORY}. Verify: pip install issuekit==${VER_FOR_MSG}"
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PyPI 发布(纯 shell,不依赖额外 Python 发布脚本)
|
|
3
|
+
#
|
|
4
|
+
# 依赖:pip install -e ".[release]" ;凭据见 ~/.pypirc 或 TWINE_* 环境变量
|
|
5
|
+
#
|
|
6
|
+
# 用法:
|
|
7
|
+
# ./scripts/release.sh patch|minor|major # 升版并发布
|
|
8
|
+
# ./scripts/release.sh --set 1.0.0 # 指定版本并发布
|
|
9
|
+
# ./scripts/release.sh # 不升版,按当前版本构建并上传
|
|
10
|
+
# ./scripts/release.sh patch --dry-run --repository testpypi
|
|
11
|
+
#
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
16
|
+
cd "$ROOT"
|
|
17
|
+
|
|
18
|
+
PYPROJECT="$ROOT/pyproject.toml"
|
|
19
|
+
INIT_PY="$ROOT/src/issuekit/__init__.py"
|
|
20
|
+
|
|
21
|
+
usage() {
|
|
22
|
+
cat <<'EOF'
|
|
23
|
+
PyPI 发布:./scripts/release.sh [patch|minor|major] [选项]
|
|
24
|
+
|
|
25
|
+
选项:
|
|
26
|
+
--set VERSION 指定版本(x.y.z)
|
|
27
|
+
--repository NAME pypi(默认)或 testpypi
|
|
28
|
+
--skip-tests 跳过 pytest
|
|
29
|
+
--dry-run 构建并检查,不上传
|
|
30
|
+
-h, --help 显示本说明
|
|
31
|
+
EOF
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
read_pyproject_version() {
|
|
35
|
+
grep -E '^version[[:space:]]*=' "$PYPROJECT" | head -1 \
|
|
36
|
+
| sed -E 's/^version[[:space:]]*=[[:space:]]*"([^"]*)".*/\1/'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
write_versions() {
|
|
40
|
+
local v="$1"
|
|
41
|
+
local tmp
|
|
42
|
+
tmp="$(mktemp)"
|
|
43
|
+
sed "s/^version = \".*\"/version = \"${v}\"/" "$PYPROJECT" >"$tmp" && mv "$tmp" "$PYPROJECT"
|
|
44
|
+
tmp="$(mktemp)"
|
|
45
|
+
sed "s/^__version__[[:space:]]*=[[:space:]]*\".*\"/__version__ = \"${v}\"/" "$INIT_PY" >"$tmp" && mv "$tmp" "$INIT_PY"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
bump_semver() {
|
|
49
|
+
local ver="$1" kind="$2"
|
|
50
|
+
local major minor patch
|
|
51
|
+
if [[ ! "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
52
|
+
echo "无法自动升版(仅支持纯 x.y.z,请用 --set):$ver" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
IFS='.' read -r major minor patch <<<"$ver"
|
|
56
|
+
case "$kind" in
|
|
57
|
+
patch) patch=$((patch + 1)) ;;
|
|
58
|
+
minor) minor=$((minor + 1)); patch=0 ;;
|
|
59
|
+
major) major=$((major + 1)); minor=0; patch=0 ;;
|
|
60
|
+
*) echo "invalid bump: $kind" >&2; exit 1 ;;
|
|
61
|
+
esac
|
|
62
|
+
echo "${major}.${minor}.${patch}"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
BUMP=""
|
|
66
|
+
SET_VERSION=""
|
|
67
|
+
REPOSITORY="pypi"
|
|
68
|
+
SKIP_TESTS=0
|
|
69
|
+
DRY_RUN=0
|
|
70
|
+
|
|
71
|
+
# 首参 patch|minor|major 快捷方式
|
|
72
|
+
if [[ "${1:-}" =~ ^(patch|minor|major)$ ]]; then
|
|
73
|
+
BUMP="$1"
|
|
74
|
+
shift
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
while [[ $# -gt 0 ]]; do
|
|
78
|
+
case "$1" in
|
|
79
|
+
--set)
|
|
80
|
+
SET_VERSION="${2:?--set 需要版本号}"
|
|
81
|
+
shift 2
|
|
82
|
+
;;
|
|
83
|
+
--repository)
|
|
84
|
+
REPOSITORY="${2:?--repository 需要 pypi 或 testpypi}"
|
|
85
|
+
shift 2
|
|
86
|
+
;;
|
|
87
|
+
--skip-tests) SKIP_TESTS=1; shift ;;
|
|
88
|
+
--dry-run) DRY_RUN=1; shift ;;
|
|
89
|
+
-h|--help) usage; exit 0 ;;
|
|
90
|
+
*)
|
|
91
|
+
echo "未知参数: $1" >&2
|
|
92
|
+
usage >&2
|
|
93
|
+
exit 1
|
|
94
|
+
;;
|
|
95
|
+
esac
|
|
96
|
+
done
|
|
97
|
+
|
|
98
|
+
if [[ -n "$BUMP" && -n "$SET_VERSION" ]]; then
|
|
99
|
+
echo "不要同时使用升版档位与 --set" >&2
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
CURRENT="$(read_pyproject_version)"
|
|
104
|
+
NEW_VERSION=""
|
|
105
|
+
|
|
106
|
+
if [[ -n "$BUMP" ]]; then
|
|
107
|
+
NEW_VERSION="$(bump_semver "$CURRENT" "$BUMP")"
|
|
108
|
+
elif [[ -n "$SET_VERSION" ]]; then
|
|
109
|
+
if [[ ! "$SET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
110
|
+
echo "--set 仅支持 x.y.z 格式: $SET_VERSION" >&2
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
NEW_VERSION="$SET_VERSION"
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
if [[ -n "$NEW_VERSION" ]]; then
|
|
117
|
+
write_versions "$NEW_VERSION"
|
|
118
|
+
echo "Version: ${CURRENT} -> ${NEW_VERSION}"
|
|
119
|
+
else
|
|
120
|
+
echo "Version: ${CURRENT} (unchanged)"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
if [[ "$SKIP_TESTS" -eq 0 ]]; then
|
|
124
|
+
if ! python -c "import pytest" 2>/dev/null; then
|
|
125
|
+
echo "未检测到 pytest,正在安装发布依赖: pip install -e \".[release]\""
|
|
126
|
+
python -m pip install -q -e ".[release]"
|
|
127
|
+
fi
|
|
128
|
+
echo "+ python -m pytest"
|
|
129
|
+
# 退出码 5 = 未收集到测试(旧版 pytest 或未开 suppress_no_test_exit_code 时仍视为可继续发布)
|
|
130
|
+
set +e
|
|
131
|
+
python -m pytest
|
|
132
|
+
pytest_ec=$?
|
|
133
|
+
set -e
|
|
134
|
+
if [[ "$pytest_ec" -ne 0 && "$pytest_ec" -ne 5 ]]; then
|
|
135
|
+
exit "$pytest_ec"
|
|
136
|
+
fi
|
|
137
|
+
if [[ "$pytest_ec" -eq 5 ]]; then
|
|
138
|
+
echo "提示: pytest 未收集到任何测试(退出码 5),继续构建与上传。" >&2
|
|
139
|
+
fi
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
echo "+ clean dist/build artifacts"
|
|
143
|
+
rm -rf dist build ./*.egg-info src/issuekit.egg-info 2>/dev/null || true
|
|
144
|
+
|
|
145
|
+
echo "+ python -m build"
|
|
146
|
+
python -m build
|
|
147
|
+
|
|
148
|
+
echo "+ twine check dist/*"
|
|
149
|
+
python -m twine check dist/*
|
|
150
|
+
|
|
151
|
+
# 使用 -r pypi|testpypi(勿用 --repository-url),Twine 才会按名称读取 ~/.pypirc 里对应段落及凭据
|
|
152
|
+
if [[ "$REPOSITORY" == "testpypi" ]]; then
|
|
153
|
+
TWINE_REPO=( -r testpypi )
|
|
154
|
+
else
|
|
155
|
+
TWINE_REPO=( -r pypi )
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
VER_FOR_MSG="${NEW_VERSION:-$CURRENT}"
|
|
159
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
160
|
+
echo "+ (dry-run) skipping: python -m twine upload ${TWINE_REPO[*]} dist/*"
|
|
161
|
+
echo "Done (dry-run)."
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
echo "+ python -m twine upload ${TWINE_REPO[*]} dist/*"
|
|
166
|
+
python -m twine upload "${TWINE_REPO[@]}" dist/*
|
|
167
|
+
|
|
168
|
+
echo "Uploaded to ${REPOSITORY}. Verify: pip install issuekit==${VER_FOR_MSG}"
|
|
@@ -1,55 +1,73 @@
|
|
|
1
|
-
"""将 issuekit skills 安装到目标目录。
|
|
2
|
-
|
|
3
|
-
每个 skill 是一个独立目录,包含 SKILL.md。
|
|
4
|
-
Codex 额外需要 agents/openai.yaml 元数据文件。
|
|
5
|
-
源模板在 bundled_skills/
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from importlib import resources
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
SKILL_DIRS = [
|
|
12
|
-
"issuekit-require",
|
|
13
|
-
"issuekit-design",
|
|
14
|
-
"issuekit-coding",
|
|
15
|
-
"issuekit-test",
|
|
16
|
-
"issuekit-
|
|
17
|
-
"issuekit-
|
|
18
|
-
"issuekit-
|
|
19
|
-
"issuekit-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
1
|
+
"""将 issuekit skills 安装到目标目录。
|
|
2
|
+
|
|
3
|
+
每个 skill 是一个独立目录,包含 SKILL.md。
|
|
4
|
+
Codex 额外需要 agents/openai.yaml 元数据文件。
|
|
5
|
+
源模板在 bundled_skills/ 下,包含入口、元数据及可选的引用文档和脚本。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from importlib import resources
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
SKILL_DIRS = [
|
|
12
|
+
"issuekit-require",
|
|
13
|
+
"issuekit-design",
|
|
14
|
+
"issuekit-coding",
|
|
15
|
+
"issuekit-test",
|
|
16
|
+
"issuekit-business-test",
|
|
17
|
+
"issuekit-release",
|
|
18
|
+
"issuekit-review",
|
|
19
|
+
"issuekit-merge",
|
|
20
|
+
"issuekit-change",
|
|
21
|
+
"issuekit-knowledge",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _copy_skill_resources(source, destination: Path) -> None:
|
|
26
|
+
"""递归复制包内 Skill 资源,兼容 importlib 的资源接口。"""
|
|
27
|
+
destination.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
for item in source.iterdir():
|
|
29
|
+
target = destination / item.name
|
|
30
|
+
if item.is_dir():
|
|
31
|
+
_copy_skill_resources(item, target)
|
|
32
|
+
else:
|
|
33
|
+
target.write_bytes(item.read_bytes())
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def install_agent_skills(skills_dir: Path, *, include_openai_yaml: bool = False) -> int:
|
|
37
|
+
"""将所有 bundled skills 安装到目标目录,返回安装数。
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
skills_dir: 目标 skills 目录。
|
|
41
|
+
include_openai_yaml: 是否同时复制 agents/openai.yaml(仅 Codex 需要)。
|
|
42
|
+
"""
|
|
43
|
+
bundled = resources.files("issuekit") / "bundled_skills"
|
|
44
|
+
count = 0
|
|
45
|
+
|
|
46
|
+
for skill_name in SKILL_DIRS:
|
|
47
|
+
source_dir = bundled / skill_name
|
|
48
|
+
skill_md = source_dir / "SKILL.md"
|
|
49
|
+
if not skill_md.is_file():
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
dest_dir = skills_dir / skill_name
|
|
53
|
+
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
54
|
+
|
|
55
|
+
content = skill_md.read_text(encoding="utf-8")
|
|
56
|
+
(dest_dir / "SKILL.md").write_text(content, encoding="utf-8")
|
|
57
|
+
|
|
58
|
+
for resource_name in ("references", "scripts", "assets"):
|
|
59
|
+
resource_dir = source_dir / resource_name
|
|
60
|
+
if resource_dir.is_dir():
|
|
61
|
+
_copy_skill_resources(resource_dir, dest_dir / resource_name)
|
|
62
|
+
|
|
63
|
+
if include_openai_yaml:
|
|
64
|
+
openai_yaml = source_dir / "agents" / "openai.yaml"
|
|
65
|
+
if openai_yaml.is_file():
|
|
66
|
+
agents_dir = dest_dir / "agents"
|
|
67
|
+
agents_dir.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
yaml_content = openai_yaml.read_text(encoding="utf-8")
|
|
69
|
+
(agents_dir / "openai.yaml").write_text(yaml_content, encoding="utf-8")
|
|
70
|
+
|
|
71
|
+
count += 1
|
|
72
|
+
|
|
73
|
+
return count
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"""AI 助手适配层,支持不同编程助手的 Skills 安装。"""
|
|
2
|
-
|
|
3
|
-
from .registry import AGENT_REGISTRY, get_agent_config
|
|
4
|
-
|
|
5
|
-
__all__ = ["AGENT_REGISTRY", "get_agent_config"]
|
|
1
|
+
"""AI 助手适配层,支持不同编程助手的 Skills 安装。"""
|
|
2
|
+
|
|
3
|
+
from .registry import AGENT_REGISTRY, get_agent_config
|
|
4
|
+
|
|
5
|
+
__all__ = ["AGENT_REGISTRY", "get_agent_config"]
|