|
|
@@ -69,19 +69,7 @@ class WebhookService:
|
|
|
# 4. Get or create project
|
|
|
project = self.storage.get_or_create_project(project_name)
|
|
|
|
|
|
- # 5. Get file tree (once for all stages)
|
|
|
- try:
|
|
|
- tree_data = await self.gogs.get_recursive_tree(owner, repo_name, after_sha)
|
|
|
- tree_files = {
|
|
|
- item['path']: item
|
|
|
- for item in tree_data.get('tree', [])
|
|
|
- if item['type'] == 'blob'
|
|
|
- }
|
|
|
- except Exception as e:
|
|
|
- logger.error(f"Failed to get file tree: {e}", exc_info=True)
|
|
|
- return
|
|
|
-
|
|
|
- # 6. Process stages (support both old and new format)
|
|
|
+ # 5. Process stages (support both old and new format)
|
|
|
stages = manifest.get("stages", [])
|
|
|
|
|
|
# Backward compatibility: old single-stage format
|
|
|
@@ -120,13 +108,13 @@ class WebhookService:
|
|
|
)
|
|
|
logger.info(f"Processing stage '{stage_name}' with {len(outputs)} output rules")
|
|
|
|
|
|
- # Process outputs for this stage
|
|
|
- await self._process_outputs(version, outputs, tree_files, owner, repo_name)
|
|
|
+ # Process outputs for this stage (fetch only needed files)
|
|
|
+ await self._process_outputs(version, outputs, owner, repo_name, after_sha)
|
|
|
|
|
|
async def _process_outputs(
|
|
|
- self, version, outputs: list, tree_files: dict, owner: str, repo_name: str
|
|
|
+ self, version, outputs: list, owner: str, repo_name: str, commit_id: str
|
|
|
):
|
|
|
- """Process output rules and download matching files."""
|
|
|
+ """Process output rules and download matching files (on-demand fetching)."""
|
|
|
for output in outputs:
|
|
|
raw_path_pattern = output.get("path", "")
|
|
|
match_pattern = output.get("pattern", "*")
|
|
|
@@ -134,24 +122,35 @@ class WebhookService:
|
|
|
path_pattern = normalize_path(raw_path_pattern)
|
|
|
is_dir = is_directory_pattern(raw_path_pattern)
|
|
|
|
|
|
- for file_path, file_info in tree_files.items():
|
|
|
- is_match = False
|
|
|
-
|
|
|
- if is_dir:
|
|
|
- dir_prefix = path_pattern.rstrip("/") + "/"
|
|
|
- if file_path.startswith(dir_prefix):
|
|
|
- rel_name = file_path[len(dir_prefix):]
|
|
|
- if rel_name and fnmatch.fnmatch(rel_name, match_pattern):
|
|
|
- is_match = True
|
|
|
- else:
|
|
|
- if file_path == path_pattern:
|
|
|
- is_match = True
|
|
|
-
|
|
|
- if is_match:
|
|
|
+ if is_dir:
|
|
|
+ # Directory pattern: fetch only this directory's files
|
|
|
+ dir_path = path_pattern.rstrip("/")
|
|
|
+ logger.info(f"Fetching directory: {dir_path} with pattern: {match_pattern}")
|
|
|
+
|
|
|
+ files = await self.gogs.get_directory_tree(owner, repo_name, commit_id, dir_path)
|
|
|
+
|
|
|
+ for file_info in files:
|
|
|
+ file_path = file_info.get("path")
|
|
|
+ # Apply pattern matching
|
|
|
+ rel_name = file_path[len(dir_path) + 1:] if file_path.startswith(dir_path + "/") else file_path
|
|
|
+ if fnmatch.fnmatch(rel_name, match_pattern):
|
|
|
+ try:
|
|
|
+ await self.storage.process_file_with_sha(
|
|
|
+ version, file_path, file_info.get("sha"), owner, repo_name
|
|
|
+ )
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"Failed to process file {file_path}: {e}")
|
|
|
+ else:
|
|
|
+ # Single file: fetch only this file's info
|
|
|
+ logger.info(f"Fetching single file: {path_pattern}")
|
|
|
+
|
|
|
+ file_info = await self.gogs.get_file_info(owner, repo_name, commit_id, path_pattern)
|
|
|
+ if file_info:
|
|
|
try:
|
|
|
- file_sha = file_info.get("sha")
|
|
|
await self.storage.process_file_with_sha(
|
|
|
- version, file_path, file_sha, owner, repo_name
|
|
|
+ version, path_pattern, file_info.get("sha"), owner, repo_name
|
|
|
)
|
|
|
except Exception as e:
|
|
|
- logger.error(f"Failed to process file {file_path}: {e}")
|
|
|
+ logger.error(f"Failed to process file {path_pattern}: {e}")
|
|
|
+ else:
|
|
|
+ logger.warning(f"File not found: {path_pattern}")
|