CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
295 lines
11 KiB
Python
295 lines
11 KiB
Python
#!/usr/bin/env python
|
|
"""Unit tests for post_build_upload.py upload functions.
|
|
|
|
Tests verify that the upload functions pass correct StorageLocations to the
|
|
StorageBackend, producing the expected file layout. Uses LocalStorageBackend
|
|
with a temp directory so no mocking of subprocess or boto3 is needed.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
# Add build_tools to path so _therock_utils is importable.
|
|
sys.path.insert(0, os.fspath(Path(__file__).parent.parent.parent))
|
|
# Add github_actions to path so post_build_upload is importable.
|
|
sys.path.insert(0, os.fspath(Path(__file__).parent.parent))
|
|
|
|
from _therock_utils.workflow_outputs import WorkflowOutputRoot
|
|
from _therock_utils.storage_backend import LocalStorageBackend
|
|
import post_build_upload
|
|
|
|
|
|
def _make_output_root(
|
|
run_id="12345",
|
|
platform="linux",
|
|
bucket="therock-ci-artifacts",
|
|
external_repo="",
|
|
):
|
|
return WorkflowOutputRoot(
|
|
bucket=bucket,
|
|
external_repo=external_repo,
|
|
run_id=run_id,
|
|
platform=platform,
|
|
)
|
|
|
|
|
|
class TestUploadLogs(unittest.TestCase):
|
|
"""Tests for upload_logs()."""
|
|
|
|
def test_uploads_log_files(self):
|
|
"""Verify log files end up at the correct paths; raw ccache excluded."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
log_dir = build_dir / "logs"
|
|
log_dir.mkdir()
|
|
(log_dir / "build.log").write_text("build output")
|
|
(log_dir / "ninja_logs.tar.gz").write_bytes(b"gzip")
|
|
(log_dir / "ccache_logs.tar.zst").write_bytes(b"compressed")
|
|
ccache_dir = log_dir / "ccache"
|
|
ccache_dir.mkdir()
|
|
(ccache_dir / "ccache.log").write_text("verbose trace")
|
|
|
|
backend = LocalStorageBackend(staging_dir)
|
|
post_build_upload.upload_logs(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
base = staging_dir / "12345-linux" / "logs" / "gfx94X-dcgpu"
|
|
self.assertTrue((base / "build.log").is_file())
|
|
self.assertTrue((base / "ninja_logs.tar.gz").is_file())
|
|
self.assertTrue((base / "ccache_logs.tar.zst").is_file())
|
|
self.assertFalse((base / "ccache" / "ccache.log").exists())
|
|
|
|
def test_build_observability_uploaded(self):
|
|
"""Verify build_observability.html ends up in the log directory."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
log_dir = build_dir / "logs"
|
|
log_dir.mkdir()
|
|
(log_dir / "build_observability.html").write_text("<html></html>")
|
|
|
|
backend = LocalStorageBackend(staging_dir)
|
|
post_build_upload.upload_logs(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
self.assertTrue(
|
|
(
|
|
staging_dir
|
|
/ "12345-linux"
|
|
/ "logs"
|
|
/ "gfx94X-dcgpu"
|
|
/ "build_observability.html"
|
|
).is_file()
|
|
)
|
|
|
|
def test_log_index_uploaded(self):
|
|
"""Verify log index.html ends up in the log directory."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
log_dir = build_dir / "logs"
|
|
log_dir.mkdir()
|
|
(log_dir / "index.html").write_text("<html></html>")
|
|
|
|
backend = LocalStorageBackend(staging_dir)
|
|
post_build_upload.upload_logs(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
self.assertTrue(
|
|
(
|
|
staging_dir / "12345-linux" / "logs" / "gfx94X-dcgpu" / "index.html"
|
|
).is_file()
|
|
)
|
|
|
|
def test_resource_profiler_flattened(self):
|
|
"""Verify resource profiler files are uploaded both in subdirectory and flattened."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
log_dir = build_dir / "logs"
|
|
prof_dir = log_dir / "therock-build-prof"
|
|
prof_dir.mkdir(parents=True)
|
|
(prof_dir / "comp-summary.html").write_text("<html></html>")
|
|
(prof_dir / "comp-summary.md").write_text("# Summary")
|
|
|
|
backend = LocalStorageBackend(staging_dir)
|
|
post_build_upload.upload_logs(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
base = staging_dir / "12345-linux" / "logs" / "gfx94X-dcgpu"
|
|
|
|
# Subdirectory copy (from upload_directory)
|
|
self.assertTrue(
|
|
(base / "therock-build-prof" / "comp-summary.html").is_file()
|
|
)
|
|
self.assertTrue((base / "therock-build-prof" / "comp-summary.md").is_file())
|
|
|
|
# Flattened copy (explicit upload_file calls)
|
|
self.assertTrue((base / "comp-summary.html").is_file())
|
|
self.assertTrue((base / "comp-summary.md").is_file())
|
|
|
|
def test_no_log_dir_skips(self):
|
|
"""Verify no uploads happen when log dir doesn't exist."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
backend = LocalStorageBackend(staging_dir)
|
|
# Should not raise
|
|
post_build_upload.upload_logs(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
|
|
class TestUploadManifest(unittest.TestCase):
|
|
"""Tests for upload_manifest()."""
|
|
|
|
def test_manifest_uploaded(self):
|
|
"""Verify manifest ends up at the correct path."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
manifest_dir = build_dir / "base" / "aux-overlay" / "build"
|
|
manifest_dir.mkdir(parents=True)
|
|
(manifest_dir / "therock_manifest.json").write_text("{}")
|
|
|
|
backend = LocalStorageBackend(staging_dir)
|
|
post_build_upload.upload_manifest(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
self.assertTrue(
|
|
(
|
|
staging_dir
|
|
/ "12345-linux"
|
|
/ "manifests"
|
|
/ "gfx94X-dcgpu"
|
|
/ "therock_manifest.json"
|
|
).is_file()
|
|
)
|
|
|
|
def test_missing_manifest_raises(self):
|
|
"""Verify FileNotFoundError when manifest doesn't exist."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as staging:
|
|
build_dir = Path(tmp)
|
|
staging_dir = Path(staging)
|
|
backend = LocalStorageBackend(staging_dir)
|
|
with self.assertRaises(FileNotFoundError):
|
|
post_build_upload.upload_manifest(
|
|
"gfx94X-dcgpu", build_dir, output_root, backend
|
|
)
|
|
|
|
|
|
class TestWriteGhaBuildSummary(unittest.TestCase):
|
|
"""Tests for write_gha_build_summary()."""
|
|
|
|
@mock.patch("post_build_upload.gha_append_step_summary")
|
|
def test_summary_with_observability(self, mock_summary):
|
|
"""Verify observability link included when the report exists."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
build_dir = Path(tmp)
|
|
log_dir = build_dir / "logs"
|
|
log_dir.mkdir()
|
|
(log_dir / "build_observability.html").write_text("<html></html>")
|
|
|
|
post_build_upload.write_gha_build_summary(
|
|
"gfx94X-dcgpu", build_dir, output_root, "success"
|
|
)
|
|
|
|
calls = [c[0][0] for c in mock_summary.call_args_list]
|
|
self.assertEqual(len(calls), 4) # logs, observability, artifacts, manifest
|
|
|
|
self.assertIn(
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/12345-linux/logs/gfx94X-dcgpu/index.html",
|
|
calls[0],
|
|
)
|
|
self.assertIn(
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/12345-linux/logs/gfx94X-dcgpu/build_observability.html",
|
|
calls[1],
|
|
)
|
|
self.assertIn(
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/12345-linux/index.html",
|
|
calls[2],
|
|
)
|
|
self.assertIn(
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/12345-linux/manifests/gfx94X-dcgpu/therock_manifest.json",
|
|
calls[3],
|
|
)
|
|
|
|
@mock.patch("post_build_upload.gha_append_step_summary")
|
|
def test_summary_without_observability(self, mock_summary):
|
|
"""Verify observability link omitted when the report was not generated."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
build_dir = Path(tmp)
|
|
|
|
post_build_upload.write_gha_build_summary(
|
|
"gfx94X-dcgpu", build_dir, output_root, "success"
|
|
)
|
|
|
|
calls = [c[0][0] for c in mock_summary.call_args_list]
|
|
self.assertEqual(len(calls), 3) # logs, artifacts, manifest
|
|
|
|
for call in calls:
|
|
self.assertNotIn("build_observability", call)
|
|
|
|
@mock.patch("post_build_upload.gha_append_step_summary")
|
|
def test_summary_failure_skips_artifacts(self, mock_summary):
|
|
"""Verify artifact link is skipped when job failed."""
|
|
output_root = _make_output_root()
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
build_dir = Path(tmp)
|
|
log_dir = build_dir / "logs"
|
|
log_dir.mkdir()
|
|
(log_dir / "build_observability.html").write_text("<html></html>")
|
|
|
|
post_build_upload.write_gha_build_summary(
|
|
"gfx94X-dcgpu", build_dir, output_root, "failure"
|
|
)
|
|
|
|
calls = [c[0][0] for c in mock_summary.call_args_list]
|
|
self.assertEqual(len(calls), 3) # logs, observability, manifest (no artifacts)
|
|
|
|
for call in calls:
|
|
self.assertNotIn("index-gfx94X-dcgpu.html", call)
|
|
self.assertNotIn("12345-linux/index.html", call)
|
|
|
|
@mock.patch("post_build_upload.gha_append_step_summary")
|
|
def test_summary_with_external_repo(self, mock_summary):
|
|
"""Verify external_repo prefix appears in summary URLs."""
|
|
output_root = _make_output_root(
|
|
external_repo="Fork-TheRock/",
|
|
bucket="therock-ci-artifacts-external",
|
|
)
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
build_dir = Path(tmp)
|
|
|
|
post_build_upload.write_gha_build_summary(
|
|
"gfx94X-dcgpu", build_dir, output_root, "success"
|
|
)
|
|
|
|
calls = [c[0][0] for c in mock_summary.call_args_list]
|
|
for call in calls:
|
|
self.assertIn("therock-ci-artifacts-external", call)
|
|
self.assertIn("Fork-TheRock/12345-linux", call)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|