[patch] 修复CI/CD中的GBK编码问题
This commit is contained in:
@@ -2,7 +2,7 @@ name: GUI Version Release
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, develop ] # 临时添加 develop 用于测试
|
branches: [ master ] # 临时添加 develop 用于测试
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
gui-version-release:
|
gui-version-release:
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import subprocess
|
|||||||
|
|
||||||
def disable_logging():
|
def disable_logging():
|
||||||
"""自动禁用所有日志功能"""
|
"""自动禁用所有日志功能"""
|
||||||
print("🔧 正在禁用日志功能...")
|
print("Disabling logging functionality...")
|
||||||
|
|
||||||
# 备份原文件
|
# 备份原文件
|
||||||
files_to_backup = ['main.py', 'exe_file_logger.py']
|
files_to_backup = ['main.py', 'exe_file_logger.py']
|
||||||
for file_name in files_to_backup:
|
for file_name in files_to_backup:
|
||||||
if os.path.exists(file_name):
|
if os.path.exists(file_name):
|
||||||
shutil.copy(file_name, f'{file_name}.backup')
|
shutil.copy(file_name, f'{file_name}.backup')
|
||||||
print(f"✅ 已备份 {file_name}")
|
print(f"Backed up {file_name}")
|
||||||
|
|
||||||
# 1. 修改 main.py - 注释掉日志初始化
|
# 1. 修改 main.py - 注释掉日志初始化
|
||||||
if os.path.exists('main.py'):
|
if os.path.exists('main.py'):
|
||||||
@@ -38,7 +38,7 @@ def disable_logging():
|
|||||||
|
|
||||||
with open('main.py', 'w', encoding='utf-8') as f:
|
with open('main.py', 'w', encoding='utf-8') as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
print("✅ 已禁用 main.py 中的日志初始化")
|
print("Disabled logging in main.py")
|
||||||
|
|
||||||
# 2. 修改 exe_file_logger.py - 让所有函数变成空操作
|
# 2. 修改 exe_file_logger.py - 让所有函数变成空操作
|
||||||
if os.path.exists('exe_file_logger.py'):
|
if os.path.exists('exe_file_logger.py'):
|
||||||
@@ -56,9 +56,9 @@ def disable_logging():
|
|||||||
|
|
||||||
with open('exe_file_logger.py', 'w', encoding='utf-8') as f:
|
with open('exe_file_logger.py', 'w', encoding='utf-8') as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
print("✅ 已禁用 exe_file_logger.py 中的日志功能")
|
print("Disabled logging in exe_file_logger.py")
|
||||||
|
|
||||||
print("✅ 所有日志功能已禁用")
|
print("All logging functionality disabled")
|
||||||
|
|
||||||
def restore_logging():
|
def restore_logging():
|
||||||
"""恢复日志功能"""
|
"""恢复日志功能"""
|
||||||
@@ -68,12 +68,12 @@ def restore_logging():
|
|||||||
if os.path.exists(backup_file):
|
if os.path.exists(backup_file):
|
||||||
shutil.copy(backup_file, file_name)
|
shutil.copy(backup_file, file_name)
|
||||||
os.remove(backup_file)
|
os.remove(backup_file)
|
||||||
print(f"✅ 已恢复 {file_name}")
|
print(f"Restored {file_name}")
|
||||||
print("✅ 所有文件已恢复到开发环境配置")
|
print("All files restored to development configuration")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""主函数"""
|
"""主函数"""
|
||||||
print("🔥 生产环境打包工具(无日志版本)")
|
print("Production Build Tool (No Logging Version)")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -81,38 +81,38 @@ def main():
|
|||||||
disable_logging()
|
disable_logging()
|
||||||
|
|
||||||
# 2. 执行打包
|
# 2. 执行打包
|
||||||
print("\n🚀 开始打包...")
|
print("\nStarting build...")
|
||||||
result = subprocess.run(['python', 'quick_build.py'], capture_output=False)
|
result = subprocess.run(['python', 'quick_build.py'], capture_output=False)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
# 验证最终输出(quick_build.py 已统一输出到 MultiPlatformGUI)
|
# 验证最终输出(quick_build.py 已统一输出到 MultiPlatformGUI)
|
||||||
if os.path.exists('dist/MultiPlatformGUI'):
|
if os.path.exists('dist/MultiPlatformGUI'):
|
||||||
print("\n🎉 生产环境打包成功!")
|
print("\nProduction build completed successfully!")
|
||||||
print("📁 输出目录: dist/MultiPlatformGUI/")
|
print("Output directory: dist/MultiPlatformGUI/")
|
||||||
print("🔇 已禁用所有日志功能,客户端不会产生日志文件")
|
print("All logging disabled - client will not generate log files")
|
||||||
|
|
||||||
# 验证关键文件
|
# 验证关键文件
|
||||||
exe_path = 'dist/MultiPlatformGUI/main.exe'
|
exe_path = 'dist/MultiPlatformGUI/main.exe'
|
||||||
if os.path.exists(exe_path):
|
if os.path.exists(exe_path):
|
||||||
size = os.path.getsize(exe_path) / 1024 / 1024 # MB
|
size = os.path.getsize(exe_path) / 1024 / 1024 # MB
|
||||||
print(f"✅ 主程序: main.exe ({size:.1f} MB)")
|
print(f"Main executable: main.exe ({size:.1f} MB)")
|
||||||
else:
|
else:
|
||||||
print("⚠️ 主程序文件未找到")
|
print("WARNING: Main executable not found")
|
||||||
else:
|
else:
|
||||||
print("\n❌ 输出目录验证失败: 未找到 dist/MultiPlatformGUI")
|
print("\nERROR: Output directory verification failed - dist/MultiPlatformGUI not found")
|
||||||
else:
|
else:
|
||||||
print("\n❌ 打包失败")
|
print("\nERROR: Build failed")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ 打包过程出错: {e}")
|
print(f"ERROR: Build process error: {e}")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# 3. 恢复日志功能(用于开发)
|
# 3. 恢复日志功能(用于开发)
|
||||||
print("\n🔄 恢复开发环境配置...")
|
print("\nRestoring development configuration...")
|
||||||
restore_logging()
|
restore_logging()
|
||||||
|
|
||||||
print("\n" + "=" * 60)
|
print("\n" + "=" * 60)
|
||||||
input("按Enter键退出...")
|
input("Press Enter to exit...")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
@@ -42,7 +42,7 @@ VERSION = "1.0"
|
|||||||
WINDOW_TITLE = "AI回复连接入口-V1.0"
|
WINDOW_TITLE = "AI回复连接入口-V1.0"
|
||||||
|
|
||||||
# 应用版本号(用于版本检查)
|
# 应用版本号(用于版本检查)
|
||||||
APP_VERSION = "1.4.29"
|
APP_VERSION = "1.5.0"
|
||||||
|
|
||||||
# 平台特定配置
|
# 平台特定配置
|
||||||
PLATFORMS = {
|
PLATFORMS = {
|
||||||
|
|||||||
@@ -43,47 +43,47 @@ class NSISInstaller:
|
|||||||
match = re.search(r'APP_VERSION\s*=\s*["\']([^"\']+)["\']', content)
|
match = re.search(r'APP_VERSION\s*=\s*["\']([^"\']+)["\']', content)
|
||||||
if match:
|
if match:
|
||||||
version = match.group(1)
|
version = match.group(1)
|
||||||
print(f"📦 从 config.py 读取版本号: v{version}")
|
print(f"Read version from config.py: v{version}")
|
||||||
return version
|
return version
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 读取版本号失败: {e},使用默认版本")
|
print(f"WARNING: Failed to read version: {e}, using default version")
|
||||||
|
|
||||||
return "1.0.0"
|
return "1.0.0"
|
||||||
|
|
||||||
def check_prerequisites(self):
|
def check_prerequisites(self):
|
||||||
"""检查构建前提条件"""
|
"""检查构建前提条件"""
|
||||||
print("🔍 检查构建前提条件...")
|
print("Checking build prerequisites...")
|
||||||
|
|
||||||
# 检查NSIS安装
|
# 检查NSIS安装
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(['makensis', '/VERSION'],
|
result = subprocess.run(['makensis', '/VERSION'],
|
||||||
capture_output=True, text=True, check=True)
|
capture_output=True, text=True, check=True)
|
||||||
nsis_version = result.stdout.strip()
|
nsis_version = result.stdout.strip()
|
||||||
print(f"✅ NSIS 版本: {nsis_version}")
|
print(f"NSIS version: {nsis_version}")
|
||||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
print("❌ 错误: 未找到NSIS或makensis命令")
|
print("ERROR: NSIS or makensis command not found")
|
||||||
print(" 请从 https://nsis.sourceforge.io/Download 下载并安装NSIS")
|
print(" Please download and install NSIS from https://nsis.sourceforge.io/Download")
|
||||||
print(" 确保将NSIS添加到系统PATH环境变量")
|
print(" Make sure to add NSIS to system PATH")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查dist目录
|
# 检查dist目录
|
||||||
if not self.dist_dir.exists():
|
if not self.dist_dir.exists():
|
||||||
print(f"❌ 错误: 未找到构建输出目录 {self.dist_dir}")
|
print(f"ERROR: Build output directory not found: {self.dist_dir}")
|
||||||
print(" 请先运行 build_production.py 构建应用程序")
|
print(" Please run build_production.py first")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查主程序文件
|
# 检查主程序文件
|
||||||
exe_path = self.dist_dir / self.exe_name
|
exe_path = self.dist_dir / self.exe_name
|
||||||
if not exe_path.exists():
|
if not exe_path.exists():
|
||||||
print(f"❌ 错误: 未找到主程序文件 {exe_path}")
|
print(f"ERROR: Main executable not found: {exe_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print(f"✅ 找到主程序: {exe_path}")
|
print(f"Found main executable: {exe_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def prepare_assets(self):
|
def prepare_assets(self):
|
||||||
"""准备安装包资源文件"""
|
"""准备安装包资源文件"""
|
||||||
print("📁 准备资源文件...")
|
print("Preparing asset files...")
|
||||||
|
|
||||||
# 创建assets目录
|
# 创建assets目录
|
||||||
self.assets_dir.mkdir(exist_ok=True)
|
self.assets_dir.mkdir(exist_ok=True)
|
||||||
@@ -107,14 +107,14 @@ class NSISInstaller:
|
|||||||
img = Image.open(icon_source)
|
img = Image.open(icon_source)
|
||||||
ico_path = self.assets_dir / "icon.ico"
|
ico_path = self.assets_dir / "icon.ico"
|
||||||
img.save(ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
img.save(ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
||||||
print(f"✅ 转换主程序图标: {icon_source.name} -> icon.ico")
|
print(f"Converted main icon: {icon_source.name} -> icon.ico")
|
||||||
icon_found = True
|
icon_found = True
|
||||||
break
|
break
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("⚠️ 未安装PIL库,跳过图标转换")
|
print("WARNING: PIL library not installed, skipping icon conversion")
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 主程序图标转换失败: {e}")
|
print(f"WARNING: Main icon conversion failed: {e}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 转换卸载程序图标
|
# 转换卸载程序图标
|
||||||
@@ -125,17 +125,17 @@ class NSISInstaller:
|
|||||||
img = Image.open(uninstall_icon_source)
|
img = Image.open(uninstall_icon_source)
|
||||||
uninstall_ico_path = self.assets_dir / "uninstall_icon.ico"
|
uninstall_ico_path = self.assets_dir / "uninstall_icon.ico"
|
||||||
img.save(uninstall_ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
img.save(uninstall_ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
||||||
print(f"✅ 转换卸载程序图标: {uninstall_icon_source.name} -> uninstall_icon.ico")
|
print(f"Converted uninstall icon: {uninstall_icon_source.name} -> uninstall_icon.ico")
|
||||||
uninstall_icon_found = True
|
uninstall_icon_found = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("⚠️ 未安装PIL库,跳过卸载图标转换")
|
print("WARNING: PIL library not installed, skipping uninstall icon conversion")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 卸载程序图标转换失败: {e}")
|
print(f"WARNING: Uninstall icon conversion failed: {e}")
|
||||||
else:
|
else:
|
||||||
print("⚠️ 未找到卸载程序专用图标,将使用主程序图标")
|
print("WARNING: Uninstall icon not found, will use main icon")
|
||||||
|
|
||||||
if not icon_found:
|
if not icon_found:
|
||||||
print("⚠️ 未找到主程序图标文件,将使用默认图标")
|
print("WARNING: Main icon not found, will use default icon")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'main_icon': icon_found,
|
'main_icon': icon_found,
|
||||||
@@ -144,13 +144,13 @@ class NSISInstaller:
|
|||||||
|
|
||||||
def generate_nsis_script(self, icon_info):
|
def generate_nsis_script(self, icon_info):
|
||||||
"""生成NSIS安装脚本"""
|
"""生成NSIS安装脚本"""
|
||||||
print("📝 生成NSIS安装脚本...")
|
print("Generating NSIS installer script...")
|
||||||
|
|
||||||
# 标准化安装包命名(不带时间戳,便于固定下载地址)
|
# 标准化安装包命名(不带时间戳,便于固定下载地址)
|
||||||
installer_name = f"{self.app_name_en}_Setup_v{self.app_version}.exe"
|
installer_name = f"{self.app_name_en}_Setup_v{self.app_version}.exe"
|
||||||
# 示例: ShuiDi_AI_Assistant_Setup_v1.4.12.exe
|
# 示例: ShuiDi_AI_Assistant_Setup_v1.4.12.exe
|
||||||
|
|
||||||
print(f"📦 安装包名称: {installer_name}")
|
print(f"Installer name: {installer_name}")
|
||||||
|
|
||||||
nsis_content = f'''# 水滴AI客服智能助手 NSIS 安装脚本
|
nsis_content = f'''# 水滴AI客服智能助手 NSIS 安装脚本
|
||||||
# 自动生成于 {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
# 自动生成于 {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
||||||
@@ -262,7 +262,7 @@ SectionEnd
|
|||||||
with open(self.nsis_script, 'w', encoding='utf-8-sig') as f:
|
with open(self.nsis_script, 'w', encoding='utf-8-sig') as f:
|
||||||
f.write(nsis_content)
|
f.write(nsis_content)
|
||||||
|
|
||||||
print(f"✅ NSIS脚本已生成: {self.nsis_script}")
|
print(f"NSIS script generated: {self.nsis_script}")
|
||||||
return installer_name
|
return installer_name
|
||||||
|
|
||||||
def create_license_file(self):
|
def create_license_file(self):
|
||||||
@@ -287,11 +287,11 @@ SectionEnd
|
|||||||
with open(license_file, 'w', encoding='utf-8-sig') as f:
|
with open(license_file, 'w', encoding='utf-8-sig') as f:
|
||||||
f.write(license_content)
|
f.write(license_content)
|
||||||
|
|
||||||
print(f"✅ 许可证文件已创建: {license_file}")
|
print(f"License file created: {license_file}")
|
||||||
|
|
||||||
def build_installer(self):
|
def build_installer(self):
|
||||||
"""构建安装包"""
|
"""构建安装包"""
|
||||||
print("🚀 开始构建NSIS安装包...")
|
print("Building NSIS installer...")
|
||||||
|
|
||||||
# 创建输出目录
|
# 创建输出目录
|
||||||
self.output_dir.mkdir(exist_ok=True)
|
self.output_dir.mkdir(exist_ok=True)
|
||||||
@@ -302,22 +302,22 @@ SectionEnd
|
|||||||
result = subprocess.run(cmd, cwd=str(self.script_dir),
|
result = subprocess.run(cmd, cwd=str(self.script_dir),
|
||||||
capture_output=True, text=True, check=True)
|
capture_output=True, text=True, check=True)
|
||||||
|
|
||||||
print("✅ NSIS编译成功")
|
print("NSIS compilation successful")
|
||||||
if result.stdout:
|
if result.stdout:
|
||||||
print("NSIS输出:")
|
print("NSIS output:")
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print("❌ NSIS编译失败")
|
print("ERROR: NSIS compilation failed")
|
||||||
print(f"错误信息: {e.stderr}")
|
print(f"Error message: {e.stderr}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""执行完整的构建流程"""
|
"""执行完整的构建流程"""
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
print(f"🔧 {self.app_name} 安装包构建工具")
|
print(f"Installer Build Tool for {self.app_name}")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -343,18 +343,18 @@ SectionEnd
|
|||||||
if installer_path.exists():
|
if installer_path.exists():
|
||||||
installer_size = installer_path.stat().st_size / (1024 * 1024)
|
installer_size = installer_path.stat().st_size / (1024 * 1024)
|
||||||
print("\n" + "=" * 60)
|
print("\n" + "=" * 60)
|
||||||
print("🎉 安装包构建成功!")
|
print("Installer build completed successfully!")
|
||||||
print(f"📁 安装包位置: {installer_path}")
|
print(f"Installer location: {installer_path}")
|
||||||
print(f"📏 文件大小: {installer_size:.1f} MB")
|
print(f"File size: {installer_size:.1f} MB")
|
||||||
print("🚀 可以直接分发给用户使用")
|
print("Ready to distribute to users")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("❌ 安装包文件未找到")
|
print("ERROR: Installer file not found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ 构建过程出错: {e}")
|
print(f"ERROR: Build process error: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,4 +1,20 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.5.0",
|
||||||
|
"update_type": "minor",
|
||||||
|
"content": "实现更新版本管理",
|
||||||
|
"author": "Gitea Actions Bot",
|
||||||
|
"commit_hash": "8ecec1edbed34ef40869cf7a0c07fc33e81d9c37",
|
||||||
|
"commit_short_hash": "8ecec1ed",
|
||||||
|
"branch": "develop",
|
||||||
|
"release_time": "2025-10-11 15:47:09",
|
||||||
|
"download_url": "https://ks3-cn-guangzhou.ksyuncs.com/shuidrop-chat-server/installers/ShuiDi_AI_Assistant_Setup_v1.5.0.exe",
|
||||||
|
"stats": {
|
||||||
|
"files_changed": 6,
|
||||||
|
"lines_added": 265,
|
||||||
|
"lines_deleted": 168
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.4.29",
|
"version": "1.4.29",
|
||||||
"update_type": "patch",
|
"update_type": "patch",
|
||||||
|
|||||||
Reference in New Issue
Block a user