feat(ship): clarify delivery stop semantics

This commit is contained in:
2026-10-14 11:49:50 +08:00
parent 125bfe0c23
commit 19aac17a0a
8 changed files with 133 additions and 21 deletions
+58
View File
@@ -244,6 +244,64 @@ def _fill_task(ship_dir: Path) -> None:
class NextStepTests(unittest.TestCase):
def _prepare_delivery_dispatch(
self, root: Path, ship_id: str, stop_at: str, state: str
) -> None:
ship_dir = _create(root, ship_id, "short", stop_at=stop_at)
(ship_dir / "spec.md").write_text(FILLED_SPEC, encoding="utf-8")
_fill_task(ship_dir)
_patch_current(ship_dir, delivery_state=state)
data = safe_load((ship_dir / "current.yaml").read_text(encoding="utf-8"))
data["evidence"]["commits"] = [{"sha": "abc1234deadbeef", "role": "head"}]
(ship_dir / "current.yaml").write_text(safe_dump(data), encoding="utf-8")
def test_stop_at_mappings_cover_each_delivery_boundary(self) -> None:
cases = (
("develop_verified", "change_ready", "verify", "verified"),
("review_ready", "verified", "open_pr", "pr_opened"),
("release_ready", "merged", "regress", "regression_passed"),
("released", "artifact_built", "publish", "published"),
("deployed", "published", "deploy", "deployed"),
)
for stop_at, state, step, target in cases:
with self.subTest(stop_at=stop_at):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
ship_id = f"ship-{stop_at.replace('_', '-')}"
self._prepare_delivery_dispatch(root, ship_id, stop_at, state)
doc = _next(root, ship_id, "short")
self.assertEqual(doc["step"], step)
self.assertEqual(doc["targetState"], target)
def test_legacy_stop_at_names_resolve_to_new_boundaries(self) -> None:
cases = (
("verified", "change_ready", "verify", "verified"),
("validation_ready", "merged", "regress", "regression_passed"),
)
for stop_at, state, step, target in cases:
with self.subTest(stop_at=stop_at):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
ship_id = f"legacy-{stop_at.replace('_', '-')}"
self._prepare_delivery_dispatch(root, ship_id, stop_at, state)
doc = _next(root, ship_id, "short")
self.assertEqual(doc["step"], step)
self.assertEqual(doc["targetState"], target)
def test_invalid_stop_at_fails_ship_validation(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
result = _run(
CREATE,
"--project-root", str(root),
"--ship-id", "invalid-stop-at",
"--kind", "short",
"--title", "无效停止点",
"--stop-at", "not_a_stop_point",
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("stopAt 无效", result.stderr)
def test_new_short_ship_writes_spec(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)