From 12c67f71370c929d708feb93f963b343a6772a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 3 Jun 2026 19:22:14 +0800 Subject: [PATCH] chore(git-hooks): make pre-push checks non-blocking Replace the local pre-push quality gate with a reminder-only hook, keep manual quality commands documented, and update the contract test to prevent reintroducing a blocking push gate. Tested: bash .git/hooks/pre-push ` | Quick live provider/proxy and desktop agent-browser smoke when provider access exists. | | High-risk pre-merge confidence | `bun run quality:gate --mode baseline --allow-live --provider-model ` | Use for agent-loop, provider routing, model selection, tool execution, session resume, desktop chat, or other core Coding Agent paths. | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43f66176..c33b01f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ bun run verify `bun run verify` 会一键检查 policy、desktop、server、adapters、native、docs、quarantine 和 coverage。非 0 退出就说明当前分支还不能提交 PR。 -已安装本地 hook 的仓库在 `git push` 前会自动运行快速门禁 `bun run quality:push`;它复用 PR 门禁但默认跳过耗时的 coverage lane,完整覆盖率仍以 `bun run verify` 为准。 +`git push` 不再自动运行本地质量门禁。需要质量检查时请手动运行 `bun run quality:push` 或 `bun run verify`;完整覆盖率仍以 `bun run verify` 为准。 只改了某个模块时可以用窄命令快速迭代: diff --git a/docs/en/guide/contributing.md b/docs/en/guide/contributing.md index 3c62d499..4ba96e23 100644 --- a/docs/en/guide/contributing.md +++ b/docs/en/guide/contributing.md @@ -89,39 +89,35 @@ Every feature, bugfix, and behavior change must ship with verifiable evidence. T - Do not lower `coverage-baseline.json` or `coverage-thresholds.json` just to pass the gate; real baseline/threshold changes require `allow-coverage-baseline-change` and a reason. Legacy low-coverage areas are debt; new PRs must leave touched areas better than they found them. - The PR description must record changed files, tests added, coverage report path, E2E/live report path or blocker, and remaining risk. -## Local Pre-Push Gate +## Local Pre-Push Reminder -Git hooks are local, so each clone needs to install the hook once: +push no longer runs a local quality gate. Run checks manually when needed: + +```bash +bun run quality:push +``` + +`bun run quality:push` reuses the PR gate impact, policy, and path-aware checks, but skips the expensive coverage lane by default; full coverage remains in `bun run verify`, `bun run quality:pr`, and CI. + +You can still install the local pre-push hook, but it only prints a non-blocking reminder and never blocks `git push`: ```bash bun run hooks:install ``` -After installation, every `git push` runs the fast local gate internally (`bun run quality:push`). It reuses the PR gate impact, policy, and path-aware checks, but skips the expensive coverage lane by default; full coverage remains in `bun run verify`, `bun run quality:pr`, and CI. If unit tests, docs/native/adapter checks, or any other selected fast path-aware lane fails, the local hook blocks the push. - -Maintainers or contributors with model quota can also add real provider smoke and desktop agent-browser smoke to the pre-push hook: +Maintainers or contributors with model quota can run real provider smoke and desktop agent-browser smoke manually: ```bash bun run quality:providers -bun run hooks:install -- --live-provider-model minimax:main:minimax-main +bun run quality:smoke -- --provider-model minimax:main:minimax-main ``` -To run the full live baseline before every push, use: +To run the full live baseline, use: ```bash -bun run hooks:install -- --live-provider-model minimax:main:minimax-main --live-mode baseline +bun run quality:gate --mode baseline --allow-live --provider-model minimax:main:minimax-main ``` -These options are stored in local `.git/config` as `quality.prePush*` keys, so provider selectors and secrets are not committed. `smoke` mode covers real provider connectivity plus the desktop UI chat smoke; `baseline` mode also runs every real Coding Agent baseline case. - -Maintainer-level overrides must also be explicit local config before the hook passes them to `quality:push`: - -```bash -bun run hooks:install -- --allow-cli-core-change --allow-coverage-baseline-change -``` - -This only affects the current clone and is not committed; PR CI still requires the matching labels. - ## PR CI Merge Gate `.github/workflows/pr-quality.yml` runs for PR `opened`, `synchronize`, `reopened`, `ready_for_review`, `labeled`, and `unlabeled` events. It starts with `change-policy`, which maps changed files to the desktop, server, adapter, native, docs, and coverage lanes. The final `pr-quality-gate` job aggregates every selected job: failed selected jobs fail `pr-quality-gate`, while unselected jobs may be skipped. diff --git a/docs/guide/contributing.md b/docs/guide/contributing.md index 1f510d0e..4e8dc6e7 100644 --- a/docs/guide/contributing.md +++ b/docs/guide/contributing.md @@ -89,39 +89,35 @@ Agent 应按这个顺序处理失败: - 不要为了过门禁随便降低 `coverage-baseline.json` 或 `coverage-thresholds.json`;确实要改时必须有 `allow-coverage-baseline-change` 和原因。历史低覆盖区域是技术债,新 PR 至少要让触达区域更好。 - PR 描述必须写清楚:改了哪些文件、补了哪些测试、coverage 报告路径、E2E/live 报告路径或 blocker、剩余风险。 -## 本机 Push 前门禁 +## 本机 Push 前提醒 -Git hook 不能提交到远端自动生效,所以每个 clone 需要安装一次: +push 不再自动运行本地质量门禁。需要质量检查时,请手动运行: + +```bash +bun run quality:push +``` + +`bun run quality:push` 复用 PR gate 的 impact/policy/路径检查,但默认跳过耗时的 coverage lane;完整覆盖率仍保留在 `bun run verify`、`bun run quality:pr` 和 CI。 + +仍然可以安装本机 pre-push hook,但它只打印非阻塞提醒,不会卡住 `git push`: ```bash bun run hooks:install ``` -安装后,每次 `git push` 都会先运行快速本地门禁(内部是 `bun run quality:push`)。它复用 PR gate 的 impact/policy/路径检查,但默认跳过耗时的 coverage lane;完整覆盖率仍保留在 `bun run verify`、`bun run quality:pr` 和 CI。如果单元测试、文档/native/adapter 等按路径选中的快速门禁失败,push 会被本机 hook 阻断。 - -维护者或有模型额度的贡献者可以把真实 provider smoke 和桌面 agent-browser smoke 也纳入 push 前门禁: +维护者或有模型额度的贡献者可以手动运行真实 provider smoke 和桌面 agent-browser smoke: ```bash bun run quality:providers -bun run hooks:install -- --live-provider-model minimax:main:minimax-main +bun run quality:smoke -- --provider-model minimax:main:minimax-main ``` -需要每次 push 前跑完整 live baseline 时使用: +需要完整 live baseline 时使用: ```bash -bun run hooks:install -- --live-provider-model minimax:main:minimax-main --live-mode baseline +bun run quality:gate --mode baseline --allow-live --provider-model minimax:main:minimax-main ``` -这些选项写入本机 `.git/config` 的 `quality.prePush*` 配置,不会提交 provider selector 或密钥。`smoke` 模式覆盖真实 provider 连通性和桌面 UI 聊天 smoke;`baseline` 模式会额外跑全部真实 Coding Agent baseline case。 - -维护者级 override 也必须显式写入本机配置,hook 才会传给 `quality:push`: - -```bash -bun run hooks:install -- --allow-cli-core-change --allow-coverage-baseline-change -``` - -这只影响当前 clone,不会提交到仓库;PR 侧仍然需要对应 label。 - ## PR CI 合并门禁 `.github/workflows/pr-quality.yml` 会在 PR `opened`、`synchronize`、`reopened`、`ready_for_review`、`labeled`、`unlabeled` 时触发。流程先运行 `change-policy`,根据变更文件决定是否需要 desktop、server、adapter、native、docs 和 coverage lane。最后的 `pr-quality-gate` 会汇总所有被选中的 job:选中 job 失败则 `pr-quality-gate` 失败,未选中的 job 可以是 skipped。 diff --git a/scripts/git-hooks/install.ts b/scripts/git-hooks/install.ts index 577e2586..48d00b54 100755 --- a/scripts/git-hooks/install.ts +++ b/scripts/git-hooks/install.ts @@ -160,7 +160,7 @@ function parseArgs(argv: string[]): ParsedArgs { } function printHelp() { - console.log(`Install the repository pre-push quality gate. + console.log(`Install the repository non-blocking pre-push reminder. Usage: bun run hooks:install [-- --force] [-- --no-live] [-- --live-provider-model ] [-- --live-mode smoke|baseline] @@ -169,10 +169,10 @@ Usage: Examples: bun run hooks:install bun run hooks:install -- --no-live - bun run quality:providers - bun run hooks:install -- --live-provider-model codingplan:main:codingplan-main - bun run hooks:install -- --live-provider-model codingplan:main:codingplan-main --live-mode baseline bun run hooks:install -- --allow-cli-core-change --allow-coverage-baseline-change + +The installed hook never blocks git push. Run quality gates manually with +bun run quality:push, bun run verify, or the relevant narrow check. `) } @@ -195,20 +195,20 @@ if (import.meta.main) { live: args.live, }) - console.log(`Installed pre-push quality gate: ${result.hookPath}`) - console.log('Every git push now runs: bun run quality:push') - console.log('Coverage remains in bun run verify, quality:pr, and CI.') + console.log(`Installed non-blocking pre-push reminder: ${result.hookPath}`) + console.log('git push no longer runs local quality gates.') + console.log('Run checks manually with bun run quality:push, bun run verify, or the relevant narrow check.') if (args.liveProviderModels.length > 0) { - console.log(`Live ${args.liveMode ?? 'smoke'} gate is enabled for ${args.liveProviderModels.length} provider selector(s).`) + console.log(`Legacy live ${args.liveMode ?? 'smoke'} selector option was accepted, but pre-push is non-blocking and will not run it.`) } else if (args.live === false) { - console.log('Live model gate is disabled in local git config.') + console.log('Legacy live model gate config is disabled in local git config.') } else { - console.log('Live model gate is disabled. Enable it with --live-provider-model after running bun run quality:providers.') + console.log('Live model gates remain manual; use bun run quality:providers and bun run quality:smoke when needed.') } if (args.allowCliCoreChange || args.allowCoverageBaselineChange || args.allowMissingTests) { - console.log('Local maintainer override config was updated for this clone.') + console.log('Legacy local maintainer override config was updated for this clone.') } } catch (error) { console.error(error instanceof Error ? error.message : String(error)) diff --git a/scripts/git-hooks/pre-push b/scripts/git-hooks/pre-push index be2ba3f0..bd811378 100755 --- a/scripts/git-hooks/pre-push +++ b/scripts/git-hooks/pre-push @@ -1,73 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -git_config() { - git config --local --get "$1" 2>/dev/null || true -} +echo "[pre-push] non-blocking: git push no longer runs local quality gates." +echo "[pre-push] Run manually before PR/release work: bun run quality:push or bun run verify" -is_enabled() { - case "${1:-}" in - 1|true|TRUE|yes|YES|on|ON) - return 0 - ;; - *) - return 1 - ;; - esac -} - -echo "[pre-push] Running fast pre-push quality gate: bun run quality:push" - -if is_enabled "$(git_config quality.allowCliCoreChange)"; then - export ALLOW_CLI_CORE_CHANGE=1 -fi - -if is_enabled "$(git_config quality.allowMissingTests)"; then - export ALLOW_MISSING_TESTS=1 -fi - -if is_enabled "$(git_config quality.allowCoverageBaselineChange)"; then - export ALLOW_COVERAGE_BASELINE_CHANGE=1 -fi - -bun run quality:push - -live="${QUALITY_PRE_PUSH_LIVE:-$(git_config quality.prePushLive)}" - -if ! is_enabled "$live"; then - echo "[pre-push] Live model smoke is disabled. Configure it with: bun run hooks:install -- --live-provider-model " - exit 0 -fi - -provider_models="${QUALITY_PRE_PUSH_PROVIDER_MODELS:-${QUALITY_PRE_PUSH_PROVIDER_MODEL:-$(git_config quality.prePushProviderModels)}}" - -if [[ -z "${provider_models// }" ]]; then - echo "[pre-push] Live model smoke is enabled, but no provider selector is configured." - echo "[pre-push] Run: bun run quality:providers" - echo "[pre-push] Then: bun run hooks:install -- --live-provider-model " - exit 1 -fi - -live_mode="${QUALITY_PRE_PUSH_LIVE_MODE:-$(git_config quality.prePushLiveMode)}" -live_mode="${live_mode:-smoke}" - -case "$live_mode" in - smoke) - cmd=(bun run quality:smoke) - ;; - baseline) - cmd=(bun run quality:gate --mode baseline --allow-live) - ;; - *) - echo "[pre-push] Unsupported live mode: $live_mode" - echo "[pre-push] Use smoke or baseline." - exit 1 - ;; -esac - -for selector in $provider_models; do - cmd+=(--provider-model "$selector") -done - -echo "[pre-push] Running live $live_mode gate with configured provider selector(s)." -"${cmd[@]}" +exit 0 diff --git a/scripts/pr/quality-contract.test.ts b/scripts/pr/quality-contract.test.ts index b2d7b4b7..128c37d9 100644 --- a/scripts/pr/quality-contract.test.ts +++ b/scripts/pr/quality-contract.test.ts @@ -48,16 +48,21 @@ describe('feature quality contract', () => { expect(packageJson.scripts?.['check:native']).toContain('electron:package:dir') expect(packageJson.scripts?.['check:native']).toContain('test:package-smoke:current') expect(packageJson.scripts?.['test:package-smoke:current']).toBe('bun run scripts/quality-gate/package-smoke/current.ts') - expect(prePushHook).toContain('bun run quality:push') - expect(prePushHook).not.toContain('\nbun run quality:pr\n') + expect(prePushHook).toContain('non-blocking') + expect(prePushHook).not.toContain('\nbun run quality:push\n') + expect(prePushHook).not.toContain('quality:gate') + expect(prePushHook).not.toContain('quality:smoke') expect(contributing).toContain('bun run verify') expect(contributing).toContain('bun run quality:push') + expect(contributing).toContain('push 不再自动运行本地质量门禁') expect(contributing).toContain('AI Coding Agent 修复循环') expect(englishContributing).toContain('bun run verify') expect(englishContributing).toContain('bun run quality:push') + expect(englishContributing).toContain('push no longer runs a local quality gate') expect(englishContributing).toContain('AI Coding Agent Fix Loop') expect(rootContributing).toContain('bun run verify') expect(rootContributing).toContain('bun run quality:push') + expect(rootContributing).toContain('不再自动运行本地质量门禁') }) test('keeps desktop native CI aligned with Electron packaging', () => {