Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/hflow/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2716,22 +2716,53 @@ def render_contact_sheets(media_episode: Episode) -> EnrichmentResult:
continue
for artifact_name, artifact_path in enrichment_result.artifacts.items():
resolved_artifact_path = artifact_path.resolve()
# Artifact under scratch_dir is transient; stage it to artifacts/
# so the published URI remains valid across reprocess.
in_scratch = False
try:
artifact_relative_path = resolved_artifact_path.relative_to(run_dir.resolve())
artifact_key = artifact_relative_path.as_posix()
resolved_artifact_path.relative_to(scratch_dir.resolve())
in_scratch = True
except ValueError:
pass
if in_scratch:
step_directory = (
f"{_sanitize_topic(enrichment_run.enrichment.name)}-"
f"{enrichment_run.enrichment.version}"
)
artifact_name_digest = hashlib.sha256(artifact_name.encode()).hexdigest()[:8]
# Stage the artifact to a stable location within run_dir.
staging_dir = run_dir / "artifacts" / step_directory
staging_dir.mkdir(parents=True, exist_ok=True)
staged_artifact_path = staging_dir / artifact_path.name
if not staged_artifact_path.exists():
shutil.copy2(resolved_artifact_path, staged_artifact_path)
publish_path = staged_artifact_path
artifact_key = (
f"artifacts/{step_directory}/{_sanitize_topic(artifact_name)}-"
f"{artifact_name_digest}/{artifact_path.name}"
)
else:
try:
artifact_relative_path = resolved_artifact_path.relative_to(
run_dir.resolve()
)
artifact_key = artifact_relative_path.as_posix()
except ValueError:
step_directory = (
f"{_sanitize_topic(enrichment_run.enrichment.name)}-"
f"{enrichment_run.enrichment.version}"
)
artifact_name_digest = hashlib.sha256(artifact_name.encode()).hexdigest()[
:8
]
artifact_key = (
f"artifacts/{step_directory}/{_sanitize_topic(artifact_name)}-"
f"{artifact_name_digest}/{artifact_path.name}"
)
publish_path = artifact_path
try:
enrichment_run.artifact_uris[artifact_name] = run_storage_root.publish(
artifact_path, artifact_key
publish_path, artifact_key
)
except Exception as error:
# A missing or unreadable artifact file is the STEP's
Expand Down
5 changes: 4 additions & 1 deletion tests/test_camera_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ def test_camera_video_publishes_a_playable_mp4_per_camera_with_its_clock(
}
for topic in camera_topics:
published_mp4 = Path(video_run.artifact_uris[video_artifact_name(topic)])
# Published under the data root, not left in the scratch workdir.
# Published under the data root but NOT in the scratch workdir.
assert published_mp4.is_relative_to(data_root)
assert "scratch" not in published_mp4.parts, (
f"Artifact published under scratch: {published_mp4}"
)
assert published_mp4.suffix == ".mp4"
labels = video_run.result.labels
assert labels[f"{topic}/video_fps"] == pytest.approx(15.0, rel=0.05)
Expand Down