Task 1. Clone repository và khám phá file
1Mục tiêu¶
Task 1 xây dựng lớp đầu vào có thể tái hiện cho toàn bộ pipeline. Notebook clone hoặc tái sử dụng repository nguồn, ghi nhận commit SHA và khám phá các file Python từ repository root.
Kết quả discovery được lưu trong manifest cùng các thông tin như đường dẫn tương đối, commit, kích thước, content hash, trạng thái included và lý do loại trừ. Parser Service ở Task 2 sử dụng tập file hợp lệ được xác định từ manifest này.
2Vai trò trong pipeline¶
Task này tách riêng việc thu thập file nguồn khỏi quá trình parsing. Nhờ đó các task sau không cần tự duyệt repository, mà chỉ đọc manifest đã được tạo và xác minh.
3Repository nguồn¶
Repository được clone shallow để lấy đúng snapshot cần phân tích mà không tải toàn bộ lịch sử Git. Commit SHA được ghi lại như một mốc tái hiện: nếu upstream thay đổi sau này, các kết quả discovery và parser trong báo cáo vẫn có thể được đối chiếu với đúng phiên bản mã nguồn đã chạy.
Cell dưới đây xác định project root, source repository local và manifest canonical trước khi gọi CLI.
import os
import sys
import json
import subprocess
from pathlib import Path
from collections import Counter
import statistics
# Resolve PROJECT_ROOT using Git
PROJECT_ROOT = Path(
subprocess.run(
["git", "rev-parse", "--show-toplevel"],
check=True,
capture_output=True,
text=True,
).stdout.strip()
)
sys.path.insert(0, str(PROJECT_ROOT / "src"))
from infrastructure.filesystem.git_source_repository import GitSourceRepository
SOURCE_REPOSITORY = PROJECT_ROOT / "workspace/source/transformers-pr-agent"
MANIFEST_PATH = PROJECT_ROOT / "artifacts/manifests/source-files.jsonl"
print("PROJECT_ROOT:", PROJECT_ROOT)
print("SOURCE_REPOSITORY:", SOURCE_REPOSITORY)
print("MANIFEST_PATH:", MANIFEST_PATH)
PROJECT_ROOT: /home/phat/AI_Project/lab04-cpg-streaming
SOURCE_REPOSITORY: /home/phat/AI_Project/lab04-cpg-streaming/workspace/source/transformers-pr-agent
MANIFEST_PATH: /home/phat/AI_Project/lab04-cpg-streaming/artifacts/manifests/source-files.jsonl
4Chuẩn bị notebook runtime¶
CLI clone-source chỉ clone khi repository chưa tồn tại; nếu thư mục local đã có .git, notebook giữ nguyên bản sao hiện tại và đọc commit SHA từ Git. Cách này tránh thay đổi nguồn dữ liệu trong lúc báo cáo được execute lại.
5Discovery và file filters¶
Discovery bắt đầu từ repository root và ghi nhận toàn bộ file .py trước khi lọc. Sau đó một bộ filter chung loại các nhóm không phải đầu vào chính của parser như tests, setup/build files và generated files.
Điểm quan trọng là rule loại trừ không mặc định bỏ mọi file ngoài src/. Các file Python trong .github/, examples/, tools/ hoặc thư mục tương tự vẫn là đầu vào hợp lệ nếu không khớp rule loại trừ chính thức.
# Execute CLI clone command
print("Executing clone-source CLI...")
subprocess.run(
["uv", "run", "lab04", "clone-source"],
check=True,
text=True,
cwd=str(PROJECT_ROOT)
)
# Verification using Git
remote_url = subprocess.check_output(
["git", "-C", str(SOURCE_REPOSITORY), "remote", "get-url", "origin"],
text=True,
).strip()
commit_hash = subprocess.check_output(
["git", "-C", str(SOURCE_REPOSITORY), "rev-parse", "HEAD"],
text=True,
).strip()
is_shallow = subprocess.check_output(
["git", "-C", str(SOURCE_REPOSITORY), "rev-parse", "--is-shallow-repository"],
text=True,
).strip()
print("Remote URL:", remote_url)
print("Commit SHA:", commit_hash)
print("Shallow repository:", is_shallow)
Executing clone-source CLI...
Cloning target source repository...
Cloned successfully to: workspace/source/transformers-pr-agent
Commit SHA: 458c957fa1e8851825cd799f5d030876f0644194
Remote URL: https://github.com/huggingface/transformers-pr-agent.git
Commit SHA: 458c957fa1e8851825cd799f5d030876f0644194
Shallow repository: true
6Phân tích manifest¶
artifacts/manifests/source-files.jsonl là discovery manifest canonical. File này lưu toàn bộ record discovery, còn Parser Service chỉ sử dụng các record có included = true.
Cell kế tiếp chạy discovery, đọc lại manifest, tính breakdown và đối chiếu tập eligible từ manifest với discovery độc lập. So sánh dùng exact path-set equality, không chỉ so sánh số lượng.
# Run discovery CLI command
print("Executing discover CLI...")
subprocess.run(
["uv", "run", "lab04", "discover", "--scope", "final", "--manifest", str(MANIFEST_PATH)],
check=True,
text=True,
cwd=str(PROJECT_ROOT)
)
Executing discover CLI...
Executing discovery phase (scope=final, manifest=/home/phat/AI_Project/lab04-cpg-streaming/artifacts/manifests/source-files.jsonl)...
Discovery phase completed. Eligible files: 2963
CompletedProcess(args=['uv', 'run', 'lab04', 'discover', '--scope', 'final', '--manifest', '/home/phat/AI_Project/lab04-cpg-streaming/artifacts/manifests/source-files.jsonl'], returncode=0)7Verification assertions¶
Các assertion bên dưới kiểm tra những invariant quan trọng của manifest: path không duplicate, được sắp xếp ổn định, dùng định dạng POSIX relative path và không trỏ ra ngoài source root.
Notebook cũng đối chiếu tập file hợp lệ trong manifest với discovery service và parser full scope. Điều này bảo đảm Task 2 nhận đúng đầu vào đã được xác định ở Task 1.
# Read and summarize manifest generated by CLI/service
manifest_records = []
with open(MANIFEST_PATH, "r", encoding="utf-8") as f:
for line in f:
manifest_records.append(json.loads(line))
raw_files = manifest_records
eligible_files = [record for record in manifest_records if record["included"]]
excluded_files = [record for record in manifest_records if not record["included"]]
repo_adapter = GitSourceRepository(SOURCE_REPOSITORY, clone_url="")
previous_scope = os.environ.get("PARSER_SCOPE")
os.environ["PARSER_SCOPE"] = "final"
independent_eligible_paths = [path.as_posix() for path in repo_adapter.list_files()]
os.environ["PARSER_SCOPE"] = "smoke"
smoke_paths = [path.as_posix() for path in repo_adapter.list_files()]
if previous_scope is None:
os.environ.pop("PARSER_SCOPE", None)
else:
os.environ["PARSER_SCOPE"] = previous_scope
raw_paths = [record["file_path"] for record in raw_files]
eligible_paths = [record["file_path"] for record in eligible_files]
src_paths = [path for path in raw_paths if path.startswith("src/")]
exclusion_counts = Counter(record["exclusion_reason"] for record in excluded_files)
by_top_level = Counter(Path(path).parts[0] for path in raw_paths)
print("Raw Python files in repository:", len(raw_paths))
print("Python files under src/:", len(src_paths))
print("Eligible Python files after exclusions:", len(eligible_paths))
print("Full manifest count:", len(eligible_paths))
print("Files selected for smoke verification:", len(smoke_paths))
print("\nBreakdown by top-level directory:")
for name, count in by_top_level.most_common():
print(f"{name}: {count}")
print("\nExclusion rules and counts:")
for reason, count in sorted(exclusion_counts.items()):
print(f"{reason}: {count}")
sizes = [record["size_bytes"] for record in eligible_files]
print("\nEligible file size statistics (bytes):")
print("Min size:", min(sizes))
print("Max size:", max(sizes))
print("Mean size:", statistics.mean(sizes))
print("Median size:", statistics.median(sizes))
repo_ids = {record["repository_id"] for record in eligible_files}
commit_shas = {record["commit_sha"] for record in eligible_files}
print(f"\nRepository ID: {list(repo_ids)[0]}")
print(f"Commit SHA in manifest: {list(commit_shas)[0]}")
print("\nSample eligible paths:")
for path in eligible_paths[:20]:
print(path)
print("\nSample smoke paths:")
for path in smoke_paths[:10]:
print(path)
Raw Python files in repository: 4496
Python files under src/: 2779
Eligible Python files after exclusions: 2963
Full manifest count: 2963
Files selected for smoke verification: 5
Breakdown by top-level directory:
src: 2779
tests: 1516
examples: 96
utils: 75
docs: 11
benchmark_v2: 6
benchmark: 5
scripts: 3
.circleci: 2
.github: 1
conftest.py: 1
setup.py: 1
Exclusion rules and counts:
Excluded generated protobuf file: 1
Excluded setup/build file: 1
Excluded test file: 1529
Excluded test support file: 2
Eligible file size statistics (bytes):
Min size: 0
Max size: 267972
Mean size: 17544.67600404995
Median size: 8794
Repository ID: huggingface/transformers-pr-agent
Commit SHA in manifest: 458c957fa1e8851825cd799f5d030876f0644194
Sample eligible paths:
.circleci/create_circleci_config.py
.circleci/parse_test_outputs.py
.github/scripts/assign_reviewers.py
benchmark/__init__.py
benchmark/benches/llama.py
benchmark/benchmark.py
benchmark/benchmarks_entrypoint.py
benchmark/optimum_benchmark_wrapper.py
benchmark_v2/benchmark_scripts/continuous_batching_overall.py
benchmark_v2/framework/benchmark_config.py
benchmark_v2/framework/benchmark_runner.py
benchmark_v2/framework/data_classes.py
benchmark_v2/framework/hardware_metrics.py
benchmark_v2/run_benchmarks.py
docs/source/_config.py
docs/source/ar/_config.py
docs/source/de/_config.py
docs/source/en/_config.py
docs/source/es/_config.py
docs/source/fr/_config.py
Sample smoke paths:
src/transformers/__init__.py
src/transformers/_typing.py
src/transformers/activations.py
src/transformers/audio_utils.py
src/transformers/backbone_utils.py
# Task 1 Verification Assertions
assert SOURCE_REPOSITORY.exists(), "Source repository path does not exist"
assert (SOURCE_REPOSITORY / ".git").exists(), "Not a git repository"
assert is_shallow == "true", "Repository is not shallow"
assert MANIFEST_PATH.exists(), "Manifest file does not exist"
assert len(raw_files) > 0, "Raw manifest is empty"
assert len(eligible_files) > 0, "Eligible manifest is empty"
assert len(raw_paths) == len(set(raw_paths)), "Raw paths contain duplicates"
assert raw_paths == sorted(raw_paths), "Raw paths must be sorted"
assert len(eligible_paths) == len(set(eligible_paths)), "Eligible paths contain duplicates"
assert eligible_paths == sorted(eligible_paths), "Eligible paths must be sorted"
assert all(path.endswith(".py") for path in raw_paths), "Raw scope must contain only Python files"
assert all(path.endswith(".py") for path in eligible_paths), "Eligible scope must contain only Python files"
assert all('\\' not in path for path in raw_paths), "Paths must use POSIX separators"
assert all(not path.startswith("../") for path in raw_paths), "Paths must stay inside repository root"
assert set(eligible_paths) == set(independent_eligible_paths), "Full manifest must exactly equal eligible set"
assert set(smoke_paths).issubset(set(eligible_paths)), "Smoke scope must be a subset of full eligible scope"
for record in manifest_records:
assert record["commit_sha"] == commit_hash, "Commit SHA mismatch in manifest"
assert record["repository_id"] == "huggingface/transformers-pr-agent", "Repo ID mismatch"
assert record["file_path"].endswith(".py"), "Manifest record is not a Python file"
assert record["content_sha256"], "Manifest record is missing content hash"
print("Exact set-equality assertion PASSED: full manifest paths == eligible paths")
print("Task 1 verification assertions PASSED successfully!")
Exact set-equality assertion PASSED: full manifest paths == eligible paths
Task 1 verification assertions PASSED successfully!
8Kết quả tổng hợp¶
| Hạng mục | Số lượng |
|---|---|
| File Python được discovery | 4.496 |
| File test bị loại | 1.531 |
| File setup/build bị loại | 1 |
| File generated bị loại | 1 |
| Tổng file bị loại | 1.533 |
| File hợp lệ cho Parser Service | 2.963 |
| File trong smoke scope | 5 |
Repository được shallow-clone tại một commit xác định và có 4.496 file Python được discovery. Sau khi áp dụng các quy tắc loại trừ đối với test, setup/build và generated files, hệ thống xác định 2.963 file hợp lệ cho Parser Service.
Manifest lưu toàn bộ kết quả discovery và trạng thái của từng file. Eligible records in manifest: 2.963. Tập record có included = true được đối chiếu độc lập với discovery service, bảo đảm Parser Service nhận đúng tập đầu vào.
9Lệnh xác minh end-to-end¶
uv run lab04 clone-source
uv run lab04 discover --scope final --manifest artifacts/manifests/source-files.jsonl
uv run lab04 discover --scope smoke --manifest artifacts/manifests/source-files-smoke.jsonl10Nhận xét¶
Ghi commit SHA làm cho số liệu discovery có thể tái hiện thay vì phụ thuộc vào trạng thái mới nhất của repository upstream.
Việc tách raw discovery khỏi eligible filtering giúp notebook báo cáo trung thực cả quy mô repository lẫn phạm vi parser thực tế.
Manifest đóng vai trò hợp đồng giữa Task 1 và Task 2: discovery quyết định file nào hợp lệ, parser chỉ tiêu thụ tập đầu vào đã được xác minh. Smoke scope vẫn có thể dùng cho kiểm tra nhanh mà không thay đổi full parser scope.