refactor: restructure project to modern Python layout, separate src, tests, docs, examples
This commit is contained in:
190
.gitignore
vendored
Normal file
190
.gitignore
vendored
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be added to the global gitignore or merged into this project gitignore. For a PyCharm
|
||||||
|
# project, it is recommended to include the following files in version control:
|
||||||
|
# - .idea/modules.xml
|
||||||
|
# - .idea/*.iml
|
||||||
|
# - .idea/misc.xml
|
||||||
|
# - .idea/vcs.xml
|
||||||
|
# - .idea/workspace.xml
|
||||||
|
# - .idea/tasks.xml
|
||||||
|
# - .idea/usage.statistics.xml
|
||||||
|
# - .idea/shelf.xml
|
||||||
|
# - .idea/dictionaries
|
||||||
|
# - .idea/shelf
|
||||||
|
# - .idea/workspace.xml
|
||||||
|
# - .idea/tasks.xml
|
||||||
|
# - .idea/usage.statistics.xml
|
||||||
|
# - .idea/shelf.xml
|
||||||
|
# - .idea/dictionaries
|
||||||
|
# - .idea/shelf
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Config-Man specific
|
||||||
|
test_data/
|
||||||
|
*.log
|
||||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
204
PROJECT_STRUCTURE.md
Normal file
204
PROJECT_STRUCTURE.md
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
# Config-Man 项目结构
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
Config-Man 项目采用现代Python项目标准结构,将源代码、测试、文档和示例分开组织,便于维护和扩展。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
config-man/
|
||||||
|
├── src/ # 源代码目录
|
||||||
|
│ └── config_man/ # 主包
|
||||||
|
│ ├── __init__.py # 包初始化文件
|
||||||
|
│ ├── cli/ # CLI模块
|
||||||
|
│ │ ├── __init__.py
|
||||||
|
│ │ └── main.py # CLI主程序
|
||||||
|
│ ├── core/ # 核心功能模块
|
||||||
|
│ │ ├── __init__.py
|
||||||
|
│ │ ├── config_manager.py # 配置管理器
|
||||||
|
│ │ ├── display_manager.py # 显示管理器
|
||||||
|
│ │ └── view_command.py # 查看命令处理器
|
||||||
|
│ └── utils/ # 工具模块
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── crypto.py # 加密解密工具
|
||||||
|
│ └── mock_rclone.py # 模拟rclone环境
|
||||||
|
├── tests/ # 测试目录
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── unit/ # 单元测试
|
||||||
|
│ │ └── __init__.py
|
||||||
|
│ ├── integration/ # 集成测试
|
||||||
|
│ │ └── __init__.py
|
||||||
|
│ └── fixtures/ # 测试工具和数据
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── test_configs.py # 测试配置生成器
|
||||||
|
│ └── test_data/ # 测试数据目录
|
||||||
|
├── docs/ # 文档目录
|
||||||
|
│ ├── README.md # 文档说明
|
||||||
|
│ ├── USAGE.md # 使用说明
|
||||||
|
│ ├── progress-tracker.md # 进度跟踪
|
||||||
|
│ ├── requirements.md # 需求文档
|
||||||
|
│ └── workplan.md # 工作计划
|
||||||
|
├── examples/ # 示例目录
|
||||||
|
│ └── basic_usage.py # 基本使用示例
|
||||||
|
├── main.py # 主入口文件
|
||||||
|
├── pyproject.toml # 项目配置文件
|
||||||
|
├── README.md # 项目主文档
|
||||||
|
├── .gitignore # Git忽略文件
|
||||||
|
└── PROJECT_STRUCTURE.md # 项目结构说明(本文件)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 模块说明
|
||||||
|
|
||||||
|
### 源代码模块 (src/config_man/)
|
||||||
|
|
||||||
|
#### CLI模块 (cli/)
|
||||||
|
- **main.py**: CLI主程序,包含所有命令行命令的定义
|
||||||
|
- 使用Click框架实现命令行界面
|
||||||
|
- 支持view、suggest-update、force-update等命令
|
||||||
|
|
||||||
|
#### 核心模块 (core/)
|
||||||
|
- **config_manager.py**: 配置管理器,负责文件下载、解密、比较等核心功能
|
||||||
|
- **display_manager.py**: 显示管理器,负责格式化输出和表格显示
|
||||||
|
- **view_command.py**: 查看命令处理器,实现查看功能的核心逻辑
|
||||||
|
|
||||||
|
#### 工具模块 (utils/)
|
||||||
|
- **crypto.py**: 加密解密工具,提供DES加密解密功能
|
||||||
|
- **mock_rclone.py**: 模拟rclone环境,用于测试和开发
|
||||||
|
|
||||||
|
### 测试模块 (tests/)
|
||||||
|
|
||||||
|
#### 单元测试 (unit/)
|
||||||
|
- 测试各个模块的独立功能
|
||||||
|
- 测试边界条件和错误处理
|
||||||
|
|
||||||
|
#### 集成测试 (integration/)
|
||||||
|
- 测试模块间的集成功能
|
||||||
|
- 测试完整的工作流程
|
||||||
|
|
||||||
|
#### 测试工具 (fixtures/)
|
||||||
|
- **test_configs.py**: 测试配置生成器
|
||||||
|
- **test_data/**: 测试数据目录,包含模拟的配置文件
|
||||||
|
|
||||||
|
### 文档模块 (docs/)
|
||||||
|
- 包含所有项目文档
|
||||||
|
- 使用说明、需求文档、工作计划等
|
||||||
|
|
||||||
|
### 示例模块 (examples/)
|
||||||
|
- 提供使用示例和代码示例
|
||||||
|
- 帮助用户快速上手
|
||||||
|
|
||||||
|
## 设计原则
|
||||||
|
|
||||||
|
### 1. 分离关注点
|
||||||
|
- **源代码**: 只包含业务逻辑
|
||||||
|
- **测试**: 独立的测试代码和数据
|
||||||
|
- **文档**: 完整的使用和开发文档
|
||||||
|
- **示例**: 实际的使用示例
|
||||||
|
|
||||||
|
### 2. 模块化设计
|
||||||
|
- 每个模块职责单一
|
||||||
|
- 模块间依赖关系清晰
|
||||||
|
- 便于独立测试和维护
|
||||||
|
|
||||||
|
### 3. 可扩展性
|
||||||
|
- 新功能可以轻松添加到对应模块
|
||||||
|
- 测试可以独立添加
|
||||||
|
- 文档结构清晰,便于更新
|
||||||
|
|
||||||
|
### 4. 标准化
|
||||||
|
- 遵循Python项目标准结构
|
||||||
|
- 使用现代Python工具链
|
||||||
|
- 支持pip安装和开发模式
|
||||||
|
|
||||||
|
## 开发工作流
|
||||||
|
|
||||||
|
### 1. 开发新功能
|
||||||
|
```bash
|
||||||
|
# 在src/config_man/对应模块中添加代码
|
||||||
|
# 在tests/对应目录中添加测试
|
||||||
|
# 在docs/中添加文档
|
||||||
|
# 在examples/中添加示例
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 运行测试
|
||||||
|
```bash
|
||||||
|
# 运行所有测试
|
||||||
|
pytest
|
||||||
|
|
||||||
|
# 运行单元测试
|
||||||
|
pytest tests/unit/
|
||||||
|
|
||||||
|
# 运行集成测试
|
||||||
|
pytest tests/integration/
|
||||||
|
|
||||||
|
# 生成覆盖率报告
|
||||||
|
pytest --cov=src/config_man
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 代码质量检查
|
||||||
|
```bash
|
||||||
|
# 代码格式化
|
||||||
|
black src/ tests/
|
||||||
|
|
||||||
|
# 类型检查
|
||||||
|
mypy src/
|
||||||
|
|
||||||
|
# 代码检查
|
||||||
|
flake8 src/ tests/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 安装和发布
|
||||||
|
```bash
|
||||||
|
# 开发模式安装
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
# 构建包
|
||||||
|
python -m build
|
||||||
|
|
||||||
|
# 发布到PyPI
|
||||||
|
twine upload dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
### 1. 导入路径
|
||||||
|
- 使用相对导入在包内部
|
||||||
|
- 使用绝对导入从外部访问
|
||||||
|
- 避免循环导入
|
||||||
|
|
||||||
|
### 2. 测试组织
|
||||||
|
- 单元测试测试独立功能
|
||||||
|
- 集成测试测试模块协作
|
||||||
|
- 使用fixtures提供测试数据
|
||||||
|
|
||||||
|
### 3. 文档维护
|
||||||
|
- 代码和文档同步更新
|
||||||
|
- 提供完整的使用示例
|
||||||
|
- 保持文档结构清晰
|
||||||
|
|
||||||
|
### 4. 版本控制
|
||||||
|
- 合理的.gitignore配置
|
||||||
|
- 清晰的提交信息
|
||||||
|
- 版本号管理
|
||||||
|
|
||||||
|
## 扩展指南
|
||||||
|
|
||||||
|
### 添加新功能
|
||||||
|
1. 在`src/config_man/core/`中添加核心逻辑
|
||||||
|
2. 在`src/config_man/cli/main.py`中添加CLI命令
|
||||||
|
3. 在`tests/`中添加对应测试
|
||||||
|
4. 在`docs/`中更新文档
|
||||||
|
5. 在`examples/`中添加使用示例
|
||||||
|
|
||||||
|
### 添加新工具
|
||||||
|
1. 在`src/config_man/utils/`中添加工具函数
|
||||||
|
2. 在`tests/unit/`中添加单元测试
|
||||||
|
3. 在`docs/`中添加使用说明
|
||||||
|
|
||||||
|
### 添加新测试
|
||||||
|
1. 根据测试类型选择`tests/unit/`或`tests/integration/`
|
||||||
|
2. 使用`tests/fixtures/`中的测试数据
|
||||||
|
3. 遵循pytest最佳实践
|
||||||
|
|
||||||
|
这种项目结构确保了代码的可维护性、可测试性和可扩展性,符合现代Python项目的标准。
|
||||||
168
README.md
Normal file
168
README.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Config-Man CLI 工具
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
Config-Man 是一个Python CLI工具,用于管理存储在对象存储中的加密静态资源配置文件。该工具支持多版本管理,通过Cloudflare CDN进行分发,主要用于游戏应用的配置管理。
|
||||||
|
|
||||||
|
### 项目目标
|
||||||
|
- 简化多版本配置文件的查看和管理
|
||||||
|
- 支持版本升级策略(建议更新和强制更新)
|
||||||
|
- 确保配置文件的加密存储和CDN缓存同步
|
||||||
|
- 提供直观的配置对比功能
|
||||||
|
|
||||||
|
## 系统架构
|
||||||
|
|
||||||
|
### 存储架构
|
||||||
|
```
|
||||||
|
对象存储服务器
|
||||||
|
├── ab/
|
||||||
|
│ ├── 0_29/
|
||||||
|
│ │ ├── androidconfig.json (加密)
|
||||||
|
│ │ └── iosconfig.json (加密)
|
||||||
|
│ ├── 0_30/
|
||||||
|
│ │ ├── androidconfig.json (加密)
|
||||||
|
│ │ └── iosconfig.json (加密)
|
||||||
|
│ └── 1_00/
|
||||||
|
│ ├── androidconfig.json (加密)
|
||||||
|
│ └── iosconfig.json (加密)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技术栈
|
||||||
|
- **开发语言**: Python 3.13+
|
||||||
|
- **CLI框架**: Click 或 Typer
|
||||||
|
- **存储同步**: rclone
|
||||||
|
- **CDN服务**: Cloudflare
|
||||||
|
- **文件加密**: AES-256
|
||||||
|
- **配置格式**: JSON
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
### 功能1: 查看配置文件
|
||||||
|
|
||||||
|
对比显示对象存储和CDN中的配置内容,支持Android和iOS平台。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
config-man view --version <版本号>
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
- `--version`: 版本号,格式为 0.29, 0.30, 0.31 等
|
||||||
|
|
||||||
|
**功能特性**:
|
||||||
|
- 同时显示Android和iOS平台的配置文件
|
||||||
|
- 对比对象存储中的内容和CDN中的内容
|
||||||
|
- 使用表格格式漂亮地展示配置差异
|
||||||
|
- 支持JSON格式化输出
|
||||||
|
|
||||||
|
### 功能2: 建议更新
|
||||||
|
|
||||||
|
在目标版本的配置文件中添加 `Ver_New` 属性,提示用户有新版本可用。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
config-man suggest-update --platform <平台> --target-version <目标版本> --update-version <更新版本>
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
- `--platform`: 平台类型,支持 android 或 ios
|
||||||
|
- `--target-version`: 目标版本号,如 0.29
|
||||||
|
- `--update-version`: 更新版本号,如 0.30
|
||||||
|
|
||||||
|
### 功能3: 强制更新
|
||||||
|
|
||||||
|
直接更新目标版本的 `Ver` 属性,强制用户升级到新版本。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
config-man force-update --platform <平台> --target-version <目标版本> --update-version <更新版本>
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
- `--platform`: 平台类型,支持 android 或 ios
|
||||||
|
- `--target-version`: 目标版本号,如 0.29
|
||||||
|
- `--update-version`: 更新版本号,如 0.30
|
||||||
|
|
||||||
|
## 配置文件结构
|
||||||
|
|
||||||
|
### 配置项说明
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.28.2ece920695",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置项分类
|
||||||
|
- **API端点**: EventApiURL, FuncUrl
|
||||||
|
- **版本信息**: Ver, Ver_New
|
||||||
|
- **应用商店链接**: Google_Play_URL, APP_Store_URL
|
||||||
|
- **实时通信**: RTMPid, RTMServerEndpoint, RTMHmacSecret
|
||||||
|
- **功能配置**: PlayFabTitle, HeartBeat, FuncKey
|
||||||
|
|
||||||
|
## 技术要求
|
||||||
|
|
||||||
|
### 安全要求
|
||||||
|
- 配置文件在对象存储中加密存储
|
||||||
|
- 支持AES-256加密算法
|
||||||
|
- 加密密钥安全管理
|
||||||
|
- 操作日志记录
|
||||||
|
|
||||||
|
### 性能要求
|
||||||
|
- 配置文件查看响应时间 < 3秒
|
||||||
|
- 配置文件修改响应时间 < 5秒
|
||||||
|
- CDN缓存刷新响应时间 < 10秒
|
||||||
|
|
||||||
|
### 兼容性要求
|
||||||
|
- 支持Python 3.13+
|
||||||
|
- 支持Windows、macOS、Linux
|
||||||
|
- 支持rclone命令行工具
|
||||||
|
|
||||||
|
## 安装和使用
|
||||||
|
|
||||||
|
### 安装依赖
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置环境
|
||||||
|
```bash
|
||||||
|
# 配置rclone
|
||||||
|
rclone config
|
||||||
|
|
||||||
|
# 配置Cloudflare API
|
||||||
|
export CLOUDFLARE_API_TOKEN=your_token
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用示例
|
||||||
|
```bash
|
||||||
|
# 查看配置
|
||||||
|
config-man view --version 0.30
|
||||||
|
|
||||||
|
# 建议更新
|
||||||
|
config-man suggest-update --platform android --target-version 0.29 --update-version 0.30
|
||||||
|
|
||||||
|
# 强制更新
|
||||||
|
config-man force-update --platform ios --target-version 0.29 --update-version 0.30
|
||||||
|
```
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
### 常见错误场景
|
||||||
|
- 版本号不存在
|
||||||
|
- 平台类型错误
|
||||||
|
- 网络连接失败
|
||||||
|
- 文件加密/解密失败
|
||||||
|
- CDN刷新失败
|
||||||
|
|
||||||
|
### 错误处理策略
|
||||||
|
- 提供清晰的错误信息
|
||||||
|
- 支持重试机制
|
||||||
|
- 记录详细的操作日志
|
||||||
|
- 提供回滚功能
|
||||||
50
docs/README.md
Normal file
50
docs/README.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Config-Man 文档
|
||||||
|
|
||||||
|
本目录包含 Config-Man 项目的所有文档。
|
||||||
|
|
||||||
|
## 文档结构
|
||||||
|
|
||||||
|
- `README.md` - 项目主文档
|
||||||
|
- `USAGE.md` - 使用说明文档
|
||||||
|
- `progress-tracker.md` - 进度跟踪文档
|
||||||
|
- `requirements.md` - 需求文档
|
||||||
|
- `workplan.md` - 工作计划文档
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. 安装项目:
|
||||||
|
```bash
|
||||||
|
pip install -e .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 查看帮助:
|
||||||
|
```bash
|
||||||
|
python main.py --help
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 使用查看功能:
|
||||||
|
```bash
|
||||||
|
python main.py view --version 0.30 --mock
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发指南
|
||||||
|
|
||||||
|
1. 安装开发依赖:
|
||||||
|
```bash
|
||||||
|
pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 运行测试:
|
||||||
|
```bash
|
||||||
|
pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 代码格式化:
|
||||||
|
```bash
|
||||||
|
black src/ tests/
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 类型检查:
|
||||||
|
```bash
|
||||||
|
mypy src/
|
||||||
|
```
|
||||||
221
docs/USAGE.md
Normal file
221
docs/USAGE.md
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
# Config-Man 查看功能使用说明
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
Config-Man 的查看功能允许您对比显示对象存储和CDN中的配置内容,支持Android和iOS平台。
|
||||||
|
|
||||||
|
## 安装依赖
|
||||||
|
|
||||||
|
首先安装项目依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -e .
|
||||||
|
```
|
||||||
|
|
||||||
|
## 基本用法
|
||||||
|
|
||||||
|
### 1. 查看配置文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看版本 0.30 的配置文件
|
||||||
|
python main.py view --version 0.30
|
||||||
|
|
||||||
|
# 以JSON格式输出
|
||||||
|
python main.py view --version 0.30 --json
|
||||||
|
|
||||||
|
# 使用模拟环境进行测试
|
||||||
|
python main.py view --version 0.30 --mock
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 查看帮助信息
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看主命令帮助
|
||||||
|
python main.py --help
|
||||||
|
|
||||||
|
# 查看view命令帮助
|
||||||
|
python main.py view --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## 参数说明
|
||||||
|
|
||||||
|
### view 命令参数
|
||||||
|
|
||||||
|
- `--version`: 版本号,格式为 0.29, 0.30, 0.31 等(必需)
|
||||||
|
- `--json`: 以JSON格式输出(可选)
|
||||||
|
- `--storage-path`: 对象存储路径前缀,默认为 'ab'(可选)
|
||||||
|
- `--cdn-url`: CDN基础URL(可选)
|
||||||
|
- `--mock`: 使用模拟环境进行测试(可选)
|
||||||
|
|
||||||
|
## 输出格式
|
||||||
|
|
||||||
|
### 表格格式(默认)
|
||||||
|
|
||||||
|
```
|
||||||
|
版本: 0.30 | 平台: Android
|
||||||
|
┌─────────────────┬─────────────────────┬─────────────────────┬──────────┐
|
||||||
|
│ 配置项 │ 对象存储内容 │ CDN内容 │ 状态 │
|
||||||
|
├─────────────────┼─────────────────────┼─────────────────────┼──────────┤
|
||||||
|
│ Ver │ 0.30.2ghi789 │ 0.30.2ghi789 │ ✅ 一致 │
|
||||||
|
│ EventApiURL │ https://n3backend. │ https://n3backend. │ ✅ 一致 │
|
||||||
|
│ NewFeature │ enabled │ N/A │ ❌ 不同 │
|
||||||
|
│ ... │ ... │ ... │ ... │
|
||||||
|
└─────────────────┴─────────────────────┴─────────────────────┴──────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON格式
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.30",
|
||||||
|
"platform": "android",
|
||||||
|
"storage_config": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2ghi789",
|
||||||
|
"NewFeature": "enabled"
|
||||||
|
},
|
||||||
|
"cdn_config": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2ghi789"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 模拟环境测试
|
||||||
|
|
||||||
|
为了方便测试,项目提供了模拟环境:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用模拟环境测试
|
||||||
|
python main.py view --version 0.30 --mock
|
||||||
|
```
|
||||||
|
|
||||||
|
模拟环境会:
|
||||||
|
1. 自动创建测试配置文件
|
||||||
|
2. 模拟rclone命令
|
||||||
|
3. 提供完整的测试数据
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
### 常见错误
|
||||||
|
|
||||||
|
1. **版本号格式错误**
|
||||||
|
```
|
||||||
|
错误: 无效的版本号格式: 1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **rclone未安装**
|
||||||
|
```
|
||||||
|
错误: rclone 未安装或不可用。请先安装 rclone。
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **文件不存在**
|
||||||
|
```
|
||||||
|
警告: 无法从对象存储下载 ab/0_30/androidconfig.json: 文件不存在
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **网络连接失败**
|
||||||
|
```
|
||||||
|
警告: 无法从CDN获取 https://cdn.example.com/ab/0_30/androidconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置说明
|
||||||
|
|
||||||
|
### 配置文件结构
|
||||||
|
|
||||||
|
配置文件包含以下主要字段:
|
||||||
|
|
||||||
|
- **EventApiURL**: API端点URL
|
||||||
|
- **Ver**: 版本信息
|
||||||
|
- **PlayFabTitle**: PlayFab标题
|
||||||
|
- **Google_Play_URL**: Google Play商店链接
|
||||||
|
- **APP_Store_URL**: App Store链接
|
||||||
|
- **HeartBeat**: 心跳间隔
|
||||||
|
- **RTMPid**: RTM进程ID
|
||||||
|
- **RTMServerEndpoint**: RTM服务器端点
|
||||||
|
- **RTMHmacSecret**: RTM HMAC密钥
|
||||||
|
- **FuncUrl**: 功能URL
|
||||||
|
- **FuncKey**: 功能密钥
|
||||||
|
|
||||||
|
### 版本号转换
|
||||||
|
|
||||||
|
版本号会自动转换为存储路径格式:
|
||||||
|
- `0.29` → `0_29`
|
||||||
|
- `0.30` → `0_30`
|
||||||
|
- `1.00` → `1_00`
|
||||||
|
|
||||||
|
## 高级用法
|
||||||
|
|
||||||
|
### 自定义存储路径
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py view --version 0.30 --storage-path custom_path
|
||||||
|
```
|
||||||
|
|
||||||
|
### 指定CDN URL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py view --version 0.30 --cdn-url https://cdn.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 组合使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py view --version 0.30 --json --mock --storage-path test_data/ab
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 1. 安装问题
|
||||||
|
|
||||||
|
确保安装了所有依赖:
|
||||||
|
```bash
|
||||||
|
pip install click pycryptodome tabulate requests rich
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. rclone配置
|
||||||
|
|
||||||
|
如果使用真实环境,需要配置rclone:
|
||||||
|
```bash
|
||||||
|
rclone config
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 权限问题
|
||||||
|
|
||||||
|
确保有足够的权限访问对象存储和CDN。
|
||||||
|
|
||||||
|
### 4. 网络问题
|
||||||
|
|
||||||
|
检查网络连接和防火墙设置。
|
||||||
|
|
||||||
|
## 开发说明
|
||||||
|
|
||||||
|
### 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
config-man/
|
||||||
|
├── main.py # 主程序入口
|
||||||
|
├── appconfig_tool.py # 加密解密工具
|
||||||
|
├── config_manager.py # 配置管理器
|
||||||
|
├── display_manager.py # 显示管理器
|
||||||
|
├── view_command.py # 查看命令处理器
|
||||||
|
├── mock_rclone.py # 模拟rclone环境
|
||||||
|
└── test_configs.py # 测试配置生成器
|
||||||
|
```
|
||||||
|
|
||||||
|
### 扩展功能
|
||||||
|
|
||||||
|
要添加新的查看功能,可以:
|
||||||
|
|
||||||
|
1. 在 `config_manager.py` 中添加新的方法
|
||||||
|
2. 在 `display_manager.py` 中添加新的显示格式
|
||||||
|
3. 在 `view_command.py` 中添加新的处理逻辑
|
||||||
|
4. 在 `main.py` 中添加新的CLI命令
|
||||||
|
|
||||||
|
## 联系支持
|
||||||
|
|
||||||
|
如果遇到问题,请检查:
|
||||||
|
1. 版本号格式是否正确
|
||||||
|
2. 网络连接是否正常
|
||||||
|
3. rclone配置是否正确
|
||||||
|
4. 依赖是否完整安装
|
||||||
284
docs/progress-tracker.md
Normal file
284
docs/progress-tracker.md
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# Config-Man CLI 工具进度追踪
|
||||||
|
|
||||||
|
## 项目状态概览
|
||||||
|
|
||||||
|
- **项目名称**: Config-Man CLI 工具
|
||||||
|
- **当前阶段**: 项目初始化
|
||||||
|
- **开始日期**: [待定]
|
||||||
|
- **预计结束日期**: [待定]
|
||||||
|
- **实际进度**: 0%
|
||||||
|
- **剩余时间**: [待定]
|
||||||
|
|
||||||
|
## 阶段进度追踪
|
||||||
|
|
||||||
|
### 阶段1: 项目初始化 (1-2天)
|
||||||
|
**状态**: 🔄 进行中
|
||||||
|
**进度**: 0%
|
||||||
|
**开始时间**: [待定]
|
||||||
|
**预计完成**: [待定]
|
||||||
|
|
||||||
|
#### 任务1.1: 环境搭建
|
||||||
|
- [ ] 创建Python虚拟环境
|
||||||
|
- [ ] 安装项目依赖
|
||||||
|
- [ ] 配置开发环境
|
||||||
|
- [ ] 设置代码仓库
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务1.2: 项目结构设计
|
||||||
|
- [ ] 设计项目目录结构
|
||||||
|
- [ ] 创建基础模块
|
||||||
|
- [ ] 配置CLI框架
|
||||||
|
- [ ] 设置配置文件管理
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务1.3: 配置文件管理
|
||||||
|
- [ ] 实现配置文件加密/解密功能
|
||||||
|
- [ ] 实现对象存储连接
|
||||||
|
- [ ] 实现rclone集成
|
||||||
|
- [ ] 实现基础文件操作
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
### 阶段2: 核心功能开发 (3-4天)
|
||||||
|
**状态**: ⏳ 待开始
|
||||||
|
**进度**: 0%
|
||||||
|
**开始时间**: [待定]
|
||||||
|
**预计完成**: [待定]
|
||||||
|
|
||||||
|
#### 任务2.1: 查看配置文件功能
|
||||||
|
- [ ] 实现版本号转换逻辑 (0.29 → 0_29)
|
||||||
|
- [ ] 实现文件下载和解密
|
||||||
|
- [ ] 实现CDN内容获取
|
||||||
|
- [ ] 实现配置对比显示
|
||||||
|
- [ ] 实现格式化输出 (表格格式)
|
||||||
|
- [ ] 实现Android和iOS平台同时显示
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务2.2: 建议更新功能
|
||||||
|
- [ ] 实现配置文件读取和解析
|
||||||
|
- [ ] 实现Ver_New属性添加逻辑
|
||||||
|
- [ ] 实现文件加密和上传
|
||||||
|
- [ ] 实现CDN缓存刷新
|
||||||
|
- [ ] 实现错误处理和回滚
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务2.3: 强制更新功能
|
||||||
|
- [ ] 实现Ver属性更新逻辑
|
||||||
|
- [ ] 实现文件加密和上传
|
||||||
|
- [ ] 实现CDN缓存刷新
|
||||||
|
- [ ] 实现错误处理和回滚
|
||||||
|
- [ ] 实现安全确认机制
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务2.4: CLI框架完善
|
||||||
|
- [ ] 实现命令行参数解析
|
||||||
|
- [ ] 实现帮助信息
|
||||||
|
- [ ] 实现错误提示
|
||||||
|
- [ ] 实现日志记录
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
### 阶段3: 集成测试 (2-3天)
|
||||||
|
**状态**: ⏳ 待开始
|
||||||
|
**进度**: 0%
|
||||||
|
**开始时间**: [待定]
|
||||||
|
**预计完成**: [待定]
|
||||||
|
|
||||||
|
#### 任务3.1: 单元测试
|
||||||
|
- [ ] 编写配置文件处理测试
|
||||||
|
- [ ] 编写加密解密测试
|
||||||
|
- [ ] 编写CLI命令测试
|
||||||
|
- [ ] 编写版本号转换测试
|
||||||
|
- [ ] 编写JSON处理测试
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务3.2: 集成测试
|
||||||
|
- [ ] 测试对象存储连接
|
||||||
|
- [ ] 测试CDN缓存刷新
|
||||||
|
- [ ] 测试完整工作流程
|
||||||
|
- [ ] 测试多版本场景
|
||||||
|
- [ ] 测试多平台场景
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务3.3: 错误处理测试
|
||||||
|
- [ ] 测试网络错误处理
|
||||||
|
- [ ] 测试文件不存在错误
|
||||||
|
- [ ] 测试参数验证错误
|
||||||
|
- [ ] 测试加密解密错误
|
||||||
|
- [ ] 测试CDN刷新错误
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
### 阶段4: 文档和部署 (1-2天)
|
||||||
|
**状态**: ⏳ 待开始
|
||||||
|
**进度**: 0%
|
||||||
|
**开始时间**: [待定]
|
||||||
|
**预计完成**: [待定]
|
||||||
|
|
||||||
|
#### 任务4.1: 文档编写
|
||||||
|
- [ ] 编写用户使用手册
|
||||||
|
- [ ] 编写API文档
|
||||||
|
- [ ] 编写部署指南
|
||||||
|
- [ ] 编写故障排除指南
|
||||||
|
- [ ] 更新README文档
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务4.2: 部署准备
|
||||||
|
- [ ] 创建安装脚本
|
||||||
|
- [ ] 配置CI/CD流程
|
||||||
|
- [ ] 准备发布包
|
||||||
|
- [ ] 创建配置文件模板
|
||||||
|
- [ ] 设置环境变量配置
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
### 阶段5: 验收测试 (1天)
|
||||||
|
**状态**: ⏳ 待开始
|
||||||
|
**进度**: 0%
|
||||||
|
**开始时间**: [待定]
|
||||||
|
**预计完成**: [待定]
|
||||||
|
|
||||||
|
#### 任务5.1: 功能验收
|
||||||
|
- [ ] 验证所有CLI命令
|
||||||
|
- [ ] 验证配置文件管理
|
||||||
|
- [ ] 验证CDN缓存刷新
|
||||||
|
- [ ] 验证错误处理
|
||||||
|
- [ ] 验证文档完整性
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
#### 任务5.2: 性能验收
|
||||||
|
- [ ] 测试响应时间
|
||||||
|
- [ ] 测试并发处理
|
||||||
|
- [ ] 测试错误恢复
|
||||||
|
- [ ] 测试内存使用
|
||||||
|
- [ ] 测试CPU使用
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
|
||||||
|
## 里程碑追踪
|
||||||
|
|
||||||
|
### 里程碑1: 项目初始化完成
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **计划时间**: 第2天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
- **交付物**: 基础框架和配置文件管理功能
|
||||||
|
- **验收标准**: 可以成功操作加密的配置文件
|
||||||
|
|
||||||
|
### 里程碑2: 核心功能完成
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **计划时间**: 第6天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
- **交付物**: 三个主要CLI功能
|
||||||
|
- **验收标准**: 所有命令正常工作
|
||||||
|
|
||||||
|
### 里程碑3: 测试完成
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **计划时间**: 第9天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
- **交付物**: 测试报告和修复的问题
|
||||||
|
- **验收标准**: 测试覆盖率 > 80%,无严重bug
|
||||||
|
|
||||||
|
### 里程碑4: 项目交付
|
||||||
|
- **状态**: ⏳ 待开始
|
||||||
|
- **计划时间**: 第12天
|
||||||
|
- **实际时间**: [待定]
|
||||||
|
- **交付物**: 完整的CLI工具和文档
|
||||||
|
- **验收标准**: 满足所有需求,可以投入使用
|
||||||
|
|
||||||
|
## 问题追踪
|
||||||
|
|
||||||
|
### 已解决问题
|
||||||
|
| 问题ID | 问题描述 | 解决方案 | 解决时间 | 负责人 |
|
||||||
|
|--------|----------|----------|----------|--------|
|
||||||
|
| - | - | - | - | - |
|
||||||
|
|
||||||
|
### 待解决问题
|
||||||
|
| 问题ID | 问题描述 | 优先级 | 状态 | 负责人 | 预计解决时间 |
|
||||||
|
|--------|----------|--------|------|--------|--------------|
|
||||||
|
| - | - | - | - | - | - |
|
||||||
|
|
||||||
|
### 风险追踪
|
||||||
|
| 风险ID | 风险描述 | 影响程度 | 缓解措施 | 状态 | 负责人 |
|
||||||
|
|--------|----------|----------|----------|------|--------|
|
||||||
|
| R001 | 对象存储API集成复杂性 | 高 | 使用rclone作为统一接口 | 监控中 | [待定] |
|
||||||
|
| R002 | CDN缓存刷新API限制 | 中 | 实现重试机制和错误处理 | 监控中 | [待定] |
|
||||||
|
| R003 | CLI框架学习成本 | 低 | 选择文档完善的框架 | 监控中 | [待定] |
|
||||||
|
|
||||||
|
## 团队工作负载
|
||||||
|
|
||||||
|
### 本周工作负载
|
||||||
|
| 团队成员 | 当前任务 | 预计完成时间 | 工作负载 | 备注 |
|
||||||
|
|----------|----------|--------------|----------|------|
|
||||||
|
| [待定] | - | - | - | - |
|
||||||
|
|
||||||
|
### 下周工作计划
|
||||||
|
| 团队成员 | 计划任务 | 预计开始时间 | 预计完成时间 | 备注 |
|
||||||
|
|----------|----------|--------------|--------------|------|
|
||||||
|
| [待定] | - | - | - | - |
|
||||||
|
|
||||||
|
## 质量指标
|
||||||
|
|
||||||
|
### 代码质量
|
||||||
|
- **测试覆盖率**: 0% (目标: >80%)
|
||||||
|
- **代码审查**: 0% (目标: 100%)
|
||||||
|
- **静态分析**: 0% (目标: 100%)
|
||||||
|
|
||||||
|
### 性能指标
|
||||||
|
- **配置文件查看响应时间**: [待测试] (目标: <3秒)
|
||||||
|
- **配置文件修改响应时间**: [待测试] (目标: <5秒)
|
||||||
|
- **CDN缓存刷新响应时间**: [待测试] (目标: <10秒)
|
||||||
|
|
||||||
|
### 文档质量
|
||||||
|
- **用户手册**: 0% (目标: 100%)
|
||||||
|
- **API文档**: 0% (目标: 100%)
|
||||||
|
- **部署指南**: 0% (目标: 100%)
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
### 2024年[待定]
|
||||||
|
- 创建项目进度追踪文档
|
||||||
|
- 初始化所有任务状态为待开始
|
||||||
|
- 设置里程碑和验收标准
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**最后更新**: [待定]
|
||||||
|
**更新人**: [待定]
|
||||||
|
**下次更新**: [待定]
|
||||||
232
docs/requirements.md
Normal file
232
docs/requirements.md
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
# Config-Man CLI 工具需求文档
|
||||||
|
|
||||||
|
## 1. 项目概述
|
||||||
|
|
||||||
|
### 1.1 项目背景
|
||||||
|
开发一个Python CLI工具,用于管理存储在对象存储中的加密静态资源配置文件。该工具支持多版本管理,通过Cloudflare CDN进行分发,主要用于游戏应用的配置管理。
|
||||||
|
|
||||||
|
### 1.2 项目目标
|
||||||
|
- 简化多版本配置文件的查看和管理
|
||||||
|
- 支持版本升级策略(建议更新和强制更新)
|
||||||
|
- 确保配置文件的加密存储和CDN缓存同步
|
||||||
|
- 提供直观的配置对比功能
|
||||||
|
|
||||||
|
## 2. 系统架构
|
||||||
|
|
||||||
|
### 2.1 存储架构
|
||||||
|
```
|
||||||
|
对象存储服务器
|
||||||
|
├── ab/
|
||||||
|
│ ├── 0_29/
|
||||||
|
│ │ ├── androidconfig.json (加密)
|
||||||
|
│ │ └── iosconfig.json (加密)
|
||||||
|
│ ├── 0_30/
|
||||||
|
│ │ ├── androidconfig.json (加密)
|
||||||
|
│ │ └── iosconfig.json (加密)
|
||||||
|
│ └── 1_00/
|
||||||
|
│ ├── androidconfig.json (加密)
|
||||||
|
│ └── iosconfig.json (加密)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 技术栈
|
||||||
|
- **开发语言**: Python 3.13+
|
||||||
|
- **CLI框架**: Click 或 Typer
|
||||||
|
- **存储同步**: rclone
|
||||||
|
- **CDN服务**: Cloudflare
|
||||||
|
- **文件加密**: AES-256
|
||||||
|
- **配置格式**: JSON
|
||||||
|
|
||||||
|
## 3. 功能需求
|
||||||
|
|
||||||
|
### 3.1 功能1: 查看配置文件
|
||||||
|
|
||||||
|
#### 3.1.1 功能描述
|
||||||
|
对比显示对象存储和CDN中的配置内容,支持Android和iOS平台。
|
||||||
|
|
||||||
|
#### 3.1.2 命令行格式
|
||||||
|
```bash
|
||||||
|
config-man view --version <版本号>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.1.3 参数说明
|
||||||
|
- `--version`: 版本号,格式为 0.29, 0.30, 0.31 等
|
||||||
|
|
||||||
|
#### 3.1.4 功能特性
|
||||||
|
- 同时显示Android和iOS平台的配置文件
|
||||||
|
- 对比对象存储中的内容和CDN中的内容
|
||||||
|
- 使用表格格式漂亮地展示配置差异
|
||||||
|
- 支持JSON格式化输出
|
||||||
|
|
||||||
|
#### 3.1.5 输出示例
|
||||||
|
```
|
||||||
|
版本: 0.30
|
||||||
|
平台: Android
|
||||||
|
┌─────────────────┬─────────────────────┬─────────────────────┐
|
||||||
|
│ 配置项 │ 对象存储内容 │ CDN内容 │
|
||||||
|
├─────────────────┼─────────────────────┼─────────────────────┤
|
||||||
|
│ Ver │ 0.30.1abc123 │ 0.30.1abc123 │
|
||||||
|
│ EventApiURL │ https://... │ https://... │
|
||||||
|
│ PlayFabTitle │ B066F │ B066F │
|
||||||
|
│ ... │ ... │ ... │
|
||||||
|
└─────────────────┴─────────────────────┴─────────────────────┘
|
||||||
|
|
||||||
|
平台: iOS
|
||||||
|
┌─────────────────┬─────────────────────┬─────────────────────┐
|
||||||
|
│ 配置项 │ 对象存储内容 │ CDN内容 │
|
||||||
|
├─────────────────┼─────────────────────┼─────────────────────┤
|
||||||
|
│ Ver │ 0.30.1def456 │ 0.30.1def456 │
|
||||||
|
│ ... │ ... │ ... │
|
||||||
|
└─────────────────┴─────────────────────┴─────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 功能2: 建议更新
|
||||||
|
|
||||||
|
#### 3.2.1 功能描述
|
||||||
|
在目标版本的配置文件中添加 `Ver_New` 属性,提示用户有新版本可用。
|
||||||
|
|
||||||
|
#### 3.2.2 命令行格式
|
||||||
|
```bash
|
||||||
|
config-man suggest-update --platform <平台> --target-version <目标版本> --update-version <更新版本>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2.3 参数说明
|
||||||
|
- `--platform`: 平台类型,支持 android 或 ios
|
||||||
|
- `--target-version`: 目标版本号,如 0.29
|
||||||
|
- `--update-version`: 更新版本号,如 0.30
|
||||||
|
|
||||||
|
#### 3.2.4 功能特性
|
||||||
|
- 在目标版本配置中添加 `Ver_New` 属性
|
||||||
|
- `Ver_New` 的值设为更新版本的 `Ver` 属性值
|
||||||
|
- 自动加密并上传到对象存储
|
||||||
|
- 自动刷新CDN缓存
|
||||||
|
|
||||||
|
#### 3.2.5 配置变更示例
|
||||||
|
```json
|
||||||
|
// 修改前
|
||||||
|
{
|
||||||
|
"Ver": "0.29.1abc123",
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"PlayFabTitle": "B066F"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改后
|
||||||
|
{
|
||||||
|
"Ver": "0.29.1abc123",
|
||||||
|
"Ver_New": "0.30.1def456",
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"PlayFabTitle": "B066F"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 功能3: 强制更新
|
||||||
|
|
||||||
|
#### 3.3.1 功能描述
|
||||||
|
直接更新目标版本的 `Ver` 属性,强制用户升级到新版本。
|
||||||
|
|
||||||
|
#### 3.3.2 命令行格式
|
||||||
|
```bash
|
||||||
|
config-man force-update --platform <平台> --target-version <目标版本> --update-version <更新版本>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.3 参数说明
|
||||||
|
- `--platform`: 平台类型,支持 android 或 ios
|
||||||
|
- `--target-version`: 目标版本号,如 0.29
|
||||||
|
- `--update-version`: 更新版本号,如 0.30
|
||||||
|
|
||||||
|
#### 3.3.4 功能特性
|
||||||
|
- 将目标版本的 `Ver` 属性值改为更新版本的 `Ver` 属性值
|
||||||
|
- 自动加密并上传到对象存储
|
||||||
|
- 自动刷新CDN缓存
|
||||||
|
|
||||||
|
#### 3.3.5 配置变更示例
|
||||||
|
```json
|
||||||
|
// 修改前
|
||||||
|
{
|
||||||
|
"Ver": "0.29.1abc123",
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"PlayFabTitle": "B066F"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改后
|
||||||
|
{
|
||||||
|
"Ver": "0.30.1def456",
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"PlayFabTitle": "B066F"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 配置文件结构
|
||||||
|
|
||||||
|
### 4.1 配置项说明
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.28.2ece920695",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 配置项分类
|
||||||
|
- **API端点**: EventApiURL, FuncUrl
|
||||||
|
- **版本信息**: Ver, Ver_New
|
||||||
|
- **应用商店链接**: Google_Play_URL, APP_Store_URL
|
||||||
|
- **实时通信**: RTMPid, RTMServerEndpoint, RTMHmacSecret
|
||||||
|
- **功能配置**: PlayFabTitle, HeartBeat, FuncKey
|
||||||
|
|
||||||
|
## 5. 技术要求
|
||||||
|
|
||||||
|
### 5.1 安全要求
|
||||||
|
- 配置文件在对象存储中加密存储
|
||||||
|
- 支持AES-256加密算法
|
||||||
|
- 加密密钥安全管理
|
||||||
|
- 操作日志记录
|
||||||
|
|
||||||
|
### 5.2 性能要求
|
||||||
|
- 配置文件查看响应时间 < 3秒
|
||||||
|
- 配置文件修改响应时间 < 5秒
|
||||||
|
- CDN缓存刷新响应时间 < 10秒
|
||||||
|
|
||||||
|
### 5.3 兼容性要求
|
||||||
|
- 支持Python 3.13+
|
||||||
|
- 支持Windows、macOS、Linux
|
||||||
|
- 支持rclone命令行工具
|
||||||
|
|
||||||
|
## 6. 错误处理
|
||||||
|
|
||||||
|
### 6.1 常见错误场景
|
||||||
|
- 版本号不存在
|
||||||
|
- 平台类型错误
|
||||||
|
- 网络连接失败
|
||||||
|
- 文件加密/解密失败
|
||||||
|
- CDN刷新失败
|
||||||
|
|
||||||
|
### 6.2 错误处理策略
|
||||||
|
- 提供清晰的错误信息
|
||||||
|
- 支持重试机制
|
||||||
|
- 记录详细的操作日志
|
||||||
|
- 提供回滚功能
|
||||||
|
|
||||||
|
## 7. 非功能性需求
|
||||||
|
|
||||||
|
### 7.1 可用性
|
||||||
|
- 提供清晰的命令行帮助信息
|
||||||
|
- 支持命令自动补全
|
||||||
|
- 提供详细的错误提示
|
||||||
|
|
||||||
|
### 7.2 可维护性
|
||||||
|
- 模块化设计
|
||||||
|
- 完善的日志记录
|
||||||
|
- 清晰的代码注释
|
||||||
|
|
||||||
|
### 7.3 可扩展性
|
||||||
|
- 支持新的配置文件格式
|
||||||
|
- 支持新的存储后端
|
||||||
|
- 支持新的CDN服务商
|
||||||
246
docs/workplan.md
Normal file
246
docs/workplan.md
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# Config-Man CLI 工具工作计划
|
||||||
|
|
||||||
|
## 项目概览
|
||||||
|
|
||||||
|
- **项目名称**: Config-Man CLI 工具
|
||||||
|
- **预计工期**: 8-12天
|
||||||
|
- **开始日期**: [待定]
|
||||||
|
- **结束日期**: [待定]
|
||||||
|
- **项目经理**: [待定]
|
||||||
|
|
||||||
|
## 阶段1: 项目初始化 (1-2天)
|
||||||
|
|
||||||
|
### 任务1.1: 环境搭建
|
||||||
|
- [ ] 创建Python虚拟环境
|
||||||
|
- [ ] 安装项目依赖
|
||||||
|
- [ ] 配置开发环境
|
||||||
|
- [ ] 设置代码仓库
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **完成标准**: 开发环境可以正常运行
|
||||||
|
|
||||||
|
### 任务1.2: 项目结构设计
|
||||||
|
- [ ] 设计项目目录结构
|
||||||
|
- [ ] 创建基础模块
|
||||||
|
- [ ] 配置CLI框架
|
||||||
|
- [ ] 设置配置文件管理
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **完成标准**: 项目结构清晰,基础框架可用
|
||||||
|
|
||||||
|
### 任务1.3: 配置文件管理
|
||||||
|
- [ ] 实现配置文件加密/解密功能
|
||||||
|
- [ ] 实现对象存储连接
|
||||||
|
- [ ] 实现rclone集成
|
||||||
|
- [ ] 实现基础文件操作
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 可以成功下载、解密、加密、上传配置文件
|
||||||
|
|
||||||
|
## 阶段2: 核心功能开发 (3-4天)
|
||||||
|
|
||||||
|
### 任务2.1: 查看配置文件功能
|
||||||
|
- [ ] 实现版本号转换逻辑 (0.29 → 0_29)
|
||||||
|
- [ ] 实现文件下载和解密
|
||||||
|
- [ ] 实现CDN内容获取
|
||||||
|
- [ ] 实现配置对比显示
|
||||||
|
- [ ] 实现格式化输出 (表格格式)
|
||||||
|
- [ ] 实现Android和iOS平台同时显示
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1.5天
|
||||||
|
- **完成标准**: `config-man view --version 0.30` 命令正常工作
|
||||||
|
|
||||||
|
### 任务2.2: 建议更新功能
|
||||||
|
- [ ] 实现配置文件读取和解析
|
||||||
|
- [ ] 实现Ver_New属性添加逻辑
|
||||||
|
- [ ] 实现文件加密和上传
|
||||||
|
- [ ] 实现CDN缓存刷新
|
||||||
|
- [ ] 实现错误处理和回滚
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: `config-man suggest-update` 命令正常工作
|
||||||
|
|
||||||
|
### 任务2.3: 强制更新功能
|
||||||
|
- [ ] 实现Ver属性更新逻辑
|
||||||
|
- [ ] 实现文件加密和上传
|
||||||
|
- [ ] 实现CDN缓存刷新
|
||||||
|
- [ ] 实现错误处理和回滚
|
||||||
|
- [ ] 实现安全确认机制
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: `config-man force-update` 命令正常工作
|
||||||
|
|
||||||
|
### 任务2.4: CLI框架完善
|
||||||
|
- [ ] 实现命令行参数解析
|
||||||
|
- [ ] 实现帮助信息
|
||||||
|
- [ ] 实现错误提示
|
||||||
|
- [ ] 实现日志记录
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **完成标准**: CLI界面友好,错误提示清晰
|
||||||
|
|
||||||
|
## 阶段3: 集成测试 (2-3天)
|
||||||
|
|
||||||
|
### 任务3.1: 单元测试
|
||||||
|
- [ ] 编写配置文件处理测试
|
||||||
|
- [ ] 编写加密解密测试
|
||||||
|
- [ ] 编写CLI命令测试
|
||||||
|
- [ ] 编写版本号转换测试
|
||||||
|
- [ ] 编写JSON处理测试
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 测试覆盖率 > 80%
|
||||||
|
|
||||||
|
### 任务3.2: 集成测试
|
||||||
|
- [ ] 测试对象存储连接
|
||||||
|
- [ ] 测试CDN缓存刷新
|
||||||
|
- [ ] 测试完整工作流程
|
||||||
|
- [ ] 测试多版本场景
|
||||||
|
- [ ] 测试多平台场景
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 所有功能在真实环境中正常工作
|
||||||
|
|
||||||
|
### 任务3.3: 错误处理测试
|
||||||
|
- [ ] 测试网络错误处理
|
||||||
|
- [ ] 测试文件不存在错误
|
||||||
|
- [ ] 测试参数验证错误
|
||||||
|
- [ ] 测试加密解密错误
|
||||||
|
- [ ] 测试CDN刷新错误
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 错误处理完善,用户体验良好
|
||||||
|
|
||||||
|
## 阶段4: 文档和部署 (1-2天)
|
||||||
|
|
||||||
|
### 任务4.1: 文档编写
|
||||||
|
- [ ] 编写用户使用手册
|
||||||
|
- [ ] 编写API文档
|
||||||
|
- [ ] 编写部署指南
|
||||||
|
- [ ] 编写故障排除指南
|
||||||
|
- [ ] 更新README文档
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 文档完整,易于理解
|
||||||
|
|
||||||
|
### 任务4.2: 部署准备
|
||||||
|
- [ ] 创建安装脚本
|
||||||
|
- [ ] 配置CI/CD流程
|
||||||
|
- [ ] 准备发布包
|
||||||
|
- [ ] 创建配置文件模板
|
||||||
|
- [ ] 设置环境变量配置
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 1天
|
||||||
|
- **完成标准**: 可以一键部署和安装
|
||||||
|
|
||||||
|
## 阶段5: 验收测试 (1天)
|
||||||
|
|
||||||
|
### 任务5.1: 功能验收
|
||||||
|
- [ ] 验证所有CLI命令
|
||||||
|
- [ ] 验证配置文件管理
|
||||||
|
- [ ] 验证CDN缓存刷新
|
||||||
|
- [ ] 验证错误处理
|
||||||
|
- [ ] 验证文档完整性
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **完成标准**: 所有功能按需求正常工作
|
||||||
|
|
||||||
|
### 任务5.2: 性能验收
|
||||||
|
- [ ] 测试响应时间
|
||||||
|
- [ ] 测试并发处理
|
||||||
|
- [ ] 测试错误恢复
|
||||||
|
- [ ] 测试内存使用
|
||||||
|
- [ ] 测试CPU使用
|
||||||
|
- **负责人**: [待定]
|
||||||
|
- **预计时间**: 0.5天
|
||||||
|
- **完成标准**: 性能指标达到要求
|
||||||
|
|
||||||
|
## 关键里程碑
|
||||||
|
|
||||||
|
### 里程碑1: 项目初始化完成
|
||||||
|
- **时间**: 第2天
|
||||||
|
- **交付物**: 基础框架和配置文件管理功能
|
||||||
|
- **验收标准**: 可以成功操作加密的配置文件
|
||||||
|
|
||||||
|
### 里程碑2: 核心功能完成
|
||||||
|
- **时间**: 第6天
|
||||||
|
- **交付物**: 三个主要CLI功能
|
||||||
|
- **验收标准**: 所有命令正常工作
|
||||||
|
|
||||||
|
### 里程碑3: 测试完成
|
||||||
|
- **时间**: 第9天
|
||||||
|
- **交付物**: 测试报告和修复的问题
|
||||||
|
- **验收标准**: 测试覆盖率 > 80%,无严重bug
|
||||||
|
|
||||||
|
### 里程碑4: 项目交付
|
||||||
|
- **时间**: 第12天
|
||||||
|
- **交付物**: 完整的CLI工具和文档
|
||||||
|
- **验收标准**: 满足所有需求,可以投入使用
|
||||||
|
|
||||||
|
## 风险评估
|
||||||
|
|
||||||
|
### 高风险
|
||||||
|
- **对象存储API集成复杂性**
|
||||||
|
- 风险描述: 不同对象存储服务商的API差异较大
|
||||||
|
- 缓解措施: 使用rclone作为统一接口,降低集成复杂度
|
||||||
|
- 影响: 可能延长开发时间1-2天
|
||||||
|
|
||||||
|
### 中风险
|
||||||
|
- **CDN缓存刷新API限制**
|
||||||
|
- 风险描述: Cloudflare API可能有调用频率限制
|
||||||
|
- 缓解措施: 实现重试机制和错误处理
|
||||||
|
- 影响: 可能影响用户体验
|
||||||
|
|
||||||
|
### 低风险
|
||||||
|
- **CLI框架学习成本**
|
||||||
|
- 风险描述: 团队成员可能需要学习Click或Typer框架
|
||||||
|
- 缓解措施: 选择文档完善的框架,提供学习资源
|
||||||
|
- 影响: 轻微影响开发进度
|
||||||
|
|
||||||
|
## 成功标准
|
||||||
|
|
||||||
|
### 功能标准
|
||||||
|
- [ ] 所有三个CLI功能正常工作
|
||||||
|
- [ ] 配置文件正确加密存储
|
||||||
|
- [ ] CDN缓存正确刷新
|
||||||
|
- [ ] 错误处理完善
|
||||||
|
- [ ] 文档完整清晰
|
||||||
|
|
||||||
|
### 性能标准
|
||||||
|
- [ ] 配置文件查看响应时间 < 3秒
|
||||||
|
- [ ] 配置文件修改响应时间 < 5秒
|
||||||
|
- [ ] CDN缓存刷新响应时间 < 10秒
|
||||||
|
- [ ] 内存使用 < 100MB
|
||||||
|
- [ ] CPU使用 < 10%
|
||||||
|
|
||||||
|
### 质量标准
|
||||||
|
- [ ] 代码测试覆盖率 > 80%
|
||||||
|
- [ ] 无严重bug
|
||||||
|
- [ ] 代码注释完整
|
||||||
|
- [ ] 符合Python编码规范
|
||||||
|
|
||||||
|
## 团队分工
|
||||||
|
|
||||||
|
### 开发团队
|
||||||
|
- **主开发**: [待定] - 负责核心功能开发
|
||||||
|
- **测试工程师**: [待定] - 负责测试和验收
|
||||||
|
- **文档工程师**: [待定] - 负责文档编写
|
||||||
|
|
||||||
|
### 支持团队
|
||||||
|
- **项目经理**: [待定] - 负责项目管理和进度跟踪
|
||||||
|
- **技术顾问**: [待定] - 负责技术指导和问题解决
|
||||||
|
|
||||||
|
## 沟通计划
|
||||||
|
|
||||||
|
### 日常沟通
|
||||||
|
- **每日站会**: 每天上午9:00,15分钟
|
||||||
|
- **周报**: 每周五下午,总结本周进展和下周计划
|
||||||
|
|
||||||
|
### 里程碑沟通
|
||||||
|
- **里程碑评审**: 每个里程碑完成后进行评审
|
||||||
|
- **风险汇报**: 发现风险时立即汇报
|
||||||
|
|
||||||
|
### 文档更新
|
||||||
|
- **进度更新**: 每周更新工作计划进度
|
||||||
|
- **问题记录**: 及时记录和跟踪问题
|
||||||
|
- **经验总结**: 项目结束后进行经验总结
|
||||||
49
examples/basic_usage.py
Normal file
49
examples/basic_usage.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Config-Man 基本使用示例
|
||||||
|
|
||||||
|
演示如何使用 Config-Man CLI 工具的基本功能。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 添加项目根目录到路径
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
|
from config_man.core import ViewCommand
|
||||||
|
from config_man.utils import patch_rclone
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""基本使用示例"""
|
||||||
|
print("Config-Man 基本使用示例")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# 启用模拟环境
|
||||||
|
patch_rclone()
|
||||||
|
|
||||||
|
# 创建查看命令处理器
|
||||||
|
view_cmd = ViewCommand()
|
||||||
|
|
||||||
|
# 查看版本 0.30 的配置
|
||||||
|
print("\n1. 查看版本 0.30 的配置:")
|
||||||
|
success = view_cmd.execute("0.30", json_format=False)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print("✅ 查看成功")
|
||||||
|
else:
|
||||||
|
print("❌ 查看失败")
|
||||||
|
|
||||||
|
# 查看版本 0.29 的配置(JSON格式)
|
||||||
|
print("\n2. 查看版本 0.29 的配置(JSON格式):")
|
||||||
|
success = view_cmd.execute("0.29", json_format=True)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print("✅ 查看成功")
|
||||||
|
else:
|
||||||
|
print("❌ 查看失败")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
12
main.py
Normal file
12
main.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Config-Man CLI 工具入口点
|
||||||
|
|
||||||
|
用于管理存储在对象存储中的加密静态资源配置文件。
|
||||||
|
支持多版本管理,通过Cloudflare CDN进行分发。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from config_man.cli.main import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
111
pyproject.toml
Normal file
111
pyproject.toml
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
[project]
|
||||||
|
name = "config-man"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "CLI tool for managing encrypted configuration files"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
authors = [
|
||||||
|
{name = "Config-Man Team", email = "team@config-man.com"}
|
||||||
|
]
|
||||||
|
license = {text = "MIT"}
|
||||||
|
keywords = ["cli", "config", "encryption", "cdn", "storage"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: System :: Systems Administration",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"pycryptodome>=3.19.0",
|
||||||
|
"tabulate>=0.9.0",
|
||||||
|
"requests>=2.31.0",
|
||||||
|
"rich>=13.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=7.0.0",
|
||||||
|
"pytest-cov>=4.0.0",
|
||||||
|
"black>=23.0.0",
|
||||||
|
"flake8>=6.0.0",
|
||||||
|
"mypy>=1.0.0",
|
||||||
|
]
|
||||||
|
test = [
|
||||||
|
"pytest>=7.0.0",
|
||||||
|
"pytest-cov>=4.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
config-man = "config_man.cli.main:main"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://github.com/config-man/config-man"
|
||||||
|
Documentation = "https://config-man.readthedocs.io"
|
||||||
|
Repository = "https://github.com/config-man/config-man"
|
||||||
|
Issues = "https://github.com/config-man/config-man/issues"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["src/config_man"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
python_files = ["test_*.py"]
|
||||||
|
python_classes = ["Test*"]
|
||||||
|
python_functions = ["test_*"]
|
||||||
|
addopts = [
|
||||||
|
"--strict-markers",
|
||||||
|
"--strict-config",
|
||||||
|
"--cov=src/config_man",
|
||||||
|
"--cov-report=term-missing",
|
||||||
|
"--cov-report=html",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 88
|
||||||
|
target-version = ['py313']
|
||||||
|
include = '\.pyi?$'
|
||||||
|
extend-exclude = '''
|
||||||
|
/(
|
||||||
|
# directories
|
||||||
|
\.eggs
|
||||||
|
| \.git
|
||||||
|
| \.hg
|
||||||
|
| \.mypy_cache
|
||||||
|
| \.tox
|
||||||
|
| \.venv
|
||||||
|
| build
|
||||||
|
| dist
|
||||||
|
)/
|
||||||
|
'''
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
python_version = "3.13"
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unused_configs = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_redundant_casts = true
|
||||||
|
warn_unused_ignores = true
|
||||||
|
warn_no_return = true
|
||||||
|
warn_unreachable = true
|
||||||
|
strict_equality = true
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = [
|
||||||
|
"click.*",
|
||||||
|
"rich.*",
|
||||||
|
"requests.*",
|
||||||
|
"Crypto.*",
|
||||||
|
]
|
||||||
|
ignore_missing_imports = true
|
||||||
10
src/config_man/__init__.py
Normal file
10
src/config_man/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
"""
|
||||||
|
Config-Man CLI 工具
|
||||||
|
|
||||||
|
用于管理存储在对象存储中的加密静态资源配置文件。
|
||||||
|
支持多版本管理,通过Cloudflare CDN进行分发。
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "0.1.0"
|
||||||
|
__author__ = "Config-Man Team"
|
||||||
|
__description__ = "CLI tool for managing encrypted configuration files"
|
||||||
9
src/config_man/cli/__init__.py
Normal file
9
src/config_man/cli/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
"""
|
||||||
|
CLI 模块
|
||||||
|
|
||||||
|
包含命令行界面相关的功能。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .main import cli, main
|
||||||
|
|
||||||
|
__all__ = ["cli", "main"]
|
||||||
109
src/config_man/cli/main.py
Normal file
109
src/config_man/cli/main.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import click
|
||||||
|
import os
|
||||||
|
from ..core.view_command import ViewCommand
|
||||||
|
from ..utils.mock_rclone import patch_rclone
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
@click.version_option(version="0.1.0")
|
||||||
|
def cli():
|
||||||
|
"""Config-Man CLI 工具
|
||||||
|
|
||||||
|
用于管理存储在对象存储中的加密静态资源配置文件。
|
||||||
|
支持多版本管理,通过Cloudflare CDN进行分发。
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('--version', required=True, help='版本号,格式为 0.29, 0.30, 0.31 等')
|
||||||
|
@click.option('--json', 'json_format', is_flag=True, help='以JSON格式输出')
|
||||||
|
@click.option('--storage-path', default='ab', help='对象存储路径前缀')
|
||||||
|
@click.option('--cdn-url', default='', help='CDN基础URL')
|
||||||
|
@click.option('--mock', is_flag=True, help='使用模拟环境进行测试')
|
||||||
|
def view(version, json_format, storage_path, cdn_url, mock):
|
||||||
|
"""查看配置文件
|
||||||
|
|
||||||
|
对比显示对象存储和CDN中的配置内容,支持Android和iOS平台。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
config-man view --version 0.30
|
||||||
|
config-man view --version 0.30 --json
|
||||||
|
config-man view --version 0.30 --mock
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 如果使用模拟环境,启用rclone模拟
|
||||||
|
if mock:
|
||||||
|
patch_rclone()
|
||||||
|
click.echo("使用模拟环境进行测试...")
|
||||||
|
else:
|
||||||
|
# 检查rclone是否可用
|
||||||
|
if not _check_rclone():
|
||||||
|
click.echo("错误: rclone 未安装或不可用。请先安装 rclone。")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# 创建查看命令处理器
|
||||||
|
view_cmd = ViewCommand(storage_path, cdn_url)
|
||||||
|
|
||||||
|
# 执行查看命令
|
||||||
|
success = view_cmd.execute(version, json_format)
|
||||||
|
|
||||||
|
return 0 if success else 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
click.echo(f"错误: {str(e)}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('--platform', required=True, type=click.Choice(['android', 'ios']),
|
||||||
|
help='平台类型')
|
||||||
|
@click.option('--target-version', required=True, help='目标版本号')
|
||||||
|
@click.option('--update-version', required=True, help='更新版本号')
|
||||||
|
def suggest_update(platform, target_version, update_version):
|
||||||
|
"""建议更新
|
||||||
|
|
||||||
|
在目标版本的配置文件中添加 Ver_New 属性,提示用户有新版本可用。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
config-man suggest-update --platform android --target-version 0.29 --update-version 0.30
|
||||||
|
"""
|
||||||
|
click.echo("建议更新功能尚未实现")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('--platform', required=True, type=click.Choice(['android', 'ios']),
|
||||||
|
help='平台类型')
|
||||||
|
@click.option('--target-version', required=True, help='目标版本号')
|
||||||
|
@click.option('--update-version', required=True, help='更新版本号')
|
||||||
|
def force_update(platform, target_version, update_version):
|
||||||
|
"""强制更新
|
||||||
|
|
||||||
|
直接更新目标版本的 Ver 属性,强制用户升级到新版本。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
config-man force-update --platform ios --target-version 0.29 --update-version 0.30
|
||||||
|
"""
|
||||||
|
click.echo("强制更新功能尚未实现")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def _check_rclone():
|
||||||
|
"""检查rclone是否可用"""
|
||||||
|
import subprocess
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['rclone', 'version'],
|
||||||
|
capture_output=True, text=True, timeout=5)
|
||||||
|
return result.returncode == 0
|
||||||
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
cli()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
11
src/config_man/core/__init__.py
Normal file
11
src/config_man/core/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
"""
|
||||||
|
核心功能模块
|
||||||
|
|
||||||
|
包含配置管理、加密解密、显示管理等核心功能。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .config_manager import ConfigManager
|
||||||
|
from .display_manager import DisplayManager
|
||||||
|
from .view_command import ViewCommand
|
||||||
|
|
||||||
|
__all__ = ["ConfigManager", "DisplayManager", "ViewCommand"]
|
||||||
119
src/config_man/core/config_manager.py
Normal file
119
src/config_man/core/config_manager.py
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
from typing import Dict, Optional, Tuple
|
||||||
|
from ..utils.crypto import encrypt, decrypt
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigManager:
|
||||||
|
"""配置文件管理器"""
|
||||||
|
|
||||||
|
def __init__(self, storage_path: str = "ab", cdn_base_url: str = ""):
|
||||||
|
self.storage_path = storage_path
|
||||||
|
self.cdn_base_url = cdn_base_url
|
||||||
|
|
||||||
|
def version_to_path(self, version: str) -> str:
|
||||||
|
"""将版本号转换为存储路径格式"""
|
||||||
|
# 0.29 -> 0_29
|
||||||
|
return version.replace('.', '_')
|
||||||
|
|
||||||
|
def get_config_path(self, version: str, platform: str) -> str:
|
||||||
|
"""获取配置文件在对象存储中的路径"""
|
||||||
|
version_path = self.version_to_path(version)
|
||||||
|
filename = f"{platform}config.json"
|
||||||
|
return f"{self.storage_path}/{version_path}/{filename}"
|
||||||
|
|
||||||
|
def get_cdn_url(self, version: str, platform: str) -> str:
|
||||||
|
"""获取配置文件在CDN中的URL"""
|
||||||
|
if not self.cdn_base_url:
|
||||||
|
return ""
|
||||||
|
version_path = self.version_to_path(version)
|
||||||
|
filename = f"{platform}config.json"
|
||||||
|
return f"{self.cdn_base_url}/{self.storage_path}/{version_path}/{filename}"
|
||||||
|
|
||||||
|
def download_from_storage(self, version: str, platform: str) -> Optional[str]:
|
||||||
|
"""从对象存储下载并解密配置文件"""
|
||||||
|
try:
|
||||||
|
config_path = self.get_config_path(version, platform)
|
||||||
|
|
||||||
|
# 使用rclone下载文件
|
||||||
|
result = subprocess.run(
|
||||||
|
["rclone", "cat", config_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"警告: 无法从对象存储下载 {config_path}: {result.stderr}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 解密文件内容
|
||||||
|
encrypted_content = result.stdout.strip()
|
||||||
|
if not encrypted_content:
|
||||||
|
print(f"警告: 文件 {config_path} 为空")
|
||||||
|
return None
|
||||||
|
|
||||||
|
decrypted_content = decrypt(encrypted_content)
|
||||||
|
return decrypted_content
|
||||||
|
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print(f"错误: 下载 {config_path} 超时")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"错误: 下载 {config_path} 失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_from_cdn(self, version: str, platform: str) -> Optional[str]:
|
||||||
|
"""从CDN获取配置文件内容"""
|
||||||
|
try:
|
||||||
|
cdn_url = self.get_cdn_url(version, platform)
|
||||||
|
if not cdn_url:
|
||||||
|
print(f"警告: CDN URL未配置,跳过CDN内容获取")
|
||||||
|
return None
|
||||||
|
|
||||||
|
response = requests.get(cdn_url, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# CDN中的内容应该是解密后的JSON
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"警告: 无法从CDN获取 {cdn_url}: {str(e)}")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"错误: 获取CDN内容失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parse_config(self, content: str) -> Optional[Dict]:
|
||||||
|
"""解析配置文件内容"""
|
||||||
|
try:
|
||||||
|
return json.loads(content)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"错误: 配置文件格式错误: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def compare_configs(self, storage_config: Dict, cdn_config: Dict) -> Dict:
|
||||||
|
"""比较存储配置和CDN配置的差异"""
|
||||||
|
all_keys = set(storage_config.keys()) | set(cdn_config.keys())
|
||||||
|
differences = {}
|
||||||
|
|
||||||
|
for key in sorted(all_keys):
|
||||||
|
storage_value = storage_config.get(key, "N/A")
|
||||||
|
cdn_value = cdn_config.get(key, "N/A")
|
||||||
|
|
||||||
|
if storage_value != cdn_value:
|
||||||
|
differences[key] = {
|
||||||
|
"storage": storage_value,
|
||||||
|
"cdn": cdn_value,
|
||||||
|
"different": True
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
differences[key] = {
|
||||||
|
"storage": storage_value,
|
||||||
|
"cdn": cdn_value,
|
||||||
|
"different": False
|
||||||
|
}
|
||||||
|
|
||||||
|
return differences
|
||||||
109
src/config_man/core/display_manager.py
Normal file
109
src/config_man/core/display_manager.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
from typing import Dict, List
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.text import Text
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayManager:
|
||||||
|
"""显示管理器"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.console = Console()
|
||||||
|
|
||||||
|
def display_config_comparison(self, version: str, platform: str,
|
||||||
|
storage_config: Dict, cdn_config: Dict,
|
||||||
|
differences: Dict):
|
||||||
|
"""显示配置对比结果"""
|
||||||
|
|
||||||
|
# 创建标题
|
||||||
|
title = f"版本: {version} | 平台: {platform.title()}"
|
||||||
|
self.console.print(f"\n[bold blue]{title}[/bold blue]")
|
||||||
|
|
||||||
|
# 创建表格
|
||||||
|
table = Table(show_header=True, header_style="bold magenta")
|
||||||
|
table.add_column("配置项", style="cyan", width=20)
|
||||||
|
table.add_column("对象存储内容", style="green", width=30)
|
||||||
|
table.add_column("CDN内容", style="yellow", width=30)
|
||||||
|
table.add_column("状态", style="red", width=10)
|
||||||
|
|
||||||
|
# 添加数据行
|
||||||
|
for key, data in differences.items():
|
||||||
|
storage_value = str(data["storage"])
|
||||||
|
cdn_value = str(data["cdn"])
|
||||||
|
status = "❌ 不同" if data["different"] else "✅ 一致"
|
||||||
|
|
||||||
|
# 截断过长的值
|
||||||
|
if len(storage_value) > 25:
|
||||||
|
storage_value = storage_value[:22] + "..."
|
||||||
|
if len(cdn_value) > 25:
|
||||||
|
cdn_value = cdn_value[:22] + "..."
|
||||||
|
|
||||||
|
table.add_row(key, storage_value, cdn_value, status)
|
||||||
|
|
||||||
|
self.console.print(table)
|
||||||
|
|
||||||
|
def display_json_format(self, version: str, platform: str,
|
||||||
|
storage_config: Dict, cdn_config: Dict):
|
||||||
|
"""以JSON格式显示配置"""
|
||||||
|
|
||||||
|
title = f"版本: {version} | 平台: {platform.title()}"
|
||||||
|
self.console.print(f"\n[bold blue]{title}[/bold blue]")
|
||||||
|
|
||||||
|
# 创建对比JSON
|
||||||
|
comparison = {
|
||||||
|
"version": version,
|
||||||
|
"platform": platform,
|
||||||
|
"storage_config": storage_config,
|
||||||
|
"cdn_config": cdn_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# 格式化JSON输出
|
||||||
|
json_str = json.dumps(comparison, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
# 使用面板显示
|
||||||
|
panel = Panel(
|
||||||
|
json_str,
|
||||||
|
title="JSON格式",
|
||||||
|
border_style="blue"
|
||||||
|
)
|
||||||
|
self.console.print(panel)
|
||||||
|
|
||||||
|
def display_summary(self, version: str, results: Dict):
|
||||||
|
"""显示总结信息"""
|
||||||
|
|
||||||
|
self.console.print(f"\n[bold green]配置查看总结[/bold green]")
|
||||||
|
self.console.print(f"版本: {version}")
|
||||||
|
|
||||||
|
for platform in ["android", "ios"]:
|
||||||
|
if platform in results:
|
||||||
|
result = results[platform]
|
||||||
|
if result["success"]:
|
||||||
|
storage_keys = len(result["storage_config"])
|
||||||
|
cdn_keys = len(result["cdn_config"])
|
||||||
|
differences = sum(1 for data in result["differences"].values()
|
||||||
|
if data["different"])
|
||||||
|
|
||||||
|
status = "✅ 正常" if differences == 0 else f"⚠️ {differences} 项不同"
|
||||||
|
|
||||||
|
self.console.print(
|
||||||
|
f" {platform.title()}: {status} "
|
||||||
|
f"(存储: {storage_keys}项, CDN: {cdn_keys}项)"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.console.print(f" {platform.title()}: ❌ 失败")
|
||||||
|
else:
|
||||||
|
self.console.print(f" {platform.title()}: ⚠️ 未检查")
|
||||||
|
|
||||||
|
def display_error(self, message: str):
|
||||||
|
"""显示错误信息"""
|
||||||
|
self.console.print(f"[bold red]错误: {message}[/bold red]")
|
||||||
|
|
||||||
|
def display_warning(self, message: str):
|
||||||
|
"""显示警告信息"""
|
||||||
|
self.console.print(f"[bold yellow]警告: {message}[/bold yellow]")
|
||||||
|
|
||||||
|
def display_info(self, message: str):
|
||||||
|
"""显示信息"""
|
||||||
|
self.console.print(f"[bold blue]信息: {message}[/bold blue]")
|
||||||
142
src/config_man/core/view_command.py
Normal file
142
src/config_man/core/view_command.py
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
from typing import Dict, Optional
|
||||||
|
from .config_manager import ConfigManager
|
||||||
|
from .display_manager import DisplayManager
|
||||||
|
|
||||||
|
|
||||||
|
class ViewCommand:
|
||||||
|
"""查看命令处理器"""
|
||||||
|
|
||||||
|
def __init__(self, storage_path: str = "ab", cdn_base_url: str = ""):
|
||||||
|
self.config_manager = ConfigManager(storage_path, cdn_base_url)
|
||||||
|
self.display_manager = DisplayManager()
|
||||||
|
|
||||||
|
def execute(self, version: str, json_format: bool = False) -> bool:
|
||||||
|
"""执行查看命令"""
|
||||||
|
|
||||||
|
# 验证版本号格式
|
||||||
|
if not self._validate_version(version):
|
||||||
|
self.display_manager.display_error(f"无效的版本号格式: {version}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.display_manager.display_info(f"正在查看版本 {version} 的配置文件...")
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
success = True
|
||||||
|
|
||||||
|
# 检查Android和iOS平台
|
||||||
|
for platform in ["android", "ios"]:
|
||||||
|
result = self._check_platform_config(version, platform)
|
||||||
|
results[platform] = result
|
||||||
|
|
||||||
|
if not result["success"]:
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# 显示结果
|
||||||
|
if json_format:
|
||||||
|
self._display_json_results(version, results)
|
||||||
|
else:
|
||||||
|
self._display_table_results(version, results)
|
||||||
|
|
||||||
|
# 显示总结
|
||||||
|
self.display_manager.display_summary(version, results)
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
def _validate_version(self, version: str) -> bool:
|
||||||
|
"""验证版本号格式"""
|
||||||
|
try:
|
||||||
|
# 检查版本号格式 (如 0.29, 0.30, 1.00)
|
||||||
|
parts = version.split('.')
|
||||||
|
if len(parts) != 2:
|
||||||
|
return False
|
||||||
|
|
||||||
|
major, minor = parts
|
||||||
|
if not major.isdigit() or not minor.isdigit():
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _check_platform_config(self, version: str, platform: str) -> Dict:
|
||||||
|
"""检查指定平台的配置"""
|
||||||
|
result = {
|
||||||
|
"success": False,
|
||||||
|
"storage_config": {},
|
||||||
|
"cdn_config": {},
|
||||||
|
"differences": {},
|
||||||
|
"error": None
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 从对象存储获取配置
|
||||||
|
storage_content = self.config_manager.download_from_storage(version, platform)
|
||||||
|
if storage_content is None:
|
||||||
|
result["error"] = f"无法从对象存储获取 {platform} 配置"
|
||||||
|
return result
|
||||||
|
|
||||||
|
storage_config = self.config_manager.parse_config(storage_content)
|
||||||
|
if storage_config is None:
|
||||||
|
result["error"] = f"解析对象存储中的 {platform} 配置失败"
|
||||||
|
return result
|
||||||
|
|
||||||
|
result["storage_config"] = storage_config
|
||||||
|
|
||||||
|
# 从CDN获取配置
|
||||||
|
cdn_content = self.config_manager.get_from_cdn(version, platform)
|
||||||
|
if cdn_content is None:
|
||||||
|
# CDN获取失败,使用空配置
|
||||||
|
result["cdn_config"] = {}
|
||||||
|
result["differences"] = self.config_manager.compare_configs(
|
||||||
|
storage_config, {}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cdn_config = self.config_manager.parse_config(cdn_content)
|
||||||
|
if cdn_config is None:
|
||||||
|
result["error"] = f"解析CDN中的 {platform} 配置失败"
|
||||||
|
return result
|
||||||
|
|
||||||
|
result["cdn_config"] = cdn_config
|
||||||
|
result["differences"] = self.config_manager.compare_configs(
|
||||||
|
storage_config, cdn_config
|
||||||
|
)
|
||||||
|
|
||||||
|
result["success"] = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result["error"] = f"检查 {platform} 配置时发生错误: {str(e)}"
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _display_table_results(self, version: str, results: Dict):
|
||||||
|
"""以表格格式显示结果"""
|
||||||
|
for platform in ["android", "ios"]:
|
||||||
|
if platform in results:
|
||||||
|
result = results[platform]
|
||||||
|
if result["success"]:
|
||||||
|
self.display_manager.display_config_comparison(
|
||||||
|
version, platform,
|
||||||
|
result["storage_config"],
|
||||||
|
result["cdn_config"],
|
||||||
|
result["differences"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.display_manager.display_error(
|
||||||
|
f"{platform.title()} 配置检查失败: {result['error']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _display_json_results(self, version: str, results: Dict):
|
||||||
|
"""以JSON格式显示结果"""
|
||||||
|
for platform in ["android", "ios"]:
|
||||||
|
if platform in results:
|
||||||
|
result = results[platform]
|
||||||
|
if result["success"]:
|
||||||
|
self.display_manager.display_json_format(
|
||||||
|
version, platform,
|
||||||
|
result["storage_config"],
|
||||||
|
result["cdn_config"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.display_manager.display_error(
|
||||||
|
f"{platform.title()} 配置检查失败: {result['error']}"
|
||||||
|
)
|
||||||
10
src/config_man/utils/__init__.py
Normal file
10
src/config_man/utils/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
"""
|
||||||
|
工具模块
|
||||||
|
|
||||||
|
包含加密解密、模拟环境等工具功能。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .crypto import encrypt, decrypt
|
||||||
|
from .mock_rclone import MockRclone, patch_rclone
|
||||||
|
|
||||||
|
__all__ = ["encrypt", "decrypt", "MockRclone", "patch_rclone"]
|
||||||
23
src/config_man/utils/crypto.py
Normal file
23
src/config_man/utils/crypto.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from Crypto.Cipher import DES
|
||||||
|
from Crypto.Util.Padding import pad,unpad
|
||||||
|
import base64
|
||||||
|
|
||||||
|
def encrypt(text):
|
||||||
|
key = 'tbambooz'.encode('ascii')
|
||||||
|
des = DES.new(key, DES.MODE_CBC, IV=key)
|
||||||
|
padded_text = pad(text.encode('utf-8'), DES.block_size)
|
||||||
|
encrypted_text = des.encrypt(padded_text)
|
||||||
|
return base64.b64encode(encrypted_text).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(encrypted_text):
|
||||||
|
key = 'tbambooz'
|
||||||
|
key = key.encode('ascii')
|
||||||
|
des = DES.new(key, DES.MODE_CBC, IV=key)
|
||||||
|
decoded_text = base64.b64decode(encrypted_text)
|
||||||
|
decrypted_text = des.decrypt(decoded_text)
|
||||||
|
unpadded_text = unpad(decrypted_text, DES.block_size)
|
||||||
|
return unpadded_text.decode('utf-8')
|
||||||
|
|
||||||
153
src/config_man/utils/mock_rclone.py
Normal file
153
src/config_man/utils/mock_rclone.py
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from .crypto import encrypt, decrypt
|
||||||
|
|
||||||
|
|
||||||
|
class MockRclone:
|
||||||
|
"""模拟rclone环境,用于测试"""
|
||||||
|
|
||||||
|
def __init__(self, test_data_path: str = "test_data"):
|
||||||
|
self.test_data_path = test_data_path
|
||||||
|
self._setup_mock_environment()
|
||||||
|
|
||||||
|
def _setup_mock_environment(self):
|
||||||
|
"""设置模拟环境"""
|
||||||
|
# 确保测试数据目录存在
|
||||||
|
os.makedirs(self.test_data_path, exist_ok=True)
|
||||||
|
|
||||||
|
# 创建测试配置文件
|
||||||
|
self._create_test_configs()
|
||||||
|
|
||||||
|
def _create_test_configs(self):
|
||||||
|
"""创建测试配置文件"""
|
||||||
|
test_configs = {
|
||||||
|
"0.29": {
|
||||||
|
"android": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.29.1abc123",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.29.1def456",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0.30": {
|
||||||
|
"android": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2ghi789",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w==",
|
||||||
|
"NewFeature": "enabled"
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2jkl012",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w==",
|
||||||
|
"NewFeature": "enabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建测试目录结构
|
||||||
|
for version, platforms in test_configs.items():
|
||||||
|
version_path = f"{self.test_data_path}/ab/{version.replace('.', '_')}"
|
||||||
|
os.makedirs(version_path, exist_ok=True)
|
||||||
|
|
||||||
|
for platform, config in platforms.items():
|
||||||
|
filename = f"{platform}config.json"
|
||||||
|
filepath = os.path.join(version_path, filename)
|
||||||
|
|
||||||
|
# 加密配置并保存
|
||||||
|
config_json = json.dumps(config, indent=2, ensure_ascii=False)
|
||||||
|
encrypted_config = encrypt(config_json)
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(encrypted_config)
|
||||||
|
|
||||||
|
print(f"创建测试文件: {filepath}")
|
||||||
|
|
||||||
|
def mock_rclone_cat(self, path: str) -> str:
|
||||||
|
"""模拟rclone cat命令"""
|
||||||
|
# 将路径转换为本地文件路径
|
||||||
|
local_path = os.path.join(self.test_data_path, path)
|
||||||
|
|
||||||
|
if not os.path.exists(local_path):
|
||||||
|
raise FileNotFoundError(f"文件不存在: {path}")
|
||||||
|
|
||||||
|
with open(local_path, 'r', encoding='utf-8') as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
def patch_rclone():
|
||||||
|
"""修补rclone调用,使用模拟环境"""
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
original_run = subprocess.run
|
||||||
|
|
||||||
|
def mock_run(cmd, *args, **kwargs):
|
||||||
|
if len(cmd) >= 2 and cmd[0] == 'rclone' and cmd[1] == 'cat':
|
||||||
|
# 模拟rclone cat命令
|
||||||
|
mock_rclone = MockRclone()
|
||||||
|
try:
|
||||||
|
content = mock_rclone.mock_rclone_cat(cmd[2])
|
||||||
|
# 返回模拟的subprocess结果
|
||||||
|
from types import SimpleNamespace
|
||||||
|
result = SimpleNamespace()
|
||||||
|
result.returncode = 0
|
||||||
|
result.stdout = content
|
||||||
|
result.stderr = ""
|
||||||
|
return result
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
# 返回错误结果
|
||||||
|
from types import SimpleNamespace
|
||||||
|
result = SimpleNamespace()
|
||||||
|
result.returncode = 1
|
||||||
|
result.stdout = ""
|
||||||
|
result.stderr = str(e)
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
# 对于其他命令,使用原始实现
|
||||||
|
return original_run(cmd, *args, **kwargs)
|
||||||
|
|
||||||
|
subprocess.run = mock_run
|
||||||
|
print("已启用rclone模拟环境")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 创建测试环境
|
||||||
|
mock = MockRclone()
|
||||||
|
print("模拟rclone环境设置完成!")
|
||||||
5
tests/__init__.py
Normal file
5
tests/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
测试包
|
||||||
|
|
||||||
|
包含单元测试、集成测试和测试工具。
|
||||||
|
"""
|
||||||
5
tests/fixtures/__init__.py
vendored
Normal file
5
tests/fixtures/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
测试工具
|
||||||
|
|
||||||
|
包含测试数据、模拟环境和测试工具。
|
||||||
|
"""
|
||||||
97
tests/fixtures/test_configs.py
vendored
Normal file
97
tests/fixtures/test_configs.py
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src'))
|
||||||
|
|
||||||
|
from config_man.utils.crypto import encrypt
|
||||||
|
|
||||||
|
|
||||||
|
def create_test_configs():
|
||||||
|
"""创建测试配置文件"""
|
||||||
|
|
||||||
|
# 测试配置数据
|
||||||
|
test_configs = {
|
||||||
|
"0.29": {
|
||||||
|
"android": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.29.1abc123",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.29.1def456",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0.30": {
|
||||||
|
"android": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2ghi789",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w==",
|
||||||
|
"NewFeature": "enabled"
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"EventApiURL": "https://n3backend.azurewebsites.net/",
|
||||||
|
"Ver": "0.30.2jkl012",
|
||||||
|
"PlayFabTitle": "B066F",
|
||||||
|
"Google_Play_URL": "https://play.google.com/store/apps/details?id=com.arkgame.ft",
|
||||||
|
"APP_Store_URL": "https://apps.apple.com/us/app/id6505145935",
|
||||||
|
"HeartBeat": "60",
|
||||||
|
"RTMPid": "80000586",
|
||||||
|
"RTMServerEndpoint": "rtm-intl-frontgate.ilivedata.com:13321",
|
||||||
|
"RTMHmacSecret": "57047697437f4f2c97a835e8d9a53358",
|
||||||
|
"FuncUrl": "https://leaderboardcreate.azurewebsites.net",
|
||||||
|
"FuncKey": "R5kU45fNBRd52Eqp3tEqfpZqrbFw53uSSEo7wraUSqIfAzFuRmLm_w==",
|
||||||
|
"NewFeature": "enabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建测试目录结构
|
||||||
|
for version, platforms in test_configs.items():
|
||||||
|
version_path = f"test_data/ab/{version.replace('.', '_')}"
|
||||||
|
os.makedirs(version_path, exist_ok=True)
|
||||||
|
|
||||||
|
for platform, config in platforms.items():
|
||||||
|
filename = f"{platform}config.json"
|
||||||
|
filepath = os.path.join(version_path, filename)
|
||||||
|
|
||||||
|
# 加密配置并保存
|
||||||
|
config_json = json.dumps(config, indent=2, ensure_ascii=False)
|
||||||
|
encrypted_config = encrypt(config_json)
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(encrypted_config)
|
||||||
|
|
||||||
|
print(f"创建测试文件: {filepath}")
|
||||||
|
|
||||||
|
print("测试配置文件创建完成!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
create_test_configs()
|
||||||
5
tests/integration/__init__.py
Normal file
5
tests/integration/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
集成测试
|
||||||
|
|
||||||
|
测试模块间的集成功能。
|
||||||
|
"""
|
||||||
5
tests/unit/__init__.py
Normal file
5
tests/unit/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
单元测试
|
||||||
|
|
||||||
|
测试各个模块的独立功能。
|
||||||
|
"""
|
||||||
Reference in New Issue
Block a user