repo-audit-tool 1.2.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/AGENTS.md +67 -0
- package/AUDIT.md +802 -0
- package/BEST-PRACTICES.md +268 -0
- package/CLAUDE.md +1 -0
- package/CONTRIBUTING.md +42 -0
- package/DEVELOPMENT.md +112 -0
- package/HANDOFF.md +124 -0
- package/LICENSE +21 -0
- package/PUBLISHING.md +66 -0
- package/README.en.md +71 -0
- package/README.md +71 -0
- package/REPO-AUDIT.md +107 -0
- package/REPO-CLASSIFICATION.md +137 -0
- package/SECURITY.md +19 -0
- package/docs/repo-audit/AGENT-GUIDE.md +474 -0
- package/docs/repo-audit/HUMAN-GUIDE.md +749 -0
- package/package.json +36 -0
- package/repo-audit.mjs +1507 -0
- package/rules/categories/archive.yaml +48 -0
- package/rules/categories/content.yaml +34 -0
- package/rules/categories/dsh-plugin.yaml +79 -0
- package/rules/categories/go-service.yaml +67 -0
- package/rules/categories/product-oss.yaml +75 -0
- package/rules/categories/python-app.yaml +60 -0
- package/rules/categories/sandbox.yaml +33 -0
- package/rules/domains/docs.yaml +105 -0
- package/rules/domains/git.yaml +52 -0
- package/rules/domains/quality.yaml +69 -0
- package/rules/domains/security.yaml +79 -0
- package/shim/repo-audit.cmd +7 -0
- package/shim/repo-audit.ps1 +4 -0
- package/shim/repo-audit.sh +5 -0
- package/templates/AGENT-GUIDE.md +331 -0
- package/templates/README.md +192 -0
- package/templates/UPDATE-MODEL.md +141 -0
- package/templates/UPDATE-PLAN.md +79 -0
- package/templates/categories/content/AGENTS-append.md +6 -0
- package/templates/categories/content/CATEGORY.md +26 -0
- package/templates/categories/content/README.en.md +12 -0
- package/templates/categories/content/README.md +14 -0
- package/templates/categories/content/gitignore-append.md +6 -0
- package/templates/categories/dsh-plugin/AGENTS-append.md +21 -0
- package/templates/categories/dsh-plugin/CATEGORY.md +9 -0
- package/templates/categories/dsh-plugin/CONTRIBUTING-append.md +22 -0
- package/templates/categories/dsh-plugin/DEVELOPMENT-append.md +71 -0
- package/templates/categories/dsh-plugin/PUBLISHING-append.md +53 -0
- package/templates/categories/dsh-plugin/README-append.md +28 -0
- package/templates/categories/dsh-plugin/README.en.md +44 -0
- package/templates/categories/dsh-plugin/gitignore-append.md +15 -0
- package/templates/categories/go-service/.githooks/pre-commit +13 -0
- package/templates/categories/go-service/.github/workflows/ci.yml +31 -0
- package/templates/categories/go-service/.github/workflows/release.yml +58 -0
- package/templates/categories/go-service/.goreleaser.yaml +86 -0
- package/templates/categories/go-service/AGENTS-append.md +7 -0
- package/templates/categories/go-service/CATEGORY.md +33 -0
- package/templates/categories/go-service/CONTRIBUTING-append.md +13 -0
- package/templates/categories/go-service/DEVELOPMENT-append.md +21 -0
- package/templates/categories/go-service/Makefile +21 -0
- package/templates/categories/go-service/PUBLISHING-append.md +48 -0
- package/templates/categories/go-service/PUBLISHING.md +59 -0
- package/templates/categories/go-service/README-append.md +26 -0
- package/templates/categories/go-service/README.en.md +43 -0
- package/templates/categories/go-service/gitignore-append.md +13 -0
- package/templates/categories/product-oss/.github/CODEOWNERS +6 -0
- package/templates/categories/product-oss/.github/ISSUE_TEMPLATE/bug_report.yml +52 -0
- package/templates/categories/product-oss/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/categories/product-oss/.github/dependabot.yml +28 -0
- package/templates/categories/product-oss/.github/workflows/dependency-review.yml +18 -0
- package/templates/categories/product-oss/.github/workflows/release-please.yml +39 -0
- package/templates/categories/product-oss/.release-please-manifest.json +3 -0
- package/templates/categories/product-oss/CATEGORY.md +27 -0
- package/templates/categories/product-oss/CHANGELOG.md +14 -0
- package/templates/categories/product-oss/PULL_REQUEST_TEMPLATE.md +15 -0
- package/templates/categories/product-oss/SUPPORT.md +71 -0
- package/templates/categories/product-oss/release-please-config.json +10 -0
- package/templates/categories/python-app/.githooks/pre-commit +13 -0
- package/templates/categories/python-app/.github/workflows/ci.yml +33 -0
- package/templates/categories/python-app/.github/workflows/publish.yml +112 -0
- package/templates/categories/python-app/AGENTS-append.md +18 -0
- package/templates/categories/python-app/CATEGORY.md +34 -0
- package/templates/categories/python-app/CONTRIBUTING-append.md +13 -0
- package/templates/categories/python-app/DEVELOPMENT-append.md +21 -0
- package/templates/categories/python-app/PUBLISHING-append.md +52 -0
- package/templates/categories/python-app/PUBLISHING.md +61 -0
- package/templates/categories/python-app/README-append.md +27 -0
- package/templates/categories/python-app/README.en.md +44 -0
- package/templates/categories/python-app/gitignore-append.md +19 -0
- package/templates/categories/python-app/pyproject.toml +41 -0
- package/templates/categories/python-app/scripts/verify.py +39 -0
- package/templates/categories/sandbox/AGENTS-append.md +7 -0
- package/templates/categories/sandbox/CATEGORY.md +31 -0
- package/templates/categories/sandbox/README.en.md +24 -0
- package/templates/categories/sandbox/README.md +23 -0
- package/templates/check-single-source.mjs +107 -0
- package/templates/common/AGENTS-core.md +28 -0
- package/templates/common/CONTRIBUTING-core.md +21 -0
- package/templates/common/DEVELOPMENT-core.md +45 -0
- package/templates/common/PUBLISHING-core.md +31 -0
- package/templates/common/README-core.md +60 -0
- package/templates/common/SECURITY-core.md +19 -0
- package/templates/common/copilot-instructions.md +5 -0
- package/templates/common/gitignore-core.md +11 -0
- package/templates/repo-root/.githooks/pre-commit +20 -0
- package/templates/repo-root/.github/workflows/ci.yml +45 -0
- package/templates/repo-root/.github/workflows/publish.yml +77 -0
- package/templates/repo-root/CLAUDE.md +3 -0
- package/templates/repo-root/LICENSE +21 -0
- package/templates/repo-root/package.json +71 -0
- package/templates/repo-root/scripts/build.mjs +24 -0
- package/templates/repo-root/scripts/check-deploy.mjs +176 -0
- package/templates/repo-root/scripts/verify.mjs +52 -0
- package/templates/repo-root/src/config.ts +25 -0
- package/templates/repo-root/src/index.ts +40 -0
- package/templates/repo-root/tsconfig.build.json +22 -0
- package/templates/repo-root/tsconfig.json +23 -0
- package/templates/scaffold.mjs +793 -0
- package/templates/skill/SKILL.md +47 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!-- 模板说明(用后删除):本文件是 B 类"产品/多人协作 OSS"分类共性文档(语言无关),
|
|
2
|
+
与语言基类(python-app / go-service / dsh-plugin)叠加使用。
|
|
3
|
+
语言基类管"怎么构建验证",本文件管"怎么协作发布"。
|
|
4
|
+
依据:docs.github.com(rulesets/merge queue/CODEOWNERS/issue forms/auto-merge)+
|
|
5
|
+
googleapis/release-please v5 + docs.pypi.org 安全模型,2026-09 核实。 -->
|
|
6
|
+
|
|
7
|
+
# 分类共性:产品级多人协作 OSS
|
|
8
|
+
|
|
9
|
+
> 实证特征:PR 流(Merge PR 实证)、CHANGELOG、ROADMAP、双语 README、评审/审计文档入库。
|
|
10
|
+
> 核心差异 vs 个人单维护者库:**变更经 PR、发布经 Release 流、事实经 CHANGELOG/release-please 单源**。
|
|
11
|
+
|
|
12
|
+
## 文件层(overlay 已随本目录提供,scaffold `--overlay product-oss` 自动叠加)
|
|
13
|
+
|
|
14
|
+
| 文件 | 作用 | 备注 |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `CHANGELOG.md` | 变更唯一事实源(Keep a Changelog 分类) | release-please 自动维护;手工模式则并入手写 |
|
|
17
|
+
| `.github/PULL_REQUEST_TEMPLATE.md` | PR 自检清单(验证链/机密/文档/兼容性) | — |
|
|
18
|
+
| `.github/ISSUE_TEMPLATE/bug_report.yml` + `config.yml` | YAML issue forms(复现步骤/环境)+ 私密漏洞报告指路 | blank_issues_enabled: false |
|
|
19
|
+
| `.github/CODEOWNERS` | 评审责任人锁定(自身必须有 owner) | 开 "Require review from Code Owners" 后任一 owner 批准即满足 |
|
|
20
|
+
| `.github/dependabot.yml` | 依赖与 action 自动升级(minor/patch 成组) | ecosystem 按语言基类增删 |
|
|
21
|
+
| `.github/workflows/release-please.yml` + `release-please-config.json` + `.release-please-manifest.json` | **版本晋升自动化**:conventional commits → 自动 Release PR → 合并即打 tag + GitHub Release + CHANGELOG | manifest 首版手写当前版本,此后勿手改 |
|
|
22
|
+
| `.github/workflows/dependency-review.yml` | PR 依赖安全审查(fail-on-severity: high 起步) | — |
|
|
23
|
+
|
|
24
|
+
## 发布分工(关键!避免撞车)
|
|
25
|
+
|
|
26
|
+
- **release-please** 管**版本晋升**:算 next version、开 Release PR、维护 CHANGELOG、合并时打 tag + 发 GitHub Release
|
|
27
|
+
- **语言基类的 publish/release 工作流**(npm OIDC / PyPI TP / GoReleaser)管**制品构建上传**,被 release-please 打的 tag 触发
|
|
28
|
+
- ⚠️ 不要让两边同时建 GitHub Release:GoReleaser 检测到 Release 已存在会更新(不撞车);npm/PyPI 的 pypa/npm publish 只传包不建 Release(不冲突)
|
|
29
|
+
- GITHUB_TOKEN 限制:release-please 用它建的事件不再触发其他 workflow——依赖 tag 触发发布(默认架构)就无需 PAT;要"Release PR 合并后直接 publish"才换 PAT
|
|
30
|
+
|
|
31
|
+
## 与单人库的红线差异
|
|
32
|
+
|
|
33
|
+
- 单人库"直提 main"的 pre-commit 门禁 → **PR 门禁**(ci.yml 必须 required check)
|
|
34
|
+
- pre-commit 部署纪律钩子仍随库分发;贡献者无法跑 check:deploy(无本机 profile)时 PR 说明注明,由维护者发版前代跑
|
|
35
|
+
|
|
36
|
+
## 单人直提 main → 多人 PR 协作:升级检查清单
|
|
37
|
+
|
|
38
|
+
> 来源:docs.github.com rulesets/protected-branches/merge queue/auto-merge 官方文档(2026-09 核实)。
|
|
39
|
+
> 分支保护建议用 **rulesets**(GitHub 演进方向:多 ruleset 叠加取最严、可 Evaluate/Active 启停、支持一键从 classic 保护迁移)。
|
|
40
|
+
|
|
41
|
+
### A. 仓库 General
|
|
42
|
+
1. Pull Requests:只留 **squash merging**;勾 **Automatically delete head branches**、**Allow auto-merge**
|
|
43
|
+
2. Actions → General:勾 **Allow GitHub Actions to create and approve pull requests**(release-please 必需)
|
|
44
|
+
3. Collaborators:协作者给 write 及以上(CODEOWNERS 与 required approvals 的前提)
|
|
45
|
+
|
|
46
|
+
### B. Rulesets(Settings → Rules → Rulesets → Branch ruleset,目标 `~DEFAULT_BRANCH`)
|
|
47
|
+
4. Require a pull request before merging:Required approvals = 1(≥2 人后升 2);勾 Dismiss stale approvals、Require review from Code Owners、Require conversation resolution
|
|
48
|
+
5. Require status checks:加入 CI check 名(**check 名须全局唯一**);初期勾 Require branches to be up to date(strict)
|
|
49
|
+
6. Require linear history(与 squash 配套)
|
|
50
|
+
7. Bypass list:加 `release-please[bot]`、`dependabot[bot]`;多人期给 admin 勾 **Do not allow bypassing**
|
|
51
|
+
8. 温和上线:先用 **Evaluate** 模式跑几天再切 Active
|
|
52
|
+
|
|
53
|
+
### C. 文件层
|
|
54
|
+
9. CODEOWNERS / ISSUE_TEMPLATE / dependabot.yml / release-please 三件套 / dependency-review.yml——overlay 已含
|
|
55
|
+
10. SECURITY.md + Settings → Code security → **Private vulnerability reporting**(与 SECURITY.md 是两套机制,都要有)
|
|
56
|
+
|
|
57
|
+
### D. 安全面默认
|
|
58
|
+
11. Secret scanning / push protection:公共仓免费,开启(push protection 对个人账号默认已拦截)
|
|
59
|
+
12. Dependabot alerts / security updates:公共仓默认开,确认即可
|
|
60
|
+
|
|
61
|
+
### E. 流程习惯(非配置)
|
|
62
|
+
13. Conventional Commits + commitlint CI 校验(release-please 的地基)
|
|
63
|
+
14. merge queue:**暂不开**——每天个位数 PR 用 strict required checks + auto-merge 足够;高频合并后再把规则 5 的 strict 换成 merge queue(避免双重等待)
|
|
64
|
+
|
|
65
|
+
### 补充事实(2026-09 核实)
|
|
66
|
+
|
|
67
|
+
- classic branch protection 仍可用,但官方提供一键 "Convert to ruleset" 迁移,新配置直接用 rulesets
|
|
68
|
+
- release-please-action 最新 **v5.0.0**(2026-04-22,breaking 仅 node24);核心库 release-please v17.11.2
|
|
69
|
+
- actions/stale v11 仍活跃维护;只对 issue 温和开启(days-before-pr-stale: -1 等价于不对 PR 启用)
|
|
70
|
+
- CODEOWNERS:gitignore 风格但不支持 `!` 取反与 `[ ]` 范围;owner 须 write 权限
|
|
71
|
+
- 0.x 阶段:config 里 `bump-minor-pre-major: true` 已预置(feat 只升 minor,避免 0.x 跳 1.x)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# 验证链前门(Python 版):提交时强制 ruff + pytest(scripts/verify.py 单源)。
|
|
3
|
+
# 启用方式:git config core.hooksPath .githooks
|
|
4
|
+
# 依赖:本地 venv 已激活或 python 环境含 ruff/pytest(未就绪时 --no-verify 并注明)。
|
|
5
|
+
|
|
6
|
+
echo "pre-commit:执行验证链 python3 scripts/verify.py ..."
|
|
7
|
+
python3 scripts/verify.py
|
|
8
|
+
code=$?
|
|
9
|
+
if [ $code -ne 0 ]; then
|
|
10
|
+
echo ""
|
|
11
|
+
echo "✗ 验证链 FAIL:修复后重试;确属中间态请 commit --no-verify 并在说明注明。"
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python CI(push/PR 验证)
|
|
2
|
+
#
|
|
3
|
+
# 验证链单源:scripts/verify.py(ruff → pytest 探测式)——本地与 CI 同一入口。
|
|
4
|
+
# 首推前置:无 lockfile 时首次安装生成 requirements 锁(如 pip-compile)再入库,可选。
|
|
5
|
+
name: ci
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
pull_request:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ci-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
verify:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@<commit-SHA> # actions/checkout@v7.0.1
|
|
25
|
+
- name: Setup Python
|
|
26
|
+
uses: actions/setup-python@<commit-SHA> # actions/setup-python@v6
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.12'
|
|
29
|
+
cache: pip
|
|
30
|
+
- name: Install
|
|
31
|
+
run: python -m pip install -e ".[dev]"
|
|
32
|
+
- name: Verify
|
|
33
|
+
run: python scripts/verify.py
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Python 发布工作流(PyPI Trusted Publishing)
|
|
2
|
+
#
|
|
3
|
+
# 信任链:tag v* → build job(版本守卫 + python -m build + twine check)→
|
|
4
|
+
# PyPI publish job(OIDC Trusted Publishing,自动 PEP 740 attestations)
|
|
5
|
+
# 要点(2026-09 官方文档核实):
|
|
6
|
+
# - 构建必须在独立 build job——PyPA guide 原话 "Building distributions in a publishing
|
|
7
|
+
# job is unsupported";publish job 只做"下载 artifact + 上传"
|
|
8
|
+
# - permissions 工作流级清零,id-token: write 只放 publish job(最小化)
|
|
9
|
+
# - TestPyPI 走 workflow_dispatch 手动触发(验证发布链路用;TestPyPI 独立账号+独立配置)
|
|
10
|
+
# - 不加 skip-existing:PyPI 禁文件名复用,且 release 14 天后冻结——失败换新版本号重发
|
|
11
|
+
# - attestations 默认开启,无需额外签名步骤
|
|
12
|
+
name: publish
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
tags: ['v*.*.*']
|
|
17
|
+
workflow_dispatch: {} # 手动触发时只发 TestPyPI(验证链路)
|
|
18
|
+
|
|
19
|
+
permissions: {}
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: publish-${{ github.ref }}
|
|
23
|
+
cancel-in-progress: false
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
name: 构建发行包(sdist + wheel)
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout
|
|
33
|
+
uses: actions/checkout@<commit-SHA> # actions/checkout@v7
|
|
34
|
+
with:
|
|
35
|
+
persist-credentials: false
|
|
36
|
+
- name: Setup Python
|
|
37
|
+
uses: actions/setup-python@<commit-SHA> # actions/setup-python@v7
|
|
38
|
+
with:
|
|
39
|
+
python-version: '3.12'
|
|
40
|
+
- name: 版本一致性守卫(tag ↔ pyproject.toml 静态版本)
|
|
41
|
+
run: |
|
|
42
|
+
python - <<'PY'
|
|
43
|
+
import os, re, sys, tomllib
|
|
44
|
+
tag = os.environ["GITHUB_REF_NAME"]
|
|
45
|
+
m = re.fullmatch(r"v(\d+(?:\.\d+)+(?:[.-]?[a-zA-Z0-9.]+)?)", tag)
|
|
46
|
+
if not m:
|
|
47
|
+
sys.exit(f"::error::tag '{tag}' 不符合 vX.Y.Z 约定")
|
|
48
|
+
expected = m.group(1)
|
|
49
|
+
with open("pyproject.toml", "rb") as f:
|
|
50
|
+
data = tomllib.load(f)
|
|
51
|
+
actual = data.get("project", {}).get("version")
|
|
52
|
+
if actual is None:
|
|
53
|
+
sys.exit("::error::pyproject.toml 无静态 version;动态版本请改用『构建后比对 dist 文件名』守卫(见下注释)")
|
|
54
|
+
if actual != expected:
|
|
55
|
+
sys.exit(f"::error::版本不一致:tag {tag} vs pyproject.toml {actual}")
|
|
56
|
+
print(f"版本一致:{actual}")
|
|
57
|
+
PY
|
|
58
|
+
# ▸ 动态版本(dynamic = ["version"])替代:移到 python -m build 之后,比对产物文件名:
|
|
59
|
+
# glob "dist/*-{GITHUB_REF_NAME[1:]}.tar.gz" 不存在即失败(最通用,绕开版本来源差异)
|
|
60
|
+
- name: 构建 sdist + wheel
|
|
61
|
+
run: |
|
|
62
|
+
python -m pip install --upgrade build
|
|
63
|
+
python -m build
|
|
64
|
+
- name: twine check(pypa action 上传前也会校验;此处尽早失败)
|
|
65
|
+
run: |
|
|
66
|
+
python -m pip install twine
|
|
67
|
+
python -m twine check dist/*
|
|
68
|
+
- name: 上传构建产物
|
|
69
|
+
uses: actions/upload-artifact@<commit-SHA> # actions/upload-artifact@v5
|
|
70
|
+
with:
|
|
71
|
+
name: python-package-distributions
|
|
72
|
+
path: dist/
|
|
73
|
+
|
|
74
|
+
publish-testpypi:
|
|
75
|
+
name: 发布到 TestPyPI(仅手动触发)
|
|
76
|
+
if: github.event_name == 'workflow_dispatch'
|
|
77
|
+
needs: build
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
environment:
|
|
80
|
+
name: testpypi
|
|
81
|
+
url: https://test.pypi.org/p/<name>
|
|
82
|
+
permissions:
|
|
83
|
+
id-token: write # Trusted Publishing 必需
|
|
84
|
+
steps:
|
|
85
|
+
- name: 下载构建产物
|
|
86
|
+
uses: actions/download-artifact@<commit-SHA> # actions/download-artifact@v6
|
|
87
|
+
with:
|
|
88
|
+
name: python-package-distributions
|
|
89
|
+
path: dist/
|
|
90
|
+
- name: 发布到 TestPyPI
|
|
91
|
+
uses: pypa/gh-action-pypi-publish@release/v1 # 2026-07 当前 v1.14.2;可 pin 到 tag/SHA
|
|
92
|
+
with:
|
|
93
|
+
repository-url: https://test.pypi.org/legacy/
|
|
94
|
+
|
|
95
|
+
publish-pypi:
|
|
96
|
+
name: 发布到 PyPI(tag 触发;environment 需配 required reviewers)
|
|
97
|
+
if: github.event_name == 'push'
|
|
98
|
+
needs: build
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
environment:
|
|
101
|
+
name: pypi # GitHub Settings → Environments:required reviewers 必开
|
|
102
|
+
url: https://pypi.org/p/<name>
|
|
103
|
+
permissions:
|
|
104
|
+
id-token: write # Trusted Publishing;attestations 默认生成
|
|
105
|
+
steps:
|
|
106
|
+
- name: 下载构建产物
|
|
107
|
+
uses: actions/download-artifact@<commit-SHA> # actions/download-artifact@v6
|
|
108
|
+
with:
|
|
109
|
+
name: python-package-distributions
|
|
110
|
+
path: dist/
|
|
111
|
+
- name: 发布到 PyPI(自动 PEP 740 attestations)
|
|
112
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!-- ===== append:python-app 分类纪律(拼接到 AGENTS-core 之后) ===== -->
|
|
2
|
+
|
|
3
|
+
## 环境与验证纪律(本分类硬性)
|
|
4
|
+
|
|
5
|
+
1. **环境声明**:一切命令在项目 venv 内执行(`python -m venv .venv && . .venv/bin/activate` 后 `pip install -e ".[dev]"`);不依赖全局解释器包状态。CI 与本地同命令(`scripts/verify.py` 单源)。
|
|
6
|
+
2. **提交前门**:`python scripts/verify.py`(ruff → pytest,探测式)全绿;pre-commit 钩子自动执行(启用:`git config core.hooksPath .githooks`)。
|
|
7
|
+
3. 数据文件入 `data/` 前先确认无敏感字段(机密红线见上方 AI 协作守则第 3 条)。
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
- (升级验证)guide 手册回归项。
|
|
13
|
+
|
|
14
|
+
6. (闭环实测)模板升级新条款。
|
|
15
|
+
|
|
16
|
+
7. (闭环实测 v2)第二轮升级。
|
|
17
|
+
|
|
18
|
+
6. (闭环终测)模板升级 A。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- 模板说明(用后删除):C 类"Python 应用/研究"分类 delta 模板(语言基类)。
|
|
2
|
+
叠加规则:repo-root 的**通用文档层**(README/LICENSE/CONTRIBUTING/DEVELOPMENT/PUBLISHING/
|
|
3
|
+
SECURITY/AGENTS/CLAUDE/.gitignore 基干 + skill/)照用;npm/TS 专属文件(package.json/
|
|
4
|
+
tsconfig*/src TS 骨架/scripts/*.mjs/workflows)由本分类替代。 -->
|
|
5
|
+
|
|
6
|
+
# C 类 · Python 应用/研究(语言基类)
|
|
7
|
+
|
|
8
|
+
> 实证来源:chumen / shisui / shuijing-v2 / vertical-small-model(pyproject + src/tests 同构)。
|
|
9
|
+
|
|
10
|
+
## 文件 delta(相对 repo-root 基类)
|
|
11
|
+
|
|
12
|
+
| 动作 | 文件 | 说明 |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| **替换** | `pyproject.toml`(本目录提供骨架) | 取代 package.json:PEP 621 元数据 + 工具配置单源 |
|
|
15
|
+
| **替换** | `src/<name>/__init__.py`(**自建**,TODO 有指引) | 取代 TS 骨架;src 布局,scaffold 不生成代码文件 |
|
|
16
|
+
| **替换** | `.github/workflows/ci.yml`、`publish.yml`(本目录提供) | pytest/ruff 验证链;publish 用 **PyPI Trusted Publishing(OIDC)**——与 npm 同信任链模型 |
|
|
17
|
+
| **删除** | package.json / tsconfig* / scripts/*.mjs / src/index.ts / cordis.patch.yml / dsh 字段 | npm/TS 专属 |
|
|
18
|
+
| **保留** | 通用文档层 + `.githooks/pre-commit` | 钩子内命令改为 `python -m pytest`(见本目录 pre-commit delta) |
|
|
19
|
+
|
|
20
|
+
## 验证链(对应 verify.mjs 的 Python 单源)
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
# scripts/verify.py(或 Makefile target):
|
|
24
|
+
ruff check . → python -m pytest tests/ -q
|
|
25
|
+
# 探测式:tests/ 存在才跑 pytest;deploy 场景(shuijing-v2)加 docker build 校验(本地前门,不进 CI)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 与 dsh 插件基类的红线差异
|
|
29
|
+
|
|
30
|
+
- **无部署纪律**(无 dsh profile/file: 安装)——AGENTS.md 去掉该 5 条,改为:venv/uv 环境声明、
|
|
31
|
+
`pip install -e ".[dev]"`、机密不入库(保留)、提交前 `ruff check + pytest`(保留)
|
|
32
|
+
- **发布面**:PUBLISHING.md 换成 PyPI 版(trusted publisher / 版本策略同款;无 npm provenance 概念,
|
|
33
|
+
用 PyPI "Trusted Publishing" + attestations)
|
|
34
|
+
- README 徽章换 PyPI / CI / License;安装段 `pip install <pkg>`
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!-- ===== append:python-app 分类段(拼接到 CONTRIBUTING-core 之后) ===== -->
|
|
2
|
+
|
|
3
|
+
## 开发环境
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
python -m venv .venv && . .venv/bin/activate
|
|
7
|
+
python -m pip install -e ".[dev]"
|
|
8
|
+
python scripts/verify.py # 验证链单源:ruff → pytest(探测式,tests/ 就位后自动进链)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 发版流程
|
|
12
|
+
|
|
13
|
+
见 [PUBLISHING.md](PUBLISHING.md)(bump-my-version 或手工 tag → PyPI Trusted Publishing 发布)。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- ===== append:python-app 分类段(拼接到 DEVELOPMENT-core 之后) ===== -->
|
|
2
|
+
|
|
3
|
+
## 分类纪律:Python 实现规范
|
|
4
|
+
|
|
5
|
+
- 包布局:src/(pyproject packages 已指向 `src/<name>`);入口逻辑收敛,测试放 `tests/`
|
|
6
|
+
- 类型与风格:ruff(E/F/I/UP/B)必须零告警;公共函数带类型注解
|
|
7
|
+
- 配置:schemastery 或 dataclass + 防御性解析(partial 配置也能得到完整结果,参照 src config 惯例)
|
|
8
|
+
- 提交前门:`python scripts/verify.py`(ruff → pytest,探测式)全绿;pre-commit 钩子已指向它
|
|
9
|
+
|
|
10
|
+
## 分类 DoD 补充(Python)
|
|
11
|
+
|
|
12
|
+
- [ ] ruff 零告警;pytest 全绿(tests/ 就位后自动进验证链)
|
|
13
|
+
- [ ] 发布前 `python -m build && twine check dist/*` 通过(如发布)
|
|
14
|
+
- [ ] 依赖变更同步 pyproject;lock(如用 uv/pip-compile)入库
|
|
15
|
+
|
|
16
|
+
## 速查表预置(回顾追加)
|
|
17
|
+
|
|
18
|
+
| 坑 | 症状 | 拦截环节 |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| 占位依赖没填就 npm/pip install | EINVALIDPACKAGENAME / Cannot find module | 脚手架 TODO 第 1 步 + CONTRIBUTING 首装提示 |
|
|
21
|
+
| 发布后改 pyproject version 不同步 tag | CI 版本守卫 FAIL | publish.yml 版本一致性守卫 |
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<!-- ===== append:python-app 分类段(拼接到 PUBLISHING-core 之后) ===== -->
|
|
2
|
+
|
|
3
|
+
## 发布通道(PyPI Trusted Publishing)
|
|
4
|
+
|
|
5
|
+
**认证**:PyPI **Trusted Publishing(OIDC)**——无 token,`id-token: write` 换发 15 分钟短命
|
|
6
|
+
项目 token;上传自动带 **PEP 740 attestations**(Sigstore,PyPI 项目页显示 provenance)。
|
|
7
|
+
**前置验证**:ci.yml(ruff → pytest)把住质量关;publish 只做构建与上传(build/publish 分离是
|
|
8
|
+
PyPA guide 硬要求)。
|
|
9
|
+
|
|
10
|
+
## 日常发布流程
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
# ① bump(版本静态在 pyproject.toml;推荐 bump-my-version 一条命令 commit+tag)
|
|
14
|
+
pip install bump-my-version
|
|
15
|
+
bump-my-version bump patch # 自动改 pyproject version + commit + 打 vX.Y.Z tag
|
|
16
|
+
# 或手工:改 pyproject.toml version → commit → git tag vX.Y.Z
|
|
17
|
+
|
|
18
|
+
# ② push(发布是人的决定:tag 推送触发 publish.yml)
|
|
19
|
+
git push && git push --tags # CI:构建守卫 → build → pypi 环境(人工批准)→ 上传
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- **守卫**:CI 比 tag 与 pyproject 静态 version 一致性(动态版本项目用 dist 文件名比对,见 publish.yml 注释)
|
|
23
|
+
- **灰度**:先 `workflow_dispatch` 手动跑 TestPyPI 验证链路;`pip install --index-url https://test.pypi.org/simple/` 实测
|
|
24
|
+
- **发布失败**:大声失败换新版本号重发——**不要**加 skip-existing(PyPI 禁文件名复用;release 14 天后冻结新文件)
|
|
25
|
+
|
|
26
|
+
## 首次发布前置(一次性)
|
|
27
|
+
|
|
28
|
+
1. **GitHub Environments**:建 `pypi`(**必开 required reviewers**——PyPA guide 强调每次运行都需
|
|
29
|
+
人工批准)与 `testpypi`
|
|
30
|
+
2. **pending publisher 登记**(先建配置后建项目):账号侧 `https://pypi.org/manage/account/publishing/`
|
|
31
|
+
填项目名 + owner/repo + workflow 文件名 `publish.yml` + environment `pypi`;首次发布成功自动建项目。
|
|
32
|
+
⚠️ pending 不保留项目名,发布前被抢注则失效。TestPyPI 单独重复(独立账号)
|
|
33
|
+
3. (建议)tag protection:限制 `v*` tag 只能由维护者推送
|
|
34
|
+
|
|
35
|
+
## 应急手动发布(CI 不可用时)
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
python scripts/verify.py && python -m build && twine check dist/*
|
|
39
|
+
# 需 API token 兜底(TP 不可用时):PyPI 账号建 API token(用户名 __token__),本地 twine upload dist/*
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 维护要点
|
|
43
|
+
|
|
44
|
+
- **offboarding 维护者**:审查 Trusted Publishers(TP 绑定项目而非用户)与 GitHub environment reviewers
|
|
45
|
+
- **版本工具**:小库推荐静态 pyproject + bump-my-version;setuptools-scm(tag 即真相源)tag 密集项目才值得
|
|
46
|
+
- **依赖更新**:Dependabot 保持 action 版本(含 pypa/gh-action-pypi-publish 的 release/v1 跟踪)
|
|
47
|
+
|
|
48
|
+
## 参考来源(2026-09 核实)
|
|
49
|
+
|
|
50
|
+
- docs.pypi.org/trusted-publishers/(含 security-model / creating-a-project-through-oidc)
|
|
51
|
+
- packaging.python.org GitHub Actions 发布指南 · pypa/gh-action-pypi-publish v1.14.2(master 已 sunset,用 @release/v1)
|
|
52
|
+
- blog.pypi.org(2025 年度回顾 / "14 天冻结"公告)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 发布记录:<repo>(Python / PyPI)
|
|
2
|
+
|
|
3
|
+
**发布通道**:PyPI **Trusted Publishing(OIDC)**——无 token,`id-token: write` 换发 15 分钟短命
|
|
4
|
+
项目 token;上传自动带 **PEP 740 attestations**(Sigstore,PyPI 项目页显示 provenance)。
|
|
5
|
+
**前置验证**:ci.yml(ruff → pytest)把住质量关;publish 只做构建与上传。
|
|
6
|
+
|
|
7
|
+
## 发布状态(<日期> 更新)
|
|
8
|
+
|
|
9
|
+
| 项 | 状态 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| PyPI | <版本 / latest> |
|
|
12
|
+
| TestPyPI | <测试通道验证记录> |
|
|
13
|
+
| 本地验证 | <verify.py 全绿 + pip install 实测> |
|
|
14
|
+
|
|
15
|
+
## 一次性前置(首次发布前)
|
|
16
|
+
|
|
17
|
+
1. **GitHub Environments**:Settings → Environments 建 `pypi`(**必开 required reviewers**——
|
|
18
|
+
PyPA guide 强调 "you must require manual approval on each run")与 `testpypi`
|
|
19
|
+
2. **pending publisher 登记**(先建配置后建项目):账号侧 `https://pypi.org/manage/account/publishing/`
|
|
20
|
+
填项目名 + owner/repo + workflow 文件名 `publish.yml` + environment `pypi`;首次发布成功自动建项目。
|
|
21
|
+
⚠️ pending 不保留项目名,发布前被抢注则失效。TestPyPI 在 test.pypi.org 单独重复(独立账号)
|
|
22
|
+
3. (建议)tag protection:限制 `v*` tag 只能由维护者推送
|
|
23
|
+
4. 本地演练:`python -m build && twine check dist/*`
|
|
24
|
+
|
|
25
|
+
## 日常发布流程
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
# ① bump(版本静态在 pyproject.toml;推荐 bump-my-version 一条命令 commit+tag)
|
|
29
|
+
pip install bump-my-version
|
|
30
|
+
bump-my-version bump patch # 自动改 pyproject version + commit + 打 vX.Y.Z tag
|
|
31
|
+
# 或手工:改 pyproject.toml version → commit → git tag vX.Y.Z
|
|
32
|
+
|
|
33
|
+
# ② push(发布是人的决定:tag 推送触发 publish.yml)
|
|
34
|
+
git push && git push --tags # CI:构建守卫 → build → TestPyPI 跳过 → pypi 环境(人工批准)→ 上传
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **守卫**:CI 比 tag 与 pyproject 静态 version 一致性(动态版本项目用 dist 文件名比对,见 publish.yml 注释)
|
|
38
|
+
- **灰度**:先 `workflow_dispatch` 手动跑 TestPyPI 验证链路;`pip install --index-url https://test.pypi.org/simple/` 实测
|
|
39
|
+
- **发布失败**:大声失败换新版本号重发——**不要**加 skip-existing(PyPI 禁文件名复用;release 14 天后冻结新文件)
|
|
40
|
+
- 发布成功验证:PyPI 项目页 provenance/attestations 徽章 + `pip install <pkg>` 实测
|
|
41
|
+
|
|
42
|
+
## 应急手动发布(CI 不可用时)
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
python scripts/verify.py && python -m build && twine check dist/*
|
|
46
|
+
# 需 API token 兜底(TP 不可用时):PyPI 账号建 API token(用户名 __token__),
|
|
47
|
+
# 本地 twine upload dist/* —— 上传后仍建议补跑一次 CI 发布以恢复 attestations 链路
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 维护要点
|
|
51
|
+
|
|
52
|
+
- **offboarding 维护者**:审查 Trusted Publishers(TP 绑定项目而非用户)与 GitHub environment reviewers
|
|
53
|
+
- **版本工具**:小库推荐静态 pyproject + bump-my-version;hatch version 适合动态版本(`__about__.py`);setuptools-scm(tag 即真相源)tag 密集项目才值得
|
|
54
|
+
- **依赖更新**:Dependabot 保持 action 版本(含 pypa/gh-action-pypi-publish 的 release/v1 跟踪)
|
|
55
|
+
|
|
56
|
+
## 参考来源(2026-09 核实)
|
|
57
|
+
|
|
58
|
+
- docs.pypi.org/trusted-publishers/(含 security-model / creating-a-project-through-oidc)
|
|
59
|
+
- packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/
|
|
60
|
+
- github.com/pypa/gh-action-pypi-publish(v1.14.2 README;master 已 sunset,用 @release/v1)
|
|
61
|
+
- blog.pypi.org(2025 年度回顾 / 2026-07 "14 天冻结"与 UI 更新公告)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!-- ===== append:python-app 分类段(拼接到 README-core 之后) ===== -->
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/<name>/)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
- <功能点 1:一句话说清用户得到什么>
|
|
8
|
+
- <功能点 2>
|
|
9
|
+
|
|
10
|
+
## 安装
|
|
11
|
+
|
|
12
|
+
> 要求 Python >= 3.11(见 pyproject.toml requires-python)。
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
pip install <name>
|
|
16
|
+
# 开发:python -m venv .venv && . .venv/bin/activate && pip install -e ".[dev]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 使用
|
|
20
|
+
|
|
21
|
+
<最小可复制示例:CLI 命令 / import 调用。示例代码块必须可直接粘贴执行。>
|
|
22
|
+
|
|
23
|
+
## 配置
|
|
24
|
+
|
|
25
|
+
| 配置项 | 默认 | 说明 |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `<field>` | `<default>` | <作用与生效方式(live / 重启生效)> |
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# <name>
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/<name>/)
|
|
4
|
+
|
|
5
|
+
<One-line English description>(与中文版 README 首句同义).
|
|
6
|
+
|
|
7
|
+
[中文](README.md) | English is a mirror; the Chinese README is authoritative and may lag behind.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- <Feature 1>
|
|
12
|
+
- <Feature 2>
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
> Requires Python >= 3.11 (see `requires-python` in pyproject.toml).
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pip install <name>
|
|
20
|
+
# Development: python -m venv .venv && . .venv/bin/activate && pip install -e ".[dev]"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
<Minimal copy-paste example: CLI command / import call.>
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
| Option | Default | Description |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `<field>` | `<default>` | <What it does; live or requires restart> |
|
|
32
|
+
|
|
33
|
+
## Docs
|
|
34
|
+
|
|
35
|
+
- [Design](docs/DESIGN.md) <!-- remove this line if no docs/ directory -->
|
|
36
|
+
- [Development & verification discipline](DEVELOPMENT.md) · [Publishing](PUBLISHING.md)
|
|
37
|
+
|
|
38
|
+
## Contributing
|
|
39
|
+
|
|
40
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). AI collaborators read [AGENTS.md](AGENTS.md) first (AI-collaboration rules).
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# ===== append:python-app 分类忽略(拼接到通用段之后) =====
|
|
2
|
+
|
|
3
|
+
# 本机私有钩子(commit-msg 含身份检查)不追踪;pre-commit 随仓库分发
|
|
4
|
+
.githooks/commit-msg
|
|
5
|
+
|
|
6
|
+
# Python
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
build/
|
|
12
|
+
dist/
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# <name>(Python)
|
|
2
|
+
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["hatchling"]
|
|
5
|
+
build-backend = "hatchling.build"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "<name>"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
description = "<一句话描述>"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "<org>" }]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
dependencies = [
|
|
15
|
+
# 运行时依赖按契约预检结果填
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
dev = [
|
|
20
|
+
"pytest>=8",
|
|
21
|
+
"ruff>=0.6",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/<org>/<repo>#readme"
|
|
26
|
+
Repository = "https://github.com/<org>/<repo>.git"
|
|
27
|
+
Issues = "https://github.com/<org>/<repo>/issues"
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["src/<name>"] # src 布局:包目录 src/<name>/(自建,含 __init__.py)
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
testpaths = ["tests"]
|
|
34
|
+
addopts = "-q"
|
|
35
|
+
|
|
36
|
+
[tool.ruff]
|
|
37
|
+
line-length = 100
|
|
38
|
+
target-version = "py311"
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint]
|
|
41
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""验证链单源入口(Python 版 verify.mjs):ruff → pytest(探测式)。
|
|
3
|
+
|
|
4
|
+
package 无构建期 npm 段;链内增删步骤只改本文件。
|
|
5
|
+
退出码:任一步 FAIL = 1(发布前门)。工具未安装时提示先建环境而非裸 traceback。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
14
|
+
|
|
15
|
+
steps = [["ruff", "check", "."]]
|
|
16
|
+
if (ROOT / "tests").exists():
|
|
17
|
+
# pytest 走 PATH 上的可执行(与 ruff 同源,venv 内一致);不用 sys.executable -m,
|
|
18
|
+
# 否则 PATH stub/隔离环境无法统一拦截
|
|
19
|
+
steps.append(["pytest", "tests/", "-q"])
|
|
20
|
+
# 探测式扩展点:deploy 校验(如 docker build)为本地发布前门,不进 CI——按需自行追加
|
|
21
|
+
|
|
22
|
+
# 工具可用性前置检查:缺工具 = SKIP 语义(exit 2,不阻塞 update 的 adopt/commit),
|
|
23
|
+
# 区别于"工具在但验证失败"(exit 1,阻塞)
|
|
24
|
+
missing = sorted({s[0] for s in steps if shutil.which(s[0]) is None and s[0] != sys.executable})
|
|
25
|
+
if missing:
|
|
26
|
+
print(f"△ 验证链工具未安装:{', '.join(missing)}——跳过门禁(SKIP)")
|
|
27
|
+
print(" → 先建环境:python -m venv .venv && . .venv/bin/activate && pip install -e \".[dev]\"")
|
|
28
|
+
sys.exit(2)
|
|
29
|
+
|
|
30
|
+
print(f"验证链(verify.py 单源):{' → '.join(s[0] for s in steps)}\n")
|
|
31
|
+
|
|
32
|
+
for step in steps:
|
|
33
|
+
r = subprocess.run(step, cwd=ROOT)
|
|
34
|
+
if r.returncode != 0:
|
|
35
|
+
print(f"\n✗ [FAIL] {step[0]}(exit {r.returncode})——验证链中断,禁止发布")
|
|
36
|
+
sys.exit(1)
|
|
37
|
+
print(f"✓ [PASS] {step[0]}")
|
|
38
|
+
|
|
39
|
+
print(f"\n验证链全绿({len(steps)} 步)。")
|