mirror of
https://github.com/khodges42/nightShift.git
synced 2026-06-14 18:18:36 +00:00
68 lines
3.1 KiB
Python
68 lines
3.1 KiB
Python
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
|
|
from nightshift.artifacts import ArtifactStore
|
|
from nightshift.errors import ArtifactError
|
|
from nightshift.init import init_project
|
|
from nightshift.tasks import parse_task_file
|
|
|
|
|
|
class ArtifactStoreTests(unittest.TestCase):
|
|
def test_initialize_run_creates_base_artifact_tree(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
store = ArtifactStore(root, ".nightshift", run_id="test-run")
|
|
|
|
store.initialize_run()
|
|
|
|
self.assertTrue((root / ".nightshift").is_dir())
|
|
self.assertTrue((root / ".nightshift" / "project-context.md").exists())
|
|
self.assertTrue((root / ".nightshift" / "runs" / "test-run").is_dir())
|
|
self.assertTrue((root / ".nightshift" / "runs" / "test-run" / "tasks").is_dir())
|
|
self.assertTrue((root / ".nightshift" / "runs" / "test-run" / "run-summary.md").exists())
|
|
|
|
def test_writes_config_task_stage_and_final_artifacts(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
init_project(root)
|
|
task = parse_task_file(root, "tasks.md")[0]
|
|
store = ArtifactStore(root, ".nightshift", run_id="test-run")
|
|
|
|
config_path = store.write_config_snapshot(root / "nightshift.yaml")
|
|
task_path = store.write_task_snapshot(task)
|
|
stage_path = store.write_stage_output(task.id, "plan.md", "# Plan\n")
|
|
command_path = store.write_command_output(task.id, "test-output.txt", "ok\n")
|
|
notes_path = store.write_final_task_notes(task.id, "# Notes\n")
|
|
|
|
self.assertTrue(config_path.exists())
|
|
self.assertIn("project:", config_path.read_text(encoding="utf-8"))
|
|
self.assertTrue(task_path.exists())
|
|
self.assertIn(task.id, task_path.read_text(encoding="utf-8"))
|
|
self.assertEqual(stage_path.read_text(encoding="utf-8"), "# Plan\n")
|
|
self.assertEqual(command_path.read_text(encoding="utf-8"), "ok\n")
|
|
self.assertEqual(notes_path.read_text(encoding="utf-8"), "# Notes\n")
|
|
|
|
def test_stage_output_cannot_escape_task_directory(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
store = ArtifactStore(root, ".nightshift", run_id="test-run")
|
|
|
|
with self.assertRaisesRegex(ArtifactError, "escapes task directory"):
|
|
store.write_stage_output("TASK-001", "../leak.txt", "nope")
|
|
|
|
def test_run_id_and_task_id_must_be_safe_path_segments(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
|
|
with self.assertRaisesRegex(ArtifactError, "run id contains unsafe"):
|
|
ArtifactStore(root, ".nightshift", run_id="../run")
|
|
|
|
store = ArtifactStore(root, ".nightshift", run_id="safe-run")
|
|
with self.assertRaisesRegex(ArtifactError, "task id contains unsafe"):
|
|
store.create_task_dir("../TASK-001")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|