From 7fd3845447726002145c43ccf2e28653c941c181 Mon Sep 17 00:00:00 2001 From: shenlei Date: Mon, 20 Jul 2026 11:45:26 +0900 Subject: [PATCH] fix: disable git credential cache during builds --- .env.example | 6 +++--- backend/services/build_service.py | 20 +++++++++++++++++--- tests/test_build_service.py | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index 6aaef68..df80394 100644 --- a/.env.example +++ b/.env.example @@ -13,10 +13,10 @@ BUILD_BASE_DIR=./build # ---- 分支源码管理 ---- # Git 远程仓库地址;配置后所有分支共用 GIT_SOURCE_DIR -GIT_REMOTE_URL=https://git.example.com/group/repo.git +GIT_REMOTE_URL=https://pineapple.readoor.cn:9080/trn/triapp.git # 私有仓库:使用只读 Personal Access Token,不要使用账号登录密码。 -GIT_USERNAME=git-readonly-user -GIT_PASSWORD=cc774880b9d9b368c5f24a3821ee745dd5e4c949 +GIT_USERNAME=your-git-username +GIT_PASSWORD=your-read-repository-token # ---- 服务端口 ---- BACKEND_PORT=5002 diff --git a/backend/services/build_service.py b/backend/services/build_service.py index daf6340..348002e 100644 --- a/backend/services/build_service.py +++ b/backend/services/build_service.py @@ -66,6 +66,16 @@ _ERROR_RULES = [ ] +def _git_env() -> dict: + """为无人值守的构建任务禁用交互提示与凭据缓存写入。""" + env = os.environ.copy() + env["GIT_TERMINAL_PROMPT"] = "0" + return env + + +_GIT_NO_CREDENTIAL_HELPER = ("git", "-c", "credential.helper=") + + def _classify_build_error(output_lines: list, step: str) -> tuple: """解析构建输出,返回 (category, friendly_message) @@ -145,6 +155,7 @@ async def update_source(task_id: str, source_dir: Path, branch: str): """将共享源码工作目录强制同步到指定远程分支。""" remote_url = get_git_remote_url(with_credentials=True) remote_url_masked = mask_git_remote_url(remote_url) + git_env = _git_env() cloned = not source_dir.exists() if cloned: @@ -153,7 +164,8 @@ async def update_source(task_id: str, source_dir: Path, branch: str): source_dir.parent.mkdir(parents=True, exist_ok=True) await log_streamer.emit(task_id, f"初始化共享源码目录: {remote_url_masked}") process = await asyncio.create_subprocess_exec( - "git", "clone", remote_url, str(source_dir), + *_GIT_NO_CREDENTIAL_HELPER, "clone", remote_url, str(source_dir), + env=git_env, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, ) @@ -173,7 +185,8 @@ async def update_source(task_id: str, source_dir: Path, branch: str): if remote_url: process = await asyncio.create_subprocess_exec( - "git", "remote", "set-url", "origin", remote_url, + *_GIT_NO_CREDENTIAL_HELPER, "remote", "set-url", "origin", remote_url, + env=git_env, cwd=str(source_dir), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, ) await process.wait() @@ -188,7 +201,8 @@ async def update_source(task_id: str, source_dir: Path, branch: str): ] for command, error_message in commands: process = await asyncio.create_subprocess_exec( - *command, cwd=str(source_dir), stdout=asyncio.subprocess.PIPE, + *_GIT_NO_CREDENTIAL_HELPER, *command[1:], env=git_env, + cwd=str(source_dir), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, ) async for line in process.stdout: diff --git a/tests/test_build_service.py b/tests/test_build_service.py index 6806453..131e6b9 100644 --- a/tests/test_build_service.py +++ b/tests/test_build_service.py @@ -72,7 +72,7 @@ async def test_update_source_clone(tmp_path, log_streamer): with patch("asyncio.create_subprocess_exec", return_value=_make_mock_process()) as mock_exec: await update_source("t1", source_dir, "main") assert mock_exec.call_count == 6 # clone, set-url, fetch, checkout, reset, clean - assert mock_exec.call_args_list[0].args[:2] == ("git", "clone") + assert mock_exec.call_args_list[0].args[:4] == ("git", "-c", "credential.helper=", "clone") async def test_update_source_clone_no_remote(tmp_path, log_streamer):