Files
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

316 lines
13 KiB
Markdown

# CI Workflow Outputs Layout
This document describes the directory layout for outputs produced by TheRock's
CI workflow runs, and the Python modules for computing paths, uploading, and
downloading those outputs.
## Overview
Every CI workflow run produces a set of outputs (build artifacts, logs,
manifests, python packages) that are uploaded to S3. Three modules in
`_therock_utils` handle the path computation and I/O:
| Module | Role | Key types |
| ------------------ | ---------------------------- | ----------------------------------------------------------- |
| `storage_location` | Backend-agnostic location | `StorageLocation` |
| `workflow_outputs` | CI path computation (no I/O) | `WorkflowOutputRoot` |
| `storage_backend` | Upload I/O (write) | `StorageBackend`, `S3StorageBackend`, `LocalStorageBackend` |
| `artifact_backend` | Download I/O (read) | `ArtifactBackend`, `S3Backend`, `LocalDirectoryBackend` |
`StorageLocation` is the bridge between path computation and I/O.
`WorkflowOutputRoot` produces `StorageLocation` instances; backends consume them.
```
WorkflowOutputRoot ──produces──> StorageLocation ──consumed by──> StorageBackend
ArtifactBackend
```
## S3 Layout
All outputs for a given run live under a common prefix:
```
s3://{bucket}/{external_repo}{run_id}-{platform}/
```
| Component | Example | Description |
| --------------- | ------------------------------- | --------------------------------------------------------------------- |
| `bucket` | `therock-ci-artifacts` | Selected based on repo, fork status, release type |
| `external_repo` | `""` or `"githubuser-TheRock/"` | Non-empty for forks and non-TheRock repos (format: `{owner}-{repo}/`) |
| `run_id` | `12345678901` | GitHub Actions workflow run ID |
| `platform` | `linux` or `windows` | Build platform |
### Directory structure
There are two CI pipeline architectures with different log layouts:
- **Single-stage CI** (`ci.yml`) — one monolithic build per artifact group.
Logs from all subprojects land in a single flat directory.
- **Multi-arch CI** (`multi_arch_ci.yml`) — the build is split into stages
(compiler-runtime, runtime-tests, math-libs, etc.). Each stage runs as a
separate job and uploads its own logs, organized by stage name and GPU family.
`artifact_group` is the CI matrix variant, composed of a target family plus an
optional variant suffix (e.g., `gfx94X-dcgpu`, `gfx94X-dcgpu-asan`). It is
used as the subdirectory key for logs, manifests, and packages. Artifact
filenames contain the `target_family` (e.g., `gfx94X`); see
[#3381](https://github.com/ROCm/TheRock/issues/3381) for ongoing work to
propagate artifact group naming consistently.
#### Single-stage CI layout
```
{prefix}/
{artifact_name}_{component}_{target_family}.tar.xz
{artifact_name}_{component}_{target_family}.tar.xz.sha256sum
index-{artifact_group}.html
logs/{artifact_group}/
{subproject}_build.log
{subproject}_configure.log
{subproject}_install.log
ninja_logs.tar.gz
build_observability.html (when generated)
index.html
therock-build-prof/ (resource profiling subdirectory)
comp-summary.html
comp-summary.md
comp-summary.html (flattened copy for direct linking)
comp-summary.md (flattened copy for direct linking)
manifests/{artifact_group}/
therock_manifest.json
python/{artifact_group}/
*.whl
*.tar.gz
index.html
tarballs/
therock-dist-{platform}-{family}-{version}.tar.gz
```
The `comp-summary.*` files appear both in the `therock-build-prof/` subdirectory
(uploaded as part of the recursive directory upload) and at the log root
(uploaded explicitly for direct linking).
#### Multi-arch CI layout
Logs are organized by stage, with a subdirectory per GPU family for per-arch
stages. Generic stages (compiler-runtime, runtime-tests, profiler-apps) have no family
subdirectory. Per-arch stages (e.g., math-libs) fan out across GPU
families in parallel, producing identically-named log files (e.g.,
`rocBLAS_build.log`) that are kept separate by the family subdirectory.
```
{prefix}/
{artifact_name}_{component}_{target_family}.tar.zst
{artifact_name}_{component}_{target_family}.tar.zst.sha256sum
logs/{stage_name}/ (generic stages)
{subproject}_build.log
{subproject}_configure.log
{subproject}_install.log
ninja_logs.tar.gz
logs/{stage_name}/{amdgpu_family}/ (per-arch stages)
{subproject}_build.log
{subproject}_configure.log
{subproject}_install.log
ninja_logs.tar.gz
packages/deb/ (APT repository)
pool/main/
*.deb
dists/stable/
Release
main/binary-amd64/
Packages
Packages.gz
packages/rpm/ (DNF/Zypper repository)
x86_64/
*.rpm
repodata/
repomd.xml
primary.xml.gz
...
python/
*.whl (generic wheels, e.g., rocm_sdk_core)
{amdgpu_family}/
*.whl (per-family wheels, e.g., rocm_sdk_devel)
*.tar.gz (sdist)
index.html
tarballs/
therock-dist-{platform}-{family}-{version}.tar.gz
therock-dist-{platform}-multiarch-{version}.tar.gz (KPACK split only)
```
Example for a run with compiler-runtime + runtime-tests + math-libs stages:
```
12345-linux/
logs/compiler-runtime/
amd-llvm_build.log
amd-llvm_configure.log
amd-llvm_install.log
ninja_logs.tar.gz
logs/runtime-tests/
hip-tests_build.log
rocrtst_build.log
ninja_logs.tar.gz
logs/math-libs/gfx1151/
rocBLAS_build.log
MIOpen_build.log
ninja_logs.tar.gz
logs/math-libs/gfx110X-all/
rocBLAS_build.log
MIOpen_build.log
ninja_logs.tar.gz
```
Artifacts in multi-arch CI use `.tar.zst` compression (vs `.tar.xz` in
single-stage CI) and are managed by `artifact_manager.py`, not
`post_build_upload.py`. Index pages for logs are generated server-side.
### Bucket selection
The bucket is determined by `_retrieve_bucket_info()` in `workflow_outputs.py`.
See [S3 Buckets](s3_buckets.md) for the full list of buckets and authentication
details.
```
RELEASE_TYPE=dev/nightly/prerelease? ──Yes──> therock-{RELEASE_TYPE}-artifacts
│
No (RELEASE_TYPE=ci)
│
ROCm/TheRock (not fork)? ─────────────Yes──> therock-ci-artifacts
│
No
│
└──────────────────────────────────> therock-ci-artifacts-external
```
Valid artifact `RELEASE_TYPE` values are `ci`, `dev`, `nightly`, and
`prerelease`.
## Python API
### StorageLocation
A frozen dataclass representing a single file or directory in S3 (or a local
staging directory). Backend-agnostic — usable for CI run outputs, release
artifacts, or any S3 path.
```python
from _therock_utils.storage_location import StorageLocation
loc = StorageLocation(
bucket="therock-ci-artifacts", relative_path="12345-linux/file.tar.xz"
)
loc.s3_uri # "s3://therock-ci-artifacts/12345-linux/file.tar.xz"
loc.https_url # "https://therock-ci-artifacts.s3.amazonaws.com/12345-linux/file.tar.xz"
loc.local_path(Path("/tmp/staging")) # Path("/tmp/staging/12345-linux/file.tar.xz")
```
### WorkflowOutputRoot
A frozen dataclass that computes `StorageLocation` for every output type.
```python
from _therock_utils.workflow_outputs import WorkflowOutputRoot
# Inside a CI workflow (env vars provide bucket info, no API call)
root = WorkflowOutputRoot.from_workflow_run(run_id="12345", platform="linux")
# Fetching artifacts from another run (API call for fork/cutover detection)
root = WorkflowOutputRoot.from_workflow_run(
run_id="12345", platform="linux", lookup_workflow_run=True
)
# For local development (no API calls, no env vars needed)
root = WorkflowOutputRoot.for_local(run_id="local", platform="linux")
# Location methods — each returns an StorageLocation
root.root()
root.artifact(filename="blas_lib_gfx94X.tar.xz")
root.artifact_index()
root.log_dir(artifact_group="gfx94X-dcgpu")
root.log_stage_dir(stage_name="math-libs", amdgpu_family="gfx1151")
root.log_stage_dir(stage_name="compiler-runtime") # generic stage, no family
root.log_file(artifact_group="gfx94X-dcgpu", filename="build.log")
root.log_index(artifact_group="gfx94X-dcgpu")
root.build_observability(artifact_group="gfx94X-dcgpu")
root.manifest_dir(artifact_group="gfx94X-dcgpu")
root.manifest(artifact_group="gfx94X-dcgpu")
root.native_linux_packages(
pkg_type="deb"
) # {run_id}-linux/packages/deb — APT repo root
root.native_linux_packages(
pkg_type="rpm"
) # {run_id}-linux/packages/rpm — DNF/Zypper repo root
root.python_packages(artifact_group="gfx110X-all")
root.tarballs()
```
The `lookup_workflow_run` parameter controls whether `from_workflow_run()` calls
the GitHub API to fetch workflow run metadata (for fork detection and bucket
cutover dating). Most callers running inside their own CI workflow do not need
this — environment variables (`GITHUB_REPOSITORY`, `IS_PR_FROM_FORK`) suffice.
Set `lookup_workflow_run=True` when looking up another repository's workflow
run, e.g. when fetching artifacts.
### StorageBackend
An abstract base class for uploading files to S3 or a local directory.
Use `create_storage_backend()` to get the right implementation.
```python
from _therock_utils.storage_backend import create_storage_backend
backend = create_storage_backend() # S3 (default)
backend = create_storage_backend(staging_dir=Path("/tmp/out")) # local directory
backend = create_storage_backend(dry_run=True) # print only
backend.upload_file(source_path, dest_location)
backend.upload_directory(source_dir, dest_location, include=["*.tar.xz*"])
```
Content-type is inferred from file extension — callers don't need to specify it.
### Adding new output types
To add a new output type:
1. Add a method to `WorkflowOutputRoot` that returns `StorageLocation`
1. Add tests to [`build_tools/tests/workflow_outputs_test.py`](/build_tools/tests/workflow_outputs_test.py)
1. Update this document
## Consumers
### Upload scripts
| File | Uses |
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
| [`post_build_upload.py`](/build_tools/github_actions/post_build_upload.py) | `WorkflowOutputRoot` + `StorageBackend` for artifacts, logs, manifests |
| [`upload_package_repo.py`](/build_tools/packaging/linux/upload_package_repo.py) | `WorkflowOutputRoot.native_linux_packages()` for deb/rpm package repositories |
| [`post_stage_upload.py`](/build_tools/github_actions/post_stage_upload.py) | `WorkflowOutputRoot` + `StorageBackend` for multi-arch stage logs |
| [`upload_tarballs.py`](/build_tools/github_actions/upload_tarballs.py) | `WorkflowOutputRoot` + `StorageBackend` for tarballs |
| [`upload_python_packages.py`](/build_tools/github_actions/upload_python_packages.py) | `WorkflowOutputRoot` + `StorageBackend` for Python wheels and index |
| [`upload_pytorch_manifest.py`](/build_tools/github_actions/upload_pytorch_manifest.py) | `WorkflowOutputRoot` + `StorageBackend` for PyTorch manifests |
| [`upload_test_report_script.py`](/build_tools/github_actions/upload_test_report_script.py) | `WorkflowOutputRoot` for S3 base URI (upload not yet migrated to backend) |
### Download scripts
| File | Uses |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| [`fetch_artifacts.py`](/build_tools/fetch_artifacts.py) | `WorkflowOutputRoot.from_workflow_run(lookup_workflow_run=True)` + `S3Backend` |
| [`find_artifacts_for_commit.py`](/build_tools/find_artifacts_for_commit.py) | `WorkflowOutputRoot.from_workflow_run(workflow_run=...)` for bucket/prefix |
| [`artifact_backend.py`](/build_tools/_therock_utils/artifact_backend.py) | `WorkflowOutputRoot` for `S3Backend` construction |
| [`artifact_manager.py`](/build_tools/artifact_manager.py) | Via `create_backend_from_env()` |