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
361 lines
13 KiB
Python
361 lines
13 KiB
Python
#!/usr/bin/env python
|
|
"""Unit tests for workflow_outputs.py."""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
sys.path.insert(0, os.fspath(Path(__file__).parent.parent))
|
|
|
|
from _therock_utils.workflow_outputs import WorkflowOutputRoot
|
|
from _therock_utils.storage_location import StorageLocation
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# StorageLocation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestStorageLocation(unittest.TestCase):
|
|
def test_s3_uri(self):
|
|
loc = StorageLocation("my-bucket", "12345-linux/file.tar.xz")
|
|
self.assertEqual(loc.s3_uri, "s3://my-bucket/12345-linux/file.tar.xz")
|
|
|
|
def test_https_url(self):
|
|
loc = StorageLocation("my-bucket", "12345-linux/file.tar.xz")
|
|
self.assertEqual(
|
|
loc.https_url,
|
|
"https://my-bucket.s3.amazonaws.com/12345-linux/file.tar.xz",
|
|
)
|
|
|
|
def test_local_path(self):
|
|
loc = StorageLocation("my-bucket", "12345-linux/logs/group/build.log")
|
|
result = loc.local_path(Path("/tmp/staging"))
|
|
expected = Path("/tmp/staging/12345-linux/logs/group/build.log")
|
|
self.assertEqual(result, expected)
|
|
|
|
def test_frozen(self):
|
|
loc = StorageLocation("bucket", "path")
|
|
with self.assertRaises(AttributeError):
|
|
loc.bucket = "other"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WorkflowOutputRoot — prefix
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestWorkflowOutputRootPrefix(unittest.TestCase):
|
|
def _make_root(self, **kwargs):
|
|
defaults = dict(
|
|
bucket="therock-ci-artifacts",
|
|
external_repo="",
|
|
run_id="12345",
|
|
platform="linux",
|
|
)
|
|
defaults.update(kwargs)
|
|
return WorkflowOutputRoot(**defaults)
|
|
|
|
def test_prefix_no_external_repo(self):
|
|
root = self._make_root()
|
|
self.assertEqual(root.prefix, "12345-linux")
|
|
|
|
def test_prefix_with_external_repo(self):
|
|
root = self._make_root(external_repo="Fork-TheRock/")
|
|
self.assertEqual(root.prefix, "Fork-TheRock/12345-linux")
|
|
|
|
def test_prefix_windows(self):
|
|
root = self._make_root(platform="windows")
|
|
self.assertEqual(root.prefix, "12345-windows")
|
|
|
|
def test_frozen(self):
|
|
root = self._make_root()
|
|
with self.assertRaises(AttributeError):
|
|
root.run_id = "99999"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WorkflowOutputRoot — location methods
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestWorkflowOutputRootLocations(unittest.TestCase):
|
|
"""Test that each location method returns correct relative paths."""
|
|
|
|
def setUp(self):
|
|
self.root = WorkflowOutputRoot(
|
|
bucket="therock-ci-artifacts",
|
|
external_repo="",
|
|
run_id="99999",
|
|
platform="linux",
|
|
)
|
|
|
|
def _assert_relative_path(self, loc: StorageLocation, expected_path: str):
|
|
self.assertIsInstance(loc, StorageLocation)
|
|
self.assertEqual(loc.bucket, "therock-ci-artifacts")
|
|
self.assertEqual(loc.relative_path, expected_path)
|
|
|
|
# -- Artifacts --
|
|
|
|
def test_artifact(self):
|
|
loc = self.root.artifact("blas_lib_gfx94X.tar.xz")
|
|
self._assert_relative_path(loc, "99999-linux/blas_lib_gfx94X.tar.xz")
|
|
|
|
def test_artifact_sha256sum(self):
|
|
loc = self.root.artifact("blas_lib_gfx94X.tar.xz.sha256sum")
|
|
self._assert_relative_path(loc, "99999-linux/blas_lib_gfx94X.tar.xz.sha256sum")
|
|
|
|
def test_artifact_index(self):
|
|
loc = self.root.artifact_index()
|
|
self._assert_relative_path(loc, "99999-linux/index.html")
|
|
|
|
# -- Logs --
|
|
|
|
def test_log_dir(self):
|
|
loc = self.root.log_dir("gfx94X-dcgpu")
|
|
self._assert_relative_path(loc, "99999-linux/logs/gfx94X-dcgpu")
|
|
|
|
def test_log_file(self):
|
|
loc = self.root.log_file("gfx94X-dcgpu", "build.log")
|
|
self._assert_relative_path(loc, "99999-linux/logs/gfx94X-dcgpu/build.log")
|
|
|
|
def test_log_file_ninja_archive(self):
|
|
loc = self.root.log_file("gfx94X-dcgpu", "ninja_logs.tar.gz")
|
|
self._assert_relative_path(
|
|
loc, "99999-linux/logs/gfx94X-dcgpu/ninja_logs.tar.gz"
|
|
)
|
|
|
|
def test_log_index(self):
|
|
loc = self.root.log_index("gfx94X-dcgpu")
|
|
self._assert_relative_path(loc, "99999-linux/logs/gfx94X-dcgpu/index.html")
|
|
|
|
def test_build_observability(self):
|
|
loc = self.root.build_observability("gfx94X-dcgpu")
|
|
self._assert_relative_path(
|
|
loc, "99999-linux/logs/gfx94X-dcgpu/build_observability.html"
|
|
)
|
|
|
|
# -- Stage logs (multi-arch CI) --
|
|
|
|
def test_log_stage_dir_per_arch(self):
|
|
loc = self.root.log_stage_dir("math-libs", "gfx1151")
|
|
self._assert_relative_path(loc, "99999-linux/logs/math-libs/gfx1151")
|
|
|
|
def test_log_stage_dir_generic(self):
|
|
loc = self.root.log_stage_dir("foundation")
|
|
self._assert_relative_path(loc, "99999-linux/logs/foundation")
|
|
|
|
def test_log_stage_dir_generic_empty_string(self):
|
|
loc = self.root.log_stage_dir("compiler-runtime", "")
|
|
self._assert_relative_path(loc, "99999-linux/logs/compiler-runtime")
|
|
|
|
# -- Manifests --
|
|
|
|
def test_manifest_dir(self):
|
|
loc = self.root.manifest_dir("gfx94X-dcgpu")
|
|
self._assert_relative_path(loc, "99999-linux/manifests/gfx94X-dcgpu")
|
|
|
|
def test_manifest(self):
|
|
loc = self.root.manifest("gfx94X-dcgpu")
|
|
self._assert_relative_path(
|
|
loc,
|
|
"99999-linux/manifests/gfx94X-dcgpu/therock_manifest.json",
|
|
)
|
|
|
|
# -- Python packages --
|
|
|
|
def test_python_packages(self):
|
|
loc = self.root.python_packages("gfx110X-all")
|
|
self._assert_relative_path(loc, "99999-linux/python/gfx110X-all")
|
|
|
|
def test_python_packages_no_artifact_group(self):
|
|
loc = self.root.python_packages()
|
|
self._assert_relative_path(loc, "99999-linux/python")
|
|
|
|
|
|
class TestWorkflowOutputRootLocationsExternalRepo(unittest.TestCase):
|
|
"""Verify external_repo prefix propagates through location methods."""
|
|
|
|
def test_artifact_with_external_repo(self):
|
|
root = WorkflowOutputRoot(
|
|
bucket="therock-ci-artifacts-external",
|
|
external_repo="Fork-TheRock/",
|
|
run_id="12345",
|
|
platform="windows",
|
|
)
|
|
loc = root.artifact("blas_lib_gfx110X.tar.zst")
|
|
self.assertEqual(
|
|
loc.relative_path,
|
|
"Fork-TheRock/12345-windows/blas_lib_gfx110X.tar.zst",
|
|
)
|
|
self.assertEqual(
|
|
loc.s3_uri,
|
|
"s3://therock-ci-artifacts-external/Fork-TheRock/12345-windows/blas_lib_gfx110X.tar.zst",
|
|
)
|
|
|
|
def test_log_dir_with_external_repo(self):
|
|
root = WorkflowOutputRoot(
|
|
bucket="therock-ci-artifacts-external",
|
|
external_repo="Fork-TheRock/",
|
|
run_id="12345",
|
|
platform="linux",
|
|
)
|
|
loc = root.log_dir("gfx94X-dcgpu")
|
|
self.assertEqual(
|
|
loc.relative_path,
|
|
"Fork-TheRock/12345-linux/logs/gfx94X-dcgpu",
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WorkflowOutputRoot — end-to-end (s3_uri, https_url, local_path via StorageLocation)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestStorageLocationEndToEnd(unittest.TestCase):
|
|
"""Verify the full chain: WorkflowOutputRoot → StorageLocation → final strings."""
|
|
|
|
def setUp(self):
|
|
self.root = WorkflowOutputRoot(
|
|
bucket="therock-ci-artifacts",
|
|
external_repo="",
|
|
run_id="42",
|
|
platform="linux",
|
|
)
|
|
|
|
def test_artifact_s3_uri(self):
|
|
self.assertEqual(
|
|
self.root.artifact("f.tar.xz").s3_uri,
|
|
"s3://therock-ci-artifacts/42-linux/f.tar.xz",
|
|
)
|
|
|
|
def test_artifact_https_url(self):
|
|
self.assertEqual(
|
|
self.root.artifact("f.tar.xz").https_url,
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/42-linux/f.tar.xz",
|
|
)
|
|
|
|
def test_artifact_local_path(self):
|
|
self.assertEqual(
|
|
self.root.artifact("f.tar.xz").local_path(Path("/s")),
|
|
Path("/s/42-linux/f.tar.xz"),
|
|
)
|
|
|
|
def test_manifest_s3_uri(self):
|
|
self.assertEqual(
|
|
self.root.manifest("gfx94X-dcgpu").s3_uri,
|
|
"s3://therock-ci-artifacts/42-linux/manifests/gfx94X-dcgpu/therock_manifest.json",
|
|
)
|
|
|
|
def test_log_index_https_url(self):
|
|
self.assertEqual(
|
|
self.root.log_index("gfx94X-dcgpu").https_url,
|
|
"https://therock-ci-artifacts.s3.amazonaws.com/42-linux/logs/gfx94X-dcgpu/index.html",
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WorkflowOutputRoot — factory methods
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestWorkflowOutputRootForLocal(unittest.TestCase):
|
|
def test_defaults(self):
|
|
root = WorkflowOutputRoot.for_local()
|
|
self.assertEqual(root.bucket, "local")
|
|
self.assertEqual(root.external_repo, "")
|
|
self.assertEqual(root.run_id, "local")
|
|
# Platform depends on system, just check it's set
|
|
self.assertIn(root.platform, ("linux", "windows", "darwin"))
|
|
|
|
def test_custom_values(self):
|
|
root = WorkflowOutputRoot.for_local(
|
|
run_id="test-42", platform="linux", bucket="test-bucket"
|
|
)
|
|
self.assertEqual(root.run_id, "test-42")
|
|
self.assertEqual(root.platform, "linux")
|
|
self.assertEqual(root.bucket, "test-bucket")
|
|
self.assertEqual(root.prefix, "test-42-linux")
|
|
|
|
|
|
class TestWorkflowOutputRootFromWorkflowRun(unittest.TestCase):
|
|
"""Test from_workflow_run() with mocked _retrieve_bucket_info."""
|
|
|
|
@mock.patch("_therock_utils.workflow_outputs._retrieve_bucket_info")
|
|
def test_basic_does_not_trigger_api(self, mock_retrieve):
|
|
"""By default, run_id is NOT passed as workflow_run_id."""
|
|
mock_retrieve.return_value = ("", "therock-ci-artifacts")
|
|
root = WorkflowOutputRoot.from_workflow_run(run_id="12345", platform="linux")
|
|
self.assertEqual(root.bucket, "therock-ci-artifacts")
|
|
self.assertEqual(root.external_repo, "")
|
|
self.assertEqual(root.run_id, "12345")
|
|
self.assertEqual(root.platform, "linux")
|
|
mock_retrieve.assert_called_once_with(
|
|
github_repository=None,
|
|
workflow_run_id=None,
|
|
workflow_run=None,
|
|
release_type=None,
|
|
)
|
|
|
|
@mock.patch("_therock_utils.workflow_outputs._retrieve_bucket_info")
|
|
def test_lookup_workflow_run_triggers_api(self, mock_retrieve):
|
|
"""With lookup_workflow_run=True, run_id IS passed as workflow_run_id."""
|
|
mock_retrieve.return_value = ("Fork-Repo/", "therock-ci-artifacts-external")
|
|
root = WorkflowOutputRoot.from_workflow_run(
|
|
run_id="99999",
|
|
platform="windows",
|
|
github_repository="SomeUser/TheRock",
|
|
lookup_workflow_run=True,
|
|
)
|
|
self.assertEqual(root.external_repo, "Fork-Repo/")
|
|
self.assertEqual(root.bucket, "therock-ci-artifacts-external")
|
|
mock_retrieve.assert_called_once_with(
|
|
github_repository="SomeUser/TheRock",
|
|
workflow_run_id="99999",
|
|
workflow_run=None,
|
|
release_type=None,
|
|
)
|
|
|
|
@mock.patch("_therock_utils.workflow_outputs._retrieve_bucket_info")
|
|
def test_with_workflow_run_dict(self, mock_retrieve):
|
|
"""When workflow_run is provided, it's passed through (no API call)."""
|
|
mock_retrieve.return_value = ("", "therock-ci-artifacts")
|
|
fake_run = {"id": 12345}
|
|
root = WorkflowOutputRoot.from_workflow_run(
|
|
run_id="12345",
|
|
platform="linux",
|
|
workflow_run=fake_run,
|
|
)
|
|
mock_retrieve.assert_called_once_with(
|
|
github_repository=None,
|
|
workflow_run_id=None,
|
|
workflow_run=fake_run,
|
|
release_type=None,
|
|
)
|
|
|
|
@mock.patch("_therock_utils.workflow_outputs._retrieve_bucket_info")
|
|
def test_lookup_ignored_when_workflow_run_provided(self, mock_retrieve):
|
|
"""lookup_workflow_run is irrelevant when workflow_run is provided."""
|
|
mock_retrieve.return_value = ("", "therock-ci-artifacts")
|
|
fake_run = {"id": 12345}
|
|
root = WorkflowOutputRoot.from_workflow_run(
|
|
run_id="12345",
|
|
platform="linux",
|
|
workflow_run=fake_run,
|
|
lookup_workflow_run=True,
|
|
)
|
|
# workflow_run_id is still None because workflow_run was provided
|
|
# directly — no API lookup needed.
|
|
mock_retrieve.assert_called_once_with(
|
|
github_repository=None,
|
|
workflow_run_id=None,
|
|
workflow_run=fake_run,
|
|
release_type=None,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|