Skip to content

Commit b432ea1

Browse files
committed
feat(RELEASE-2476): add Python script for collect-charon-params task
Assisted-by: Cursor Signed-off-by: Lubomir Gallovic <lgallovi@redhat.com>
1 parent a0c68a7 commit b432ea1

2 files changed

Lines changed: 728 additions & 0 deletions

File tree

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env python3
2+
"""Collect charon configuration from data, snapshot, and release files.
3+
4+
Extract parameters needed by charon (MRRC/NRRC publishing tool) and
5+
write them as a shell-sourceable env file, a config file, and Tekton
6+
result files.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
import argparse
12+
import dataclasses
13+
import json
14+
from pathlib import Path
15+
from typing import Any
16+
17+
import tekton
18+
from file import load_json_dict
19+
from logger import logger
20+
21+
PROG = "collect_charon_params.py"
22+
23+
24+
@dataclasses.dataclass(frozen=True)
25+
class CharonParams:
26+
"""Extracted charon parameters ready for downstream tasks."""
27+
28+
target: str
29+
product_name: str
30+
product_version: str
31+
sign_key: str
32+
oci_registry: str
33+
aws_secret: str
34+
sign_ca_secret: str
35+
author: str
36+
config: Any
37+
38+
39+
def collect_charon_params(
40+
data: dict[str, Any],
41+
snapshot: dict[str, Any],
42+
release: dict[str, Any],
43+
) -> CharonParams:
44+
"""Extract charon configuration from loaded JSON dicts."""
45+
charon: dict[str, Any] = data["charon"]
46+
47+
environment: str = charon["environment"]
48+
release_val: str = charon["release"]
49+
package_type: str = charon.get("packageType", "maven")
50+
target = f"{environment}-{package_type}-{release_val}"
51+
52+
product_name: str = data["releaseNotes"]["product_name"]
53+
product_version: str = data["releaseNotes"]["product_version"]
54+
55+
signing = charon.get("signing") or {}
56+
sign_key: str = signing.get("signKey", "")
57+
sign_ca_secret: str = signing.get("signCASecret", "")
58+
59+
aws_secret: str = charon["awsSecret"]
60+
61+
components = snapshot.get("components", [])
62+
oci_registry = "%".join(c["containerImage"] for c in components)
63+
64+
author: str = release["status"]["attribution"]["author"]
65+
66+
config: Any = charon["config"]
67+
68+
return CharonParams(
69+
target=target,
70+
product_name=product_name,
71+
product_version=product_version,
72+
sign_key=sign_key,
73+
oci_registry=oci_registry,
74+
aws_secret=aws_secret,
75+
sign_ca_secret=sign_ca_secret,
76+
author=author,
77+
config=config,
78+
)
79+
80+
81+
def write_charon_env(env_path: Path, params: CharonParams) -> None:
82+
"""Write charon parameters as a shell-sourceable env file."""
83+
lines = [
84+
f"export CHARON_TARGET={params.target}",
85+
f'export CHARON_PRODUCT_NAME="{params.product_name}"',
86+
f'export CHARON_PRODUCT_VERSION="{params.product_version}"',
87+
]
88+
if params.sign_key:
89+
lines.append(f'export CHARON_SIGN_KEY="{params.sign_key}"')
90+
lines.append(f'export CHARON_OCI_REGISTRY="{params.oci_registry}"')
91+
lines.append(f'export CHARON_AUTHOR="{params.author}"')
92+
env_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
93+
94+
95+
def write_charon_config(config_path: Path, config: Any) -> None:
96+
"""Write the charon config file.
97+
98+
String values are written as-is (matching ``jq -r`` behaviour);
99+
non-string values are serialised as JSON.
100+
"""
101+
if isinstance(config, str):
102+
text = config
103+
else:
104+
text = json.dumps(config)
105+
config_path.write_text(text + "\n", encoding="utf-8")
106+
107+
108+
def run(
109+
work_dir: Path,
110+
data_json_path: str,
111+
snapshot_path: str,
112+
release_path: str,
113+
result_charon_param_file_path: Path,
114+
result_charon_config_file_path: Path,
115+
result_charon_aws_secret: Path,
116+
result_charon_sign_ca_secret: Path,
117+
) -> None:
118+
"""Orchestrate collection of charon parameters."""
119+
data = load_json_dict(work_dir / data_json_path)
120+
snapshot = load_json_dict(work_dir / snapshot_path)
121+
release_data = load_json_dict(work_dir / release_path)
122+
123+
params = collect_charon_params(data, snapshot, release_data)
124+
125+
env_rel = str(Path(data_json_path).parent / "charon.env")
126+
cfg_rel = str(Path(data_json_path).parent / "charon-config.yaml")
127+
128+
write_charon_env(work_dir / env_rel, params)
129+
write_charon_config(work_dir / cfg_rel, params.config)
130+
131+
result_charon_param_file_path.write_text(env_rel, encoding="utf-8")
132+
result_charon_config_file_path.write_text(cfg_rel, encoding="utf-8")
133+
result_charon_aws_secret.write_text(params.aws_secret, encoding="utf-8")
134+
result_charon_sign_ca_secret.write_text(params.sign_ca_secret, encoding="utf-8")
135+
136+
logger.info("Charon parameters collected successfully")
137+
138+
139+
def _parse_args(
140+
argv: list[str] | None = None,
141+
) -> argparse.Namespace:
142+
"""Parse command-line arguments."""
143+
parser = argparse.ArgumentParser(description=__doc__, prog=PROG)
144+
parser.add_argument(
145+
"--work-dir",
146+
required=True,
147+
help="Base directory for data files",
148+
)
149+
parser.add_argument(
150+
"--data-json-path",
151+
required=True,
152+
help="Relative path to the data JSON file",
153+
)
154+
parser.add_argument(
155+
"--snapshot-path",
156+
required=True,
157+
help="Relative path to the snapshot JSON file",
158+
)
159+
parser.add_argument(
160+
"--release-path",
161+
required=True,
162+
help="Relative path to the release JSON file",
163+
)
164+
return parser.parse_args(argv)
165+
166+
167+
def main(argv: list[str] | None = None) -> int:
168+
"""Parse arguments and run charon parameter collection."""
169+
args = _parse_args(argv)
170+
r_param, r_cfg, r_aws, r_ca = tekton.result_paths_from_env(
171+
"RESULT_CHARON_PARAM_FILE_PATH",
172+
"RESULT_CHARON_CONFIG_FILE_PATH",
173+
"RESULT_CHARON_AWS_SECRET",
174+
"RESULT_CHARON_SIGN_CA_SECRET",
175+
)
176+
run(
177+
work_dir=Path(args.work_dir),
178+
data_json_path=args.data_json_path,
179+
snapshot_path=args.snapshot_path,
180+
release_path=args.release_path,
181+
result_charon_param_file_path=r_param,
182+
result_charon_config_file_path=r_cfg,
183+
result_charon_aws_secret=r_aws,
184+
result_charon_sign_ca_secret=r_ca,
185+
)
186+
return 0
187+
188+
189+
if __name__ == "__main__": # pragma: no cover
190+
raise SystemExit(main())

0 commit comments

Comments
 (0)