Coverage for /builds/svesch/cikit/src/cikit/macros/bundle.py: 96%
36 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-09 14:17 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-09 14:17 +0000
1# SPDX-License-Identifier: GPL-3.0-or-later
2"""Bundle macro helpers for cikit.
4This module creates distributable archive bundles from a single file or
5directory. Generated archives are copied to the public artifact storage and
6registered as bundle artifacts for the active CI run.
8Author:
9 Sven Schlender
10Date:
11 2026-09-21
12"""
14import tarfile
15import tempfile
16import zipfile
17from pathlib import Path
19from cikit.artifacts import ArtifactType
20from cikit.errors import CiToolsError
23def _create_tar_bundle(output_file: Path, source: Path, mode: str):
24 """Create a TAR archive from one file or directory.
26 Args:
27 output_file: Target archive path.
28 source: File or directory to package.
29 mode: Tarfile write mode.
30 """
31 with tarfile.open(output_file, mode) as archive:
32 if source.is_dir(): 32 ↛ 36line 32 didn't jump to line 36 because the condition on line 32 was always true
33 for item in source.iterdir():
34 archive.add(item, arcname=item.name)
35 else:
36 archive.add(source, arcname=source.name)
39def _create_zip_bundle(output_file: Path, source: Path):
40 """Create a ZIP archive from one file or directory.
42 Args:
43 output_file: Target archive path.
44 source: File or directory to package.
45 """
46 with zipfile.ZipFile(output_file, "w", zipfile.ZIP_DEFLATED) as archive:
47 if source.is_dir():
48 for item in source.rglob("*"):
49 archive.write(item, item.relative_to(source))
50 else:
51 archive.write(source, source.name)
54def create(env, target_name: str, source: Path) -> Path:
55 """Create and register a bundle archive from one file or directory.
57 The archive format is derived from ``target_name``. ZIP, TAR, and TAR.GZ
58 archives are supported. Directory contents are placed directly in the
59 archive root.
61 Args:
62 env: Resolved CI run environment.
63 target_name: Final bundle filename.
64 source: File or directory to package.
66 Returns:
67 Path to the registered bundle artifact.
69 Raises:
70 CiToolsError: If the source does not exist, the archive format is
71 unsupported, or the bundle cannot be created.
72 """
73 source = env.resolve_path(source)
75 if not source.exists():
76 raise CiToolsError(f"Bundle source '{source}' does not exist.")
78 with tempfile.TemporaryDirectory() as temp_dir:
79 output_file = Path(temp_dir) / target_name
81 try:
82 if target_name.endswith(".tar.gz"):
83 _create_tar_bundle(output_file, source, "w:gz")
84 elif output_file.suffix == ".tar":
85 _create_tar_bundle(output_file, source, "w")
86 elif output_file.suffix == ".zip":
87 _create_zip_bundle(output_file, source)
88 else:
89 raise CiToolsError(f"Unsupported bundle format '{target_name}'. "
90 "Supported formats are .zip, .tar, and .tar.gz.")
91 except (OSError, tarfile.TarError, zipfile.BadZipFile, zipfile.LargeZipFile) as exp:
92 raise CiToolsError(f"Failed to create bundle '{target_name}': {exp}") from exp
94 artifact = env.copy_artifact(output_file, ArtifactType.BUNDLE)
96 return artifact.path