Skip to content

Commit 3d82cfd

Browse files
committed
- was missing the list ingest from the _copy.txt. This fixed now for the contributors CI.
1 parent e03c508 commit 3d82cfd

1 file changed

Lines changed: 68 additions & 33 deletions

File tree

tools/normalize_contribution.py

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ def _load_pack_registry(packs_root: Optional[Path]) -> tuple[dict, dict]:
193193
".secrets-ignore",
194194
"Author_image.png",
195195
"CHANGELOG.md",
196+
# Policy/config files that live inside List directories but are not
197+
# list descriptors or data files — read directly by framework validators.
198+
"shadow_mode_policy.json",
196199
}
197200

198201
# Files in these directories are skipped. They have their own SDK schema
@@ -333,8 +336,12 @@ def content_type_from_path(path: Path) -> Optional[str]:
333336
if content_dir == "Playbooks" and path.suffix.lower() in (".yml", ".yaml"):
334337
return "playbook"
335338

336-
# Accept both .json and .txt in Lists/ — XSIAM exports can produce either
339+
# Accept both .json and .txt in Lists/ — XSIAM exports can produce either.
340+
# Never process _data.json files — they are the data half of the two-file
341+
# list structure already in the repo, not a new contribution to normalise.
337342
if content_dir == "Lists" and path.suffix.lower() in (".json", ".txt"):
343+
if path.stem.endswith("_data"):
344+
return None
338345
return "list"
339346

340347
if content_dir == "Scripts":
@@ -1197,6 +1204,59 @@ def process_file(
11971204
return True, False
11981205

11991206
canon = list_canonical_name(path, override_name)
1207+
1208+
# Determine the target directory — where the canonical files live.
1209+
if out_dir is not None:
1210+
target_dir = Path(out_dir) / canon
1211+
else:
1212+
lists_parent = path.parent
1213+
if lists_parent.name == canon:
1214+
target_dir = lists_parent
1215+
else:
1216+
p = path.parent
1217+
while p != p.parent and p.name != "Lists":
1218+
p = p.parent
1219+
target_dir = p / canon
1220+
1221+
data_path = target_dir / f"{canon}_data.json"
1222+
desc_path = target_dir / f"{canon}.json"
1223+
1224+
# ── UPDATE MODE: _data.json already exists ────────────────────────────
1225+
# The contributor is updating an existing list. Write the new content
1226+
# directly to _data.json and leave the descriptor completely untouched.
1227+
# No descriptor modification, no fromVersion injection, no split.
1228+
if data_path.exists():
1229+
# Check if content actually changed
1230+
try:
1231+
existing = json.loads(data_path.read_text(encoding="utf-8"))
1232+
except Exception:
1233+
existing = {}
1234+
1235+
if existing == data:
1236+
print(OK(" ✓ already clean"))
1237+
return True, False
1238+
1239+
changes = ["data file updated (existing list)"]
1240+
prefix = "(dry-run) " if dry_run else ""
1241+
for c in changes:
1242+
print(f" {prefix}{OK('●')} {c}")
1243+
1244+
if not dry_run:
1245+
target_dir.mkdir(parents=True, exist_ok=True)
1246+
data_path.write_text(
1247+
json.dumps(data, indent=2, ensure_ascii=False) + "\n",
1248+
encoding="utf-8",
1249+
)
1250+
print(f" {OK('→')} {data_path} (data)")
1251+
if path.resolve() != data_path.resolve():
1252+
path.unlink()
1253+
print(f" {OK('✗')} removed {path.name} (replaced by canonical data file)")
1254+
1255+
return True, True
1256+
1257+
# ── CREATE MODE: new list, no existing _data.json ─────────────────────
1258+
# The contributor is adding a brand new list. Create both the descriptor
1259+
# and data files from the contribution.
12001260
descriptor, changes, data_out = normalize_list(data, canon)
12011261

12021262
if not changes:
@@ -1208,47 +1268,22 @@ def process_file(
12081268
print(f" {prefix}{OK('●')} {c}")
12091269

12101270
if not dry_run:
1211-
# Determine the target directory.
1212-
# Repo structure: Lists/<ListName>/<ListName>.json + <ListName>_data.json
1213-
# If the file is already inside a correctly-named subdirectory, use it.
1214-
# If the file is at the Lists/ level or has a different name, create
1215-
# the subdirectory and write both files there.
1216-
if out_dir is not None:
1217-
target_dir = Path(out_dir) / canon
1218-
else:
1219-
# Check if we are already inside Lists/<canon>/
1220-
lists_parent = path.parent
1221-
if lists_parent.name == canon:
1222-
# Already in the right subdirectory
1223-
target_dir = lists_parent
1224-
else:
1225-
# At Lists/ level or wrong directory — create canonical subdir
1226-
# Walk up to find the Lists/ directory
1227-
p = path.parent
1228-
while p != p.parent and p.name != "Lists":
1229-
p = p.parent
1230-
target_dir = p / canon
1231-
12321271
target_dir.mkdir(parents=True, exist_ok=True)
12331272

1234-
# Write the descriptor file: <ListName>.json
1235-
desc_path = target_dir / f"{canon}.json"
1236-
desc_path.write_text(
1237-
json.dumps(descriptor, indent=2, ensure_ascii=False) + "\n",
1238-
encoding="utf-8",
1239-
)
1240-
print(f" {OK('→')} {desc_path} (descriptor)")
1273+
# Write descriptor only if it doesn't already exist
1274+
if not desc_path.exists():
1275+
desc_path.write_text(
1276+
json.dumps(descriptor, indent=2, ensure_ascii=False) + "\n",
1277+
encoding="utf-8",
1278+
)
1279+
print(f" {OK('→')} {desc_path} (descriptor)")
12411280

1242-
# Write the data file: <ListName>_data.json
1243-
data_path = target_dir / f"{canon}_data.json"
12441281
data_path.write_text(
12451282
json.dumps(data_out, indent=2, ensure_ascii=False) + "\n",
12461283
encoding="utf-8",
12471284
)
12481285
print(f" {OK('→')} {data_path} (data)")
12491286

1250-
# Remove the original file if it is in a different location or has a
1251-
# different name — prevents stale files with duplicate identity
12521287
if path.resolve() != desc_path.resolve() and path.resolve() != data_path.resolve():
12531288
path.unlink()
12541289
print(f" {OK('✗')} removed {path.name} (replaced by canonical files)")

0 commit comments

Comments
 (0)