Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ Each build writes a diagnostic bundle into the git-tracked `diagnostic/` directo

Before submitting a PR, include the generated diagnostic files in your branch. This diagnostic is required for this PR so reviewers can verify the build environment, but it can be removed before merging if requested. The repository includes a stub example in `diagnostic/` to show the expected shape; real `.logd` files are generated by `python3 build.py`.

Validate diagnostic metadata and encrypted log references with:

```sh
python3 tools/verify_diagnostic_bundle.py diagnostic/build-00000000.json
python3 -m unittest discover -s tests -t . -v
```

## Bounties

Active bounties are tracked as GitHub issues, find them on the Issues page.
Expand Down
6 changes: 3 additions & 3 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ def build_diagnostic_report(

decrypt_target = logd_relpaths[0] if logd_relpaths and len(logd_relpaths) == 1 else None
if logd_relpaths and len(logd_relpaths) > 1:
decrypt_target = str((DIAGNOSTIC_DIR / f"build-{commit_id}.logd").relative_to(ROOT))
decrypt_target = (DIAGNOSTIC_DIR / f"build-{commit_id}.logd").relative_to(ROOT).as_posix()

report = {
"generated_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
Expand Down Expand Up @@ -592,8 +592,8 @@ def generate_logd(

safe_pw = sr.stdout.strip()
logd_files = split_diagnostic_logd(logd_path)
logd_relpaths = [str(path.relative_to(ROOT)) for path in logd_files]
decrypt_target = logd_relpaths[0] if len(logd_relpaths) == 1 else str(logd_path.relative_to(ROOT))
logd_relpaths = [path.relative_to(ROOT).as_posix() for path in logd_files]
decrypt_target = logd_relpaths[0] if len(logd_relpaths) == 1 else logd_path.relative_to(ROOT).as_posix()
write_diagnostic_report(
metadata_path,
build_diagnostic_report(
Expand Down
Binary file added diagnostic/build-0e5a90ec-part001.logd
Binary file not shown.
Binary file added diagnostic/build-0e5a90ec-part002.logd
Binary file not shown.
26 changes: 26 additions & 0 deletions diagnostic/build-0e5a90ec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"generated_at": "2026-07-06T14:00:34.952613+00:00",
"commit": "0e5a90ec",
"diagnostic_logd": [
"diagnostic/build-0e5a90ec-part001.logd",
"diagnostic/build-0e5a90ec-part002.logd"
],
"diagnostic_logd_error": null,
"chunked": true,
"chunk_size_bytes": 41943040,
"password": "5bd4dc9f1b40d989ade8",
"decrypt_command": "encryptly unpack diagnostic/build-0e5a90ec.logd <outdir> --password 5bd4dc9f1b40d989ade8",
"total_modules": 1,
"passed": 0,
"failed": 1,
"modules": [
{
"name": "backend",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [WinError 2] \u7cfb\u7edf\u627e\u4e0d\u5230\u6307\u5b9a\u7684\u6587\u4ef6\u3002"
}
],
"pr_note": "Include the encrypted diagnostic logd artifact(s): diagnostic/build-0e5a90ec-part001.logd, diagnostic/build-0e5a90ec-part002.logd. The encrypted .logd is the required diagnostic content for PR review; this JSON file is metadata. Maintainers may ask you to remove these diagnostic artifacts before merging."
}
1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

144 changes: 144 additions & 0 deletions tests/test_verify_diagnostic_bundle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import json
import tempfile
import unittest
from pathlib import Path
from unittest import mock

import build
from tools.verify_diagnostic_bundle import validate_diagnostic_bundle


class DiagnosticBundleValidationTests(unittest.TestCase):
def _write_metadata(self, root: Path, name: str, diagnostic_logd):
metadata = root / "diagnostic" / name
metadata.parent.mkdir(parents=True, exist_ok=True)
metadata.write_text(
json.dumps(
{
"commit": "12345678",
"diagnostic_logd": diagnostic_logd,
"modules": [],
}
),
encoding="utf-8",
)
return metadata

def test_valid_metadata_matches_existing_repo_relative_logd(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
(root / "diagnostic").mkdir()
(root / "diagnostic" / "build-12345678.logd").write_bytes(b"logd")
metadata = self._write_metadata(
root,
"build-12345678.json",
"diagnostic/build-12345678.logd",
)

self.assertEqual(validate_diagnostic_bundle(metadata, root), [])

def test_chunked_logd_references_are_allowed(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
diagnostic = root / "diagnostic"
diagnostic.mkdir()
(diagnostic / "build-12345678-part001.logd").write_bytes(b"one")
(diagnostic / "build-12345678-part002.logd").write_bytes(b"two")
metadata = self._write_metadata(
root,
"build-12345678.json",
[
"diagnostic/build-12345678-part001.logd",
"diagnostic/build-12345678-part002.logd",
],
)

self.assertEqual(validate_diagnostic_bundle(metadata, root), [])

def test_missing_json_fails_clearly(self):
with tempfile.TemporaryDirectory() as tmpdir:
errors = validate_diagnostic_bundle(Path(tmpdir) / "diagnostic" / "missing.json", Path(tmpdir))

self.assertTrue(any("missing diagnostic JSON" in error for error in errors))

def test_missing_logd_reference_fails_clearly(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
metadata = self._write_metadata(
root,
"build-12345678.json",
"diagnostic/build-12345678.logd",
)

errors = validate_diagnostic_bundle(metadata, root)

self.assertTrue(any("referenced .logd artifact is missing" in error for error in errors))

def test_mismatched_logd_pair_fails_clearly(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
diagnostic = root / "diagnostic"
diagnostic.mkdir()
(diagnostic / "build-deadbeef.logd").write_bytes(b"logd")
metadata = self._write_metadata(
root,
"build-12345678.json",
"diagnostic/build-deadbeef.logd",
)

errors = validate_diagnostic_bundle(metadata, root)

self.assertTrue(any("JSON/logd pair mismatch" in error for error in errors))

def test_absolute_or_windows_paths_are_rejected(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
metadata = self._write_metadata(
root,
"build-12345678.json",
r"C:\Users\someone\diagnostic\build-12345678.logd",
)

errors = validate_diagnostic_bundle(metadata, root)

self.assertTrue(any("repository-relative / path" in error for error in errors))

def test_local_path_and_user_values_are_redacted(self):
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
diagnostic = root / "diagnostic"
diagnostic.mkdir()
(diagnostic / "build-12345678.logd").write_bytes(b"logd")
metadata = self._write_metadata(
root,
"build-12345678.json",
"diagnostic/build-12345678.logd",
)
payload = json.loads(metadata.read_text(encoding="utf-8"))
payload["output"] = f"leaked path {root}"
metadata.write_text(json.dumps(payload), encoding="utf-8")

with mock.patch("tools.verify_diagnostic_bundle.getpass.getuser", return_value="example-user"):
with mock.patch("tools.verify_diagnostic_bundle.platform.node", return_value="example-host"):
errors = validate_diagnostic_bundle(metadata, root)

self.assertTrue(any("leaks local value" in error for error in errors))

def test_build_report_uses_posix_reassemble_target_for_chunked_logd(self):
report = build.build_diagnostic_report(
results=[],
commit_id="12345678",
logd_relpaths=[
"diagnostic/build-12345678-part001.logd",
"diagnostic/build-12345678-part002.logd",
],
password="pw",
chunked=True,
)

self.assertIn("diagnostic/build-12345678.logd", report["decrypt_command"])
self.assertNotIn("\\", report["decrypt_command"])


if __name__ == "__main__":
unittest.main()
100 changes: 100 additions & 0 deletions tools/verify_diagnostic_bundle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env python3

from __future__ import annotations

import argparse
import getpass
import json
import os
import platform
import tempfile
from pathlib import Path, PurePosixPath
from typing import Any


ROOT = Path(__file__).resolve().parents[1]


def _as_list(value: Any) -> list[str]:
if value is None:
return []
if isinstance(value, str):
return [value]
if isinstance(value, list) and all(isinstance(item, str) for item in value):
return value
return []


def _is_repo_relative_posix_path(value: str) -> bool:
if "\\" in value:
return False
path = PurePosixPath(value)
return not path.is_absolute() and ".." not in path.parts and value.startswith("diagnostic/")


def _sensitive_tokens(root: Path) -> list[str]:
candidates = {
str(root),
str(root.resolve()),
str(Path.home()),
tempfile.gettempdir(),
getpass.getuser(),
platform.node(),
}
return sorted({token for token in candidates if token and len(token) >= 3}, key=len, reverse=True)


def validate_diagnostic_bundle(metadata_path: Path, root: Path = ROOT) -> list[str]:
errors: list[str] = []
if not metadata_path.exists():
return [f"missing diagnostic JSON: {metadata_path}"]

try:
report = json.loads(metadata_path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
return [f"invalid diagnostic JSON: {exc}"]

logd_paths = _as_list(report.get("diagnostic_logd"))
if not logd_paths:
errors.append("diagnostic_logd is missing or not a string/list")

for logd_path in logd_paths:
if not _is_repo_relative_posix_path(logd_path):
errors.append(f"diagnostic_logd must be a repository-relative / path: {logd_path}")
continue
absolute_logd = root / Path(logd_path)
if not absolute_logd.exists():
errors.append(f"referenced .logd artifact is missing: {logd_path}")
if absolute_logd.suffix != ".logd":
errors.append(f"referenced diagnostic artifact must end with .logd: {logd_path}")

expected_prefix = metadata_path.stem
for logd_path in logd_paths:
if Path(logd_path).stem != expected_prefix and not Path(logd_path).stem.startswith(f"{expected_prefix}-part"):
errors.append(f"diagnostic JSON/logd pair mismatch: {metadata_path.name} -> {logd_path}")

serialized = json.dumps(report, sort_keys=True)
for token in _sensitive_tokens(root):
escaped_token = json.dumps(token)[1:-1]
if token in serialized or escaped_token in serialized:
errors.append(f"diagnostic metadata leaks local value: {token}")

return errors


def main() -> int:
parser = argparse.ArgumentParser(description="Validate diagnostic JSON/logd bundle pairing")
parser.add_argument("metadata", type=Path, help="Path to diagnostic/build-*.json")
args = parser.parse_args()

errors = validate_diagnostic_bundle(args.metadata)
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print(f"OK: {args.metadata}")
return 0


if __name__ == "__main__":
raise SystemExit(main())