Skip to content

Migrate fetch_artifacts.py to use artifact_backend and artifact_manager#3019

Merged
ScottTodd merged 8 commits into
ROCm:mainfrom
ScottTodd:fetch-artifacts-backend
Feb 3, 2026
Merged

Migrate fetch_artifacts.py to use artifact_backend and artifact_manager#3019
ScottTodd merged 8 commits into
ROCm:mainfrom
ScottTodd:fetch-artifacts-backend

Conversation

@ScottTodd
Copy link
Copy Markdown
Member

@ScottTodd ScottTodd commented Jan 21, 2026

Motivation

While working on #3000, I found that this code is directly handling S3 paths like so:

    def __post_init__(self):
        self.s3_key_path = f"{self.external_repo}{self.workflow_run_id}-{self.platform}"

I'm trying to move that code to a central location and to make it possible to swap out the "s3 cloud backend for a "local backend" for easier testing. Moving string manipulation code is easy enough, but this file also directly communicated with S3:

          log(f"++ Downloading {artifact_key} to {output_path}")
          with open(output_path, "wb") as f:
              s3_client.download_fileobj(bucket, artifact_key, f)

That would be harder to refactor... if we didn't already have this abstraction in ArtifactBackend. So, I'm first migrating this code to use that class.

Technical Details

I also considered making fetch_artifacts.py just call artifact_manager.py directly, but they have different roles:

  • artifact_manager.py is topology-aware and is currently just used for multi-arch builds
  • fetch_artifacts.py has regex-based fetching and is currently used by developers to fetch explicit lists of artifacts and by CI workflows to download subsets of artifacts for tests

Test Plan

  • Existing unit tests (light coverage)
  • Manual sanity check:
    python ./build_tools/fetch_artifacts.py ^
      --run-id=18480879899 ^
      --artifact-group=gfx110X-dgpu ^
      --output-dir=%HOME%\.therock\18480879899\artifacts
  • CI test jobs will run this fetch_artifacts.py script indirectly via build_tools/install_rocm_from_artifacts.py

Test Result

  • CI jobs run the script with no issues, e.g. https://github.com/ROCm/TheRock/actions/runs/21192582915/job/60969434096?pr=3019#step:6:280

    Calling fetch_artifacts_main with args:
      --run-id 21192582915 --artifact-group gfx94X-dcgpu --output-dir build --flatten core-hipinfo_run core-runtime_run core-runtime_lib sysdeps_lib base_run base_lib amd-llvm_run amd-llvm_lib core-hip_lib core-hip_dev core-ocl_lib core-ocl_dev rocprofiler-sdk_lib host-suite-sparse_lib blas_lib blas_test
    
    ...
    
    ++ Flattening 'blas_test_gfx94X-dcgpu.tar.xz' to 'blas_test_gfx94X-dcgpu'
    ++ Flattening 'blas_lib_gfx94X-dcgpu.tar.xz' to 'blas_lib_gfx94X-dcgpu'
    Retrieved artifacts for run ID 21192582915
    

Submission Checklist

ScottTodd and others added 6 commits January 20, 2026 15:34
Refactors fetch_artifacts.py to use the ArtifactBackend interface instead
of directly accessing S3 implementation details. This improves separation
of concerns and makes the code more testable.

Changes:
- Remove BucketMetadata class (duplicated S3Backend path construction)
- Remove module-level S3 client (now uses backend.s3_client internally)
- Update list_s3_artifacts() to use S3Backend.list_artifacts()
- Update ArtifactDownloadRequest to use generic ArtifactBackend type
- Simplify download_artifact() to use backend.download_artifact() API
- Add retry logic (3 retries, exponential backoff) to S3Backend.download_artifact()
- Update tests to mock S3Backend instead of raw paginator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Makes the function fully backend-agnostic by:
- Renaming from list_s3_artifacts to list_artifacts_for_group
- Changing type hint from S3Backend to ArtifactBackend
- Simplifying logging to use backend.base_uri instead of S3-specific attributes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removes duplicate download logic from fetch_artifacts.py by reusing
existing code from artifact_manager.py which already has retry logic.

Changes:
- Remove ArtifactDownloadRequest class (use artifact_manager.DownloadRequest)
- Remove local download_artifact() function (use artifact_manager.download_artifact)
- Rename get_artifact_download_requests() to get_download_requests()
- Update extract_artifact() to take Path instead of request object
- Revert retry logic from S3Backend.download_artifact() (not needed now)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This test was mocking the backend to raise ClientError, then verifying
that list_artifacts_for_group() propagates the exception. Since there's
no exception handling in that function, this was just testing that
Python propagates exceptions - not useful.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ScottTodd
Copy link
Copy Markdown
Member Author

Ping?

Comment thread build_tools/tests/fetch_artifacts_test.py Outdated
Comment thread build_tools/fetch_artifacts.py
@ScottTodd ScottTodd merged commit ab58222 into ROCm:main Feb 3, 2026
70 of 71 checks passed
@ScottTodd ScottTodd deleted the fetch-artifacts-backend branch February 3, 2026 02:28
@github-project-automation github-project-automation Bot moved this from TODO to Done in TheRock Triage Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants