diff --git a/pipeline_service/workspace.py b/pipeline_service/workspace.py index 74f185f..81a8488 100644 --- a/pipeline_service/workspace.py +++ b/pipeline_service/workspace.py @@ -345,34 +345,57 @@ async def get_project_dir_pl(sor, uid, session_id='', pipeline_id=''): async def get_project_apps_modules(sor, uid, session_id=''): - """读项目目录下 {应用名}_spec.json,返回 (apps, modules)。 + """返回项目用到的 (apps, modules)。 - apps = 各 spec.json 的 app 字段;modules = referenced_modules + generated_modules 去重。 + 数据源(并集去重): + 1. 项目目录下各 *_spec.json 的 app / referenced_modules / generated_modules 字段 + 2. sd_project_repos 关联仓库——按仓库在机构空间的实际位置归类({space}/apps/ 或 + {space}/modules/);两个目录都不存在则不挂载(仓库可能尚未克隆)。 + (2026-09-01 修复:元景项目无 spec.json 但有 7 个关联仓库,工作空间树 + 因此看不到任何模块/应用仓库——仓库表是项目用哪些仓库的权威来源之一) """ import json as _json project_dir, _ = await get_project_dir(sor, uid, session_id) - if not project_dir or not os.path.isdir(project_dir): - return [], [] + space_dir, _ = await get_space_dir(sor, uid, session_id) apps = [] modules = set() + if project_dir and os.path.isdir(project_dir): + try: + for f in sorted(os.listdir(project_dir)): + if not f.endswith('_spec.json'): + continue + fp = os.path.join(project_dir, f) + try: + with open(fp, 'r', encoding='utf-8') as fh: + data = _json.loads(fh.read()) + except Exception: + continue + if not isinstance(data, dict): + continue + app = (data.get('app') or '').strip() + if app: + apps.append(app) + for m in (data.get('referenced_modules') or []) + (data.get('generated_modules') or []): + if isinstance(m, str) and m.strip(): + modules.add(m.strip()) + except Exception: + pass + # 关联仓库:按机构空间实际目录归类(仓库表是项目用哪些仓库的权威来源) try: - for f in sorted(os.listdir(project_dir)): - if not f.endswith('_spec.json'): - continue - fp = os.path.join(project_dir, f) - try: - with open(fp, 'r', encoding='utf-8') as fh: - data = _json.loads(fh.read()) - except Exception: - continue - if not isinstance(data, dict): - continue - app = (data.get('app') or '').strip() - if app: - apps.append(app) - for m in (data.get('referenced_modules') or []) + (data.get('generated_modules') or []): - if isinstance(m, str) and m.strip(): - modules.add(m.strip()) + pid = await get_session_project_id(sor, uid, session_id) + if pid and space_dir: + recs = await sor.sqlExe( + "SELECT repo_name FROM sd_project_repos WHERE project_id=${pid}$", + {"pid": pid}) + await sor.sqlExe("COMMIT", {}) + for r in (recs or []): + rn = (getattr(r, 'repo_name', '') or '').strip() + if not rn or '/' in rn: + continue + if os.path.isdir(os.path.join(space_dir, 'apps', rn)): + apps.append(rn) + elif os.path.isdir(os.path.join(space_dir, 'modules', rn)): + modules.add(rn) except Exception: pass return sorted(set(apps)), sorted(modules)