feat(ship): clarify delivery stop semantics
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user