feat: 服务端集成自动打包流程

This commit is contained in:
shen
2026-07-17 22:34:04 +08:00
parent a2437a039d
commit d1f070b251
221 changed files with 7284 additions and 447 deletions
+48 -21
View File
@@ -36,6 +36,9 @@ def tmp_dirs(tmp_path):
(source_dir / "Podfile.lock").write_text("PODFILE CHECKSUM: abc")
(source_dir / "readoor.xcworkspace").mkdir()
(source_dir / "AutoPacking").mkdir()
vendor_dir = source_dir / "Vendor" / "RDEpubReaderView"
vendor_dir.mkdir(parents=True)
(vendor_dir / "RDEpubReaderView.podspec").write_text("Pod::Spec.new do |s| end")
(source_dir / "readoorTests").mkdir()
(source_dir / "podfile").write_text("pod 'AFNetworking'")
@@ -63,7 +66,7 @@ async def test_update_source_clone(tmp_path, log_streamer):
source_dir = tmp_path / "branches" / "main"
source_dir.parent.mkdir()
with patch("backend.services.build_service.GIT_REMOTE_URL", "git@github.com:test/repo.git"):
with patch("backend.services.build_service.get_git_remote_url", return_value="git@github.com:test/repo.git"):
with patch("asyncio.create_subprocess_exec", return_value=_make_mock_process()) as mock_exec:
await update_source("t1", source_dir, "main")
mock_exec.assert_called_once()
@@ -76,7 +79,7 @@ async def test_update_source_clone_no_remote(tmp_path, log_streamer):
"""目录不存在且未配置远程仓库时抛异常"""
source_dir = tmp_path / "branches" / "main"
with patch("backend.services.build_service.GIT_REMOTE_URL", ""):
with patch("backend.services.build_service.get_git_remote_url", return_value=""):
with pytest.raises(Exception, match="GIT_REMOTE_URL"):
await update_source("t1", source_dir, "main")
@@ -95,8 +98,9 @@ async def test_update_source_pull_existing(tmp_path, log_streamer):
call_count += 1
return _make_mock_process()
with patch("asyncio.create_subprocess_exec", side_effect=mock_exec):
await update_source("t1", source_dir, "dev")
with patch("backend.services.build_service.get_git_remote_url", return_value=""):
with patch("asyncio.create_subprocess_exec", side_effect=mock_exec):
await update_source("t1", source_dir, "dev")
assert call_count == 3 # fetch, checkout, pull
@@ -110,9 +114,10 @@ async def test_update_source_fetch_failure(tmp_path, log_streamer):
async def mock_exec(*args, **kwargs):
return _make_mock_process(returncode=1, output=b"error\n")
with patch("asyncio.create_subprocess_exec", side_effect=mock_exec):
with pytest.raises(Exception, match="git fetch 失败"):
await update_source("t1", source_dir, "dev")
with patch("backend.services.build_service.get_git_remote_url", return_value=""):
with patch("asyncio.create_subprocess_exec", side_effect=mock_exec):
with pytest.raises(Exception, match="git fetch 失败"):
await update_source("t1", source_dir, "dev")
# ---- copy_source_code ----
@@ -132,6 +137,8 @@ async def test_copy_source_code(tmp_dirs, log_streamer):
assert (result / "Pods").exists()
assert (result / "Podfile.lock").exists()
assert (result / "readoor.xcworkspace").exists()
assert (result / "Vendor" / "RDEpubReaderView" / "RDEpubReaderView.podspec").exists()
assert not (result / "AutoPacking").exists()
async def test_copy_source_code_excludes_git(tmp_dirs, log_streamer):
@@ -191,9 +198,8 @@ async def test_generate_config(tmp_path, log_streamer):
"schemes": {"1": {"name": "testScheme", "ossFloder": "test"}},
}
with patch("backend.services.build_service.AUTOPACKING_DIR", tmp_path / "AutoPacking"):
with patch("backend.routers.config.load_config", return_value=mock_config):
result = await generate_config("t1", task, build_dir)
with patch("backend.routers.config.load_config", return_value=mock_config):
result = await generate_config("t1", task, build_dir)
assert result["APPID"] == "guid-123"
assert result["SCHEME"] == "testScheme"
@@ -207,17 +213,11 @@ async def test_generate_config(tmp_path, log_streamer):
assert saved["APPID"] == "guid-123"
async def test_generate_config_reads_version(tmp_path, log_streamer):
""" start_build_app.py 读取版本号"""
async def test_generate_config_uses_saved_version(tmp_path, log_streamer):
"""服务配置读取版本号,不依赖分支源码脚本"""
build_dir = tmp_path / "build"
build_dir.mkdir()
autopacking = tmp_path / "AutoPacking"
autopacking.mkdir()
(autopacking / "start_build_app.py").write_text(
'App_Ver = "3.0.1"\nBuild_Ver = "3.0.1.0"\n'
)
task = MagicMock()
task.app_id = "1"
task.scheme_id = "1"
@@ -227,16 +227,43 @@ async def test_generate_config_reads_version(tmp_path, log_streamer):
mock_config = {
"apps": {"1": {"name": "App", "certificates": {}}},
"schemes": {"1": {"name": "sch", "ossFloder": "f"}},
"versions": {"app_ver": "3.0.1", "build_ver": "3.0.1.0"},
}
with patch("backend.services.build_service.AUTOPACKING_DIR", autopacking):
with patch("backend.routers.config.load_config", return_value=mock_config):
result = await generate_config("t1", task, build_dir)
with patch("backend.routers.config.load_config", return_value=mock_config):
result = await generate_config("t1", task, build_dir)
assert result["VERSION"] == "3.0.1"
assert result["BUILD_VERSION"] == "3.0.1.0"
async def test_generate_config_uses_server_theme_not_source_autopacking(tmp_path, log_streamer):
"""Web 打包不读取分支源码中的 AutoPacking 目录。"""
build_dir = tmp_path / "build"
(build_dir / "AutoPacking" / "ymh").mkdir(parents=True)
automation_dir = tmp_path / "automation"
default_theme = automation_dir / "themes" / "ymh"
default_theme.mkdir(parents=True)
task = MagicMock(app_id="1", scheme_id="1", build_type="Ad_Hoc", obfuscation=False)
mock_config = {
"apps": {
"1": {
"name": "App",
"certificates": {"Ad_Hoc": {"name": "com.example.app", "theme": "AutoPacking/ymh"}},
}
},
"schemes": {"1": {"name": "sch", "ossFloder": "f"}},
}
with patch("backend.routers.config.load_config", return_value=mock_config), \
patch("backend.services.build_service.AUTOMATION_DIR", automation_dir), \
patch("backend.services.build_service.SKINS_DIR", tmp_path / "skins"):
result = await generate_config("t1", task, build_dir)
assert result["THEME"] == str(default_theme)
# ---- _cleanup_old_builds ----
def test_cleanup_old_builds(tmp_path):