mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
LLVM coverage jobs (Integration, Functional and Unit tests, amd_llvm_coverage)
run their coverage merge non-blocking: llvm-profdata can crash on a corrupt
.profraw and produce no .profdata, but the tests all pass and the job is meant
to stay green ("do not block pipeline").
Each such job also declares provides=[LLVM_COVERAGE_FILE_*] with path
./*.profdata. The praktika post-run upload treated a missing providing artifact
as a hard error and set the job to check_status=error even though 0 tests
failed. Observed on several PRs where job.log shows "Failed to create final
coverage file" (llvm-profdata crash) followed by "Failed to upload artifact
[LLVM_COVERAGE_FILE_it_N:./*.profdata]".
Add an optional flag to Artifact.Config. When a providing artifact marked
optional matches no file at upload time, skip it with a warning instead of
reddening the job. Mark the coverage profdata artifacts optional. The
downstream LLVM Coverage aggregation already globs whatever .profdata files
exist, so a missing batch is tolerated.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
import copy
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Dict, List, Union
|
|
|
|
|
|
class Artifact:
|
|
class Type:
|
|
GH = "github"
|
|
S3 = "s3"
|
|
PHONY = "phony"
|
|
|
|
@dataclass
|
|
class Config:
|
|
"""
|
|
name - artifact name
|
|
type - artifact type, see Artifact.Type
|
|
path - file path or glob, e.g. "path/**/[abc]rtifac?/*"
|
|
"""
|
|
|
|
name: str
|
|
type: str
|
|
path: Union[str, List[str]]
|
|
compress_zst: bool = False
|
|
# When True, a providing job whose output file(s) are missing at upload
|
|
# time does not fail. The job that already ran non-blocking (e.g. LLVM
|
|
# coverage merge) stays green; only the artifact is skipped. Consumers
|
|
# of an optional artifact must tolerate its absence.
|
|
optional: bool = False
|
|
_provided_by: str = ""
|
|
ext: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
def is_s3_artifact(self):
|
|
return self.type == Artifact.Type.S3
|
|
|
|
def parametrize(self, names):
|
|
res = []
|
|
for name in names:
|
|
obj = copy.deepcopy(self)
|
|
obj.name = name
|
|
res.append(obj)
|
|
return res
|
|
|
|
def add_tags(self, tags: Dict[str, str]):
|
|
"""
|
|
Add tags to the artifact. Only S3 artifacts support tags.
|
|
Returns a copy of the artifact with the tags added.
|
|
:param tags: Dictionary of tag key-value pairs
|
|
:return: A new Config object with the tags added
|
|
:raises ValueError: If artifact type is not S3
|
|
"""
|
|
if not self.is_s3_artifact():
|
|
raise ValueError(
|
|
f"Tags can only be added to S3 artifacts, but artifact type is [{self.type}]"
|
|
)
|
|
obj = copy.deepcopy(self)
|
|
if "tags" not in obj.ext:
|
|
obj.ext["tags"] = {}
|
|
obj.ext["tags"].update(tags)
|
|
return obj
|