Close trial task cards and keep long histories visible
Why: pipefail treated a recent merged-card match as a failed git log after grep exited early, hiding completed cards from precheck and task-close. Evidence: A disposable long-history regression failed before the fix and passed after it; make test-governance passed 341 cases. Git history confirms PR #489/#488/#486 merge SHAs. Impact: Detect merged cards reliably and archive only the three authorized trial cards; four unrelated eligible cards remain untouched. Refs: Dev merge queue #518; Dev #489, #488, #486
This commit is contained in:
+4
-2
@@ -57,7 +57,9 @@ cmd_precheck() {
|
||||
pb=$(card_of_branch "$pc"); [ -n "$pb" ] || continue
|
||||
pst=$(card_status "$pc"); case "$pst" in 已完成*) continue ;; esac
|
||||
card_pending "${pc##*/}" && continue
|
||||
if git log --merges --format='%s' "origin/${TARGET_BRANCH}" 2>/dev/null | grep -qF " from $pb into ${TARGET_BRANCH}"; then
|
||||
# Consume the complete producer output: grep -q exits on the first match,
|
||||
# making git log die with SIGPIPE (141 under pipefail) on long histories.
|
||||
if git log --merges --format='%s' "origin/${TARGET_BRANCH}" 2>/dev/null | grep -F " from $pb into ${TARGET_BRANCH}" >/dev/null; then
|
||||
open_cards="${open_cards} ${pc##*/}"
|
||||
fi
|
||||
done
|
||||
@@ -379,7 +381,7 @@ card_of_branch() { sed -n 's/^- 工作区:.*分支:\([A-Za-z0-9._/-]\+\).*/\
|
||||
card_status() { sed -n 's/^.*;状态:\([^;]*\).*/\1/p' "$1" | head -1; }
|
||||
card_merge() { # $1=branch → "sha|subject"(该分支合入 origin/<target> 的合并提交)
|
||||
git log --merges --format='%H|%s' "origin/${TARGET_BRANCH}" 2>/dev/null \
|
||||
| grep -F " from $1 into ${TARGET_BRANCH}" | head -1
|
||||
| grep -F " from $1 into ${TARGET_BRANCH}" | sed -n '1p'
|
||||
}
|
||||
card_pending() { # $1=卡片文件名——闭合是否已在某 origin/feature/card-close-* 分支待合入
|
||||
local cb
|
||||
|
||||
@@ -758,6 +758,35 @@ class TaskLifecycleTests(unittest.TestCase):
|
||||
self.git(publisher, "push", "origin", "main")
|
||||
return self.git(publisher, "rev-parse", "HEAD").stdout.strip(), card.read_text()
|
||||
|
||||
def test_long_merge_history_keeps_merged_card_visible_and_closable(self):
|
||||
# A recent match makes grep -q/head exit before git log has finished
|
||||
# writing a large history. With pipefail, its SIGPIPE used to hide the
|
||||
# card from precheck and leave task-close with nothing to archive.
|
||||
base = self.git(self.repo, "rev-parse", "HEAD").stdout.strip()
|
||||
tree = self.git(self.repo, "rev-parse", "HEAD^{tree}").stdout.strip()
|
||||
side = self.git(self.repo, "commit-tree", tree, "-p", base,
|
||||
"-m", "Fixture side commit").stdout.strip()
|
||||
tip = base
|
||||
for i in range(220):
|
||||
tip = self.git(self.repo, "commit-tree", tree, "-p", tip, "-p", side,
|
||||
"-m", f"Older fixture merge {i} " + "x" * 512).stdout.strip()
|
||||
self.git(self.repo, "update-ref", "refs/heads/main", tip)
|
||||
self.git(self.repo, "push", "origin", "main")
|
||||
actual_merge, _ = self.publish_merged_task()
|
||||
self.git(self.repo, "fetch", "origin")
|
||||
self.git(self.repo, "merge", "--ff-only", "origin/main")
|
||||
|
||||
precheck = self.task(self.repo, "precheck")
|
||||
self.assertIn("[cards] 已合入未闭合任务卡:feature-merged.md", precheck.stdout)
|
||||
closed = self.task(self.repo, "close")
|
||||
self.assertIn("[closed] 1 张已合入卡片", closed.stdout)
|
||||
refs = self.git(self.repo, "for-each-ref", "--format=%(refname:short)",
|
||||
"refs/heads/feature/card-close-*").stdout.splitlines()
|
||||
self.assertEqual(len(refs), 1)
|
||||
archived = self.git(self.repo, "show", f"{refs[0]}:.task/archive/feature-merged.md").stdout
|
||||
self.assertIn("状态:已完成(回填)", archived)
|
||||
self.assertIn(actual_merge, archived)
|
||||
|
||||
def assert_post_merge_only_reminds_owner(self, operation):
|
||||
expected_head, expected_card = self.publish_merged_task()
|
||||
self.git(self.repo, "fetch", "origin")
|
||||
|
||||
Reference in New Issue
Block a user