Files
goauto/docs/04-local-development-and-verification.md
T

24 KiB
Raw Blame History

generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Local-Development-and-Verification wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Local-Development-and-Verification.- wiki_revision: 03ea269058b50fea2be7842b9c284018987c82d9 synchronized_at: 2026-09-21T08:14:42Z

本地开发与验证

T01 已建立可执行的三端骨架。建议从仓库根目录运行统一脚本:

.\scripts\verify.ps1 -Component all

Component 也可以是 server、web 或 android。

Windows PowerShell 与 UTF-8

Shell 选择

  • 优先使用当前已配置的 PowerShell;可选择时优先 PowerShell 7 pwsh.exe。只有命令明确依赖 Windows PowerShell 5.1 时才使用 powershell.exe。
  • 不得仅为设置编码重复启动一层 PowerShell;嵌套进程会增加启动时间、转义复杂度和错误定位成本。
  • 代码发现优先使用项目配置的代码图工具;检索字符串、配置和非代码文件,或图工具不足时使用 rg。

PowerShell 语法与外部命令

  • Windows 命令不得默认套用 Bash 语法;复杂正则优先先赋给变量或使用 rg -e,避免在多层引号中继续嵌套。
  • 多行 Python 或 JSON 正文使用单引号 PowerShell here-string,避免 $()、反引号和变量被 PowerShell 提前展开:
$script = @'
print("保持原文")
'@
$script | python -
  • foreach、if 等语句块应保留在同一个 PowerShell 解析上下文中;需要收集表达式结果时使用数组表达式:
$items = @(foreach ($path in $paths) {
    if (Test-Path -LiteralPath $path) { Get-Item -LiteralPath $path }
})
  • rg 使用真实目录配合 -g/--glob,不要把 Bash 风格通配路径作为目录参数:
rg -n -g '*.md' 'sync --check' docs

文件编码与控制台输出

文件解码和控制台输出是两个边界。读取 UTF-8 文本时,在命令支持的情况下显式指定字面路径与编码:

Get-Content -LiteralPath "path\to\file.md" -Encoding utf8

仓库文件仍使用项目规定的编辑工具修改,不为指定编码改用 shell 拼接、重定向或临时文件。PowerShell 5.1 与 PowerShell 7 对无 BOM UTF-8 的默认处理不同,不能只凭控制台显示判断文件编码。

只有出现真实乱码,或已知宿主/外部程序不是 UTF-8 时,才在当前进程设置:

$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)

Python 中文输出已经出现乱码时,可只对当前进程设置:

$env:PYTHONUTF8 = "1"
$env:PYTHONIOENCODING = "utf-8"
python dev_scripts/harness.py check --strict

同一会话已经生效且环境未变化时不重复设置;乱码仍存在时先区分文件解码、控制台、管道和外部程序,处理首个真实原因。

ExecutionPolicy 边界

  • Get-Content、rg、Git、Python 和普通 PowerShell cmdlet 不需要 -ExecutionPolicy Bypass。
  • 不得默认添加 Bypass,也不得把它写入统一命令包装。
  • 只有可信 .ps1 确实被执行策略阻止、任务范围允许且没有更小替代方案时,才对该次进程使用,并在工单记录脚本、阻止信息和原因。
  • Bypass 只解决执行策略阻止,不解决编码、权限或脚本自身错误。

通用检查

git status --short --branch
git diff --check

服务端验证

Set-Location server
go test ./...
go build ./...

服务端固定为 go-admin v2.3.0,模块要求 Go 1.26.5;本机可由 GOTOOLCHAIN=auto 获取匹配工具链。对象存储用例带有 integration 标签,默认验证不会访问云端凭据。

默认运行目标是 MySQL。开发者在仓库根目录的 config.yaml 中维护本机连接参数和启动端口;该文件已被 Git 忽略,不得提交。可从不含凭据的 config.example.yaml 复制。启动脚本读取配置后,仅通过当前进程环境注入数据库连接、服务端端口和前端 API 地址,不把账号密码写回 server/config/settings.yml、日志、工单或文档。

如需启用 AI 规格匹配,管理员在“AI 规格匹配”页面配置单一 OpenAI-compatible Provider 的 Base URL、模型、超时和 API Key;超时默认 15 秒,可设置为 3~600 秒。根据 #62 已确认的内部部署例外,API Key 明文保存在专用设置表,并只在管理员设置页面回显,不能出现在代码、日志、工单、Wiki、任务快照、采购员接口或 Android 接口。Base URL 支持公网或内网的 HTTP/HTTPS 地址,不作局域网限制;HTTP 不加密传输中的 API Key,生产环境建议 HTTPS。

已经执行过旧版 GoAuto 表结构的数据库,会由 1786700300000_collection_execution.go 增量补齐任务幂等、结果、软删除和颜色价格字段;不要通过修改已执行迁移的版本号强制重跑。

Windows 本地 MySQL 8.4 可以从仓库根目录双击或执行:

.\start-server.bat

首次使用先编辑根目录 config.yaml:database 节点配置 host、port、user、password 和 name,ports.server 与 ports.web 配置 API 和管理端开发服务器端口。两个启动端口必须位于 1~65535 且不能相同。随后脚本直接读取该文件,创建数据库、执行迁移并启动服务,不再交互询问密码。迁移已经执行过时,可使用 .\start-server.bat -SkipMigration;只验证服务端配置可使用 .\start-server.bat -ValidateConfigOnly,只验证前端端口配置可使用 .\start-web.bat -ValidateConfigOnly。

管理端前端可单独双击 start-web.bat;也可双击 start-all.bat 同时打开服务端和前端两个窗口。访问地址分别为 http://127.0.0.1:<ports.web> 和 http://127.0.0.1:<ports.server>,默认仍是 9527 和 8000。前端开发 API 地址会自动跟随 ports.server。修改服务端端口后,还需同步修改 Android Agent 保存的服务地址。API 根路径显示 go-admin 默认欢迎页属于正常现象。

只验证最小闭环迁移和数据库约束:

Set-Location server
go test ./app/goauto/...

该命令同时覆盖设备注册的首次签发、requestId 重放、错误 Token、防接管、停用/吊销、默认 HTTPS、显式 HTTP 例外、限流、心跳任务一致性和超时离线失败测试。

AI 规格匹配的隔离验证:

Set-Location server
go test ./app/goauto/aimatching ./app/goauto/purchase

该测试覆盖确定性标准化、歧义拒绝、Provider 回退的候选原文校验、内部 API Key 的管理员读取/采购员隔离以及 HTTP/HTTPS Base URL 校验;不会调用真实 Provider 或创建订单。

如需用临时 SQLite 做隔离联调,服务端命令必须显式带上 SQLite 构建标签:

Set-Location server
go run -tags sqlite3 . migrate -c config/settings.sqlite.yml
go run -tags sqlite3 . server -c config/settings.sqlite.yml

SQLite 只用于测试;正式运行和最终迁移目标仍为 MySQL 8.4。真实 MySQL 连接串继续通过 GOAUTO_DB_DSN 注入。

SYB 定时同步

迁移 1786701600000_syb_hourly_sync_job.go 会幂等写入 go-admin 的 sys_job,调用目标为 GoAutoSYBHourlySync,默认 Cron 为 0 5 * * * *、状态为启用。已有同调用目标的任务不会被迁移覆盖;管理员可在 go-admin“定时任务”中调整 Cron、启停状态和参数。

默认参数为 {"lookbackDays":2,"timezone":"Asia/Shanghai"}。当前实现允许回看 1~7 天;默认 2 天即当天和前一天。修改后需要让调度器重新加载任务(通常重启 Admin API)。

本地验证不要为了检查迁移而启动 Admin API:迁移本身不会访问 SYB,但启用状态的定时任务会在服务启动并到达下一次调度时间后访问已配置的 SYB。可只执行迁移并再次执行确认幂等:

Set-Location server
go run . migrate -c config/settings.yml
go run . migrate -c config/settings.yml

Web 验证

Set-Location web
pnpm install --frozen-lockfile
pnpm run lint
pnpm run build:prod

上游现存 lint 警告和构建体积提示不会阻断验证,但新增代码不得增加错误。

Android 验证

Set-Location android
.\gradlew.bat test
.\gradlew.bat assembleDebug

Android 骨架使用 Kotlin 1.9.22、AGP 8.2.0、Java 17 和 SDK 34。

真机联调或经管理员确认的 HTTP 部署可在构建时设置 GOAUTO_SERVER_URL。Debug 和 Release 都接受 HTTP 或 HTTPS Origin;服务端生产模式默认仍拒绝 HTTP,仅显式设置 GOAUTO_ALLOW_INSECURE_AGENT_HTTP=true 后允许。HTTP 会明文传输 Device Token、任务内容和执行结果。

原型验证

  • 直接打开 prototypes/server-admin.html 和 prototypes/android-agent.html。
  • 检查 375、768、1024、1440 像素宽度。
  • 用键盘完成导航,检查明显焦点、表单标签和删除/重置确认。
  • 开启 prefers-reduced-motion 后不应依赖动画表达状态。

必须真机验证的范围

  • 一加/ColorOS 的无障碍绑定、后台运行和安装保护。
  • 任务执行期间 Agent 只持有最长 5 分钟的屏幕唤醒锁,并在任务结束时释放;不解锁安全锁屏,也不常驻保持屏幕。
  • 浏览器打开 PDD、两层确认、商品详情识别和规格遍历。
  • 网络断开、登录失效、验证码、风控和规则删除后的快照执行。
  • 一台设备串行任务和 20 台设备连接稳定性。

cmautobuy 商品导入

从 server/ 运行 #70 独立命令。两个配置文件都必须是未被 Git 跟踪的本地文件;密码不接受命令行参数。

# 默认只读预检,不写两个数据库
go run ./cmd/import-cmautobuy-products --source-config "D:\chengma\cmautobuy\admin\config.yaml" --target-config "D:\OPC\goauto\config.yaml"

# 仅在检查 dry-run 精确数量、备份目标商品表并再次人工确认后运行
go run ./cmd/import-cmautobuy-products --source-config "D:\chengma\cmautobuy\admin\config.yaml" --target-config "D:\OPC\goauto\config.yaml" --apply

也可分别用 GOAUTO_CMAUTOBUY_CONFIG 和 GOAUTO_CONFIG 指定路径。来源配置支持 disabled 或 verify_ca;相对 CA 路径按来源配置文件目录解析。导入报告不得包含 DSN、密码或原始业务响应。

MySQL 8.4 写入路径的隔离测试只允许连接名称以 _test 结尾的数据库:

$env:GOAUTO_IMPORT_MYSQL_TEST_DSN="<仅由安全环境注入的 _test DSN>"
go test ./app/goauto/cmautobuyimport -run TestRunMySQL84DryRunAndApply -count=1
Remove-Item Env:GOAUTO_IMPORT_MYSQL_TEST_DSN

Windows Supervisor 托管

本机安装的 Go Supervisor 位于 D:\supervisor。GoAuto 的版本化配置源为 scripts/supervisor/goauto.conf,运行副本为 D:\supervisor\programs\goauto.conf。两个实例都读取仓库根目录已忽略的 config.yaml,Supervisor 配置不得保存数据库密码:

  • goauto-admin-api:调用 scripts/start-server.ps1,执行迁移后启动 Admin API。
  • goauto-admin-ui:调用 scripts/start-web.ps1,先等待 ports.server 对应的 /api/v1/health 返回 200,再启动 Admin UI;脚本会解析 Node.js 并直接运行项目的 Vite CLI,避免 Supervisor 子进程缺少 Node PATH。API 在 60 秒内未就绪时,脚本明确失败并由 Supervisor 按重启策略处理。
  • 日志:D:\supervisor\logs\goauto-admin-api.log、D:\supervisor\logs\goauto-admin-ui.log。
  • Supervisor 管理界面:http://127.0.0.1:9009。

部署或修改配置后执行:

Copy-Item -LiteralPath .\scripts\supervisor\goauto.conf -Destination D:\supervisor\programs\goauto.conf
D:\supervisor\supervisord.exe /c D:\supervisor\supervisord.conf ctl reload
D:\supervisor\supervisord.exe /c D:\supervisor\supervisord.conf ctl status

单独控制实例:

D:\supervisor\supervisord.exe /c D:\supervisor\supervisord.conf ctl restart goauto-admin-api
D:\supervisor\supervisord.exe /c D:\supervisor\supervisord.conf ctl restart goauto-admin-ui

Supervisor 托管期间不要再运行 start-all.bat 或重复启动对应单端脚本,否则会因 8010/9527 被占用而失败。两个 GoAuto 实例同时重启时,Admin UI 会等待 API HTTP 就绪后再监听 Web 端口;SYB 商品页对一次短暂网络断开做单次有界重试,不对认证、权限或业务错误重试。

Android Agent 0.3 四 Tab 真机检查

#88 起 Debug APK 版本为 0.3.0。除单元测试和构建外,在设备空闲且没有采集/采购任务时安装:

Set-Location android
.\gradlew.bat testDebugUnitTest assembleDebug
adb install -r app\build\outputs\apk\debug\app-debug.apk
adb shell am start -n cn.ilapage.goauto.agent/.MainActivity

真机至少检查:

  • 底部状态、采集、采购、设置四项都有图标与文字,默认状态页,触控目标不少于 48dp。
  • 状态页分别验证无障碍未开启、系统已开启但服务未绑定、服务已绑定就绪;返回系统设置后自动刷新。
  • 设置页服务器地址、设备名称、测试连接和保存重连反馈可读;测试连接只访问 GET /api/v1/health。
  • 任务执行中服务器地址、设备名称、测试和保存均禁用;Token 只显示“已配置/未配置”。
  • 采集/采购 Tab 在 #90 前只显示明确占位,不应出现采购写操作、PDD 凭据或支付入口。
  • Debug 和 Release 都应验证 HTTP/HTTPS Origin;使用 HTTP 时必须确认服务端已显式开启 GOAUTO_ALLOW_INSECURE_AGENT_HTTP=true,并记录明文传输风险。安装前必须确认设备空闲,避免重启 Agent 中断任务。

Android Agent 0.6.0 采购失败重试检查

  • 无真机授权时只运行 cd android && .\\gradlew.bat testDebugUnitTest assembleDebug,以及服务端采购包测试;不要调用采购重试接口,因为成功后新任务会进入正式采购队列。
  • 获得独立授权后,使用一条确认未进入不可逆边界、无 PDD 订单号的当前设备失败任务检查列表和详情入口、二次确认、旧任务保留、新任务编号/地址后缀、固定原设备与幂等反馈。
  • 取消确认不得发请求;成功后只能由既有队列执行,验证停止在创建待付款订单并读取订单号,永久禁止支付。

Android Agent 0.3.1 空闲返回与亮屏检查

#89 起 Debug APK 版本为 0.3.1(versionCode 4)。先确认设备空闲,再覆盖安装;安装后系统可能关闭无障碍服务,需要人工重新开启。

真机验证应至少覆盖:

  • 分别在采集、采购和设置 Tab 离开 Agent,完成一个不会支付的采集或演练任务,确认结果已提交后约 5 秒返回 Agent,并保持离开前 Tab;记录 ROM 是否限制后台 Activity 启动。
  • 在最近 Tab 不是状态页时重建 MainActivity 或 Agent 进程,确认恢复最近有效 Tab;无历史或无效值回退状态页,系统辅助功能按钮同样恢复最近一次有效 Tab。
  • 冷却 5 秒内创建任一类型新任务,确认 Agent 取消返回并继续按采购优先、采集其次执行。
  • 冷却期间断网,确认不会把网络失败当成空队列,也不会返回。
  • 冷却期间人工切换到其他 App,确认 Agent 不会强拉回;即使再切回 PDD,前台切换序号变化也会取消本次返回。
  • 使用 adb shell dumpsys power 或屏幕实际状态确认任务执行与冷却期间亮屏;返回、取消或服务停止后不再持有 cn.ilapage.goauto.agent:collection-task / :idle-return WakeLock。
  • 该流程不自动解锁安全锁屏,不点击创建订单或支付。

Android 系统辅助功能按钮检查(#97)

  • 覆盖安装可能被部分 ROM 视为无障碍服务配置变化并自动关闭服务;不得用 ADB 强行开启,必须由用户在系统设置中重新开启“采集采购助手”。
  • Android 8.0 及以上且系统已把辅助功能按钮分配给 GoAuto 时,单击图标应只把 Agent 切到前台并显示“状态”Tab;返回键行为保持系统默认。
  • 验收时先确认设备无活动任务,再检查点击不会打开 PDD、领取/重试任务、修改地址、创建订单或支付。不支持该系统按钮的 ROM 只验证无崩溃和现有 Agent 入口可用。

Android Agent 0.7.0 状态页下拉检查(#98)

  • 先确认设备没有活动任务,再覆盖安装 Debug APK;覆盖安装后若系统关闭无障碍服务,必须由用户在系统设置中重新开启“采集采购助手”。
  • 状态 Tab 顶部下拉应显示检查中,并分别验证:暂无任务、领取采集、领取采购、设备忙、无障碍未开启和网络失败。检查期间重复下拉不得产生并发请求。
  • 使用服务端日志或任务状态确认手动动作复用了既有 next → claim → start 调度;自动轮询仍为 15 秒、采购优先和单设备串行。
  • 状态页不再提供无障碍设置按钮或重复设备信息卡;设备身份只显示简短名称与编号,唯一无障碍入口位于设置 Tab。
  • 无授权任务时只验证空队列、忙碌、无障碍和网络反馈,不创建正式采购任务或订单,永久禁止支付。

Android Agent 0.8.0 任务记录刷新与同步检查(#99)

  • 运行 cd android && .\\gradlew.bat testDebugUnitTest assembleDebug assembleRelease,服务端运行 go test ./app/goauto/task ./app/goauto/purchase;确认 days 省略时仍为 30,1/3/7/15/30 天有效,0、负数和大于 30 均拒绝。
  • 真机覆盖安装前确认设备无活动任务。采集、采购 Tab 在列表顶部下拉应只刷新当前筛选、编号和当前页;重复下拉不得并发,成功、无变化和失败均有文字反馈,失败页仍有“重新加载”。
  • 设置页默认 7 天,可切换 1/3/7/15/30 天;分别检查完整成功、范围内无记录、单类失败和全部失败,按钮在同步中禁用并在结束后恢复。
  • 断网后打开有缓存的同范围列表,应显示最近同步摘要;任务详情仍需联网读取。检查应用数据中不存在 Device Token 明文、完整规则、PDD URL、地址、控件树或截图。
  • 只读刷新和同步无需创建正式任务;验收不得借此触发重新采集、采购重试、PDD、创建订单或支付。

Android Agent 采集任务间隔检查(#102)

  • 运行 cd android && .\\gradlew.bat testDebugUnitTest assembleDebug assembleRelease;单元测试至少覆盖两个输入的 0/15/600 秒边界、起始值大于结束值、0~0、固定范围、包含上下边界的可控随机、倒计时向上取整、过期清理、系统时间回拨截断和亮屏策略。随机源必须可注入,禁止概率性测试。
  • 真机覆盖安装前确认设备无活动任务。设置页检查“采集任务执行间隔”默认 15~15 秒、两个 0~600 整数输入、左值不得大于右值、保存反馈,以及修改设置不改变已经开始的倒计时。
  • 分别以成功、部分完成和失败的采集任务确认:结果被服务端接收后进入“在线 · 采集间隔中”;状态页下拉和采集记录“重新采集”均显示剩余秒数且不能绕过;间隔结束后现有调度器继续领取下一条采集任务。
  • 间隔期间创建采购任务,确认采购仍优先执行;采购结束后若原间隔未到期,采集继续等待。心跳、采购 Outbox、记录刷新与同步不受影响。
  • 将范围设为非固定值并完成一次采集,记录状态页显示的实际剩余秒数;间隔期间重启 Agent 前台服务,确认按同一抽取结果恢复且没有重新随机。使用 adb shell dumpsys power 确认 :collection-cooldown WakeLock 有界持有并在到期或服务停止后释放。
  • 此项验证不要求创建正式采购订单;没有单独授权时不得点击创建订单,永久禁止支付。

Android Agent 0.9.6 当前页面临时采集检查(#101/#107/#108/#109)

  • 自动化验证运行 cd android && .\gradlew.bat testDebugUnitTest assembleDebug,服务端运行 cd server && go test ./...;覆盖本地串行预占转移、分享 URL 白名单、唯一分享/复制入口、默认规则、创建/识别幂等、身份冲突和结果写回。
  • 本地 MySQL 8.4 必须先在明确授权后运行 cd server && go run . migrate -c config/settings.yml,确认迁移版本 1787790000000 已应用;重复执行应报告 0 个新增迁移。迁移保留旧任务并回填来源 admin。
  • 真机覆盖安装前确认设备空闲、Agent 0.9.6 已上报 collector.pdd.current-page-share.v1、无障碍已人工开启,服务端已有 Agent 手动采集默认规则。
  • 在 PDD 人工打开已授权的测试商品详情页,分别经 PDD 直接切换、桌面图标和最近任务进入 Agent,点击“采集”并确认;验证前台服务先启动,PDD 现有任务被拉回前台且仍停在原商品详情页,没有清栈、重置首页或启动浏览器,再依次完成分享、复制链接、goods_id 识别和常规采集。另验证 PDD 未安装、启动 Intent 缺失、前台切换超时和前台服务启动被拒绝时均有可见反馈。
  • 分别验证含 goods_id 的直链,以及白名单内无 goods_id 的 p.pinduoduo.com 短链和 mobile.yangkeduo.com/goods2.html?ps=...:直链不应触发 Agent 额外网络展开;无 goods_id 的白名单链接应优先由手机侧在 4 跳、每次连接/读取 5 秒、64KB 正文上限内展开,并覆盖 302/307。正文只含 refer_goods_id 时不得误判为商品身份。另覆盖链接后紧跟中文、多个链接冲突、白名单外跳转、超时和服务端兜底;诊断、日志和数据库不得出现链接原文、goods_id、剪贴板或响应正文。成功/部分成功应显示来源“Agent 当前页面”,相同 goods_id 不产生重复商品,任务详情与 PDD 最新档案一致。
  • 断开网络、离开详情页、制造重复分享入口或剪贴板不可用时,应得到普通人可理解的失败原因并释放设备槽;原始分享文案、剪贴板、控件树和截图不得出现在数据库或日志。
  • 验证期间不得自动搜索或选择相似商品,不得修改虾皮关联,不创建采购任务、不修改地址、不创建订单,永久禁止支付。

Android Agent 0.9.28 应用内更新检查(#143/#144)

  • 自动验证:cd server && go test ./app/goauto/apprelease ./app/goauto/access ./app/goauto/migrations;cd android && .\gradlew.bat testDebugUnitTest assembleDebug。服务端 APK 解析测试在 debug APK 已构建时读取真实 Manifest,当前期望 versionCode=41、versionName=0.9.28。
  • 新增迁移 1787983700000_agent_app_release.go 只创建 agent_app_release 和 agent_app_release_setting。未获得明确本机/正式库迁移授权时只做测试库验证。
  • APK 文件目录使用 GOAUTO_AGENT_RELEASE_DIR;缺省为服务端工作目录下 var/goauto-agent-releases,不得映射成公开静态目录。部署需让 Admin/API 进程对该目录具有创建、写入、读取和删除临时失败文件的权限。
  • 真机发布验证前确认设备空闲,再由管理员上传一个签名一致、versionCode 更高的 APK并显式设为当前。依次验证启动静默提示、设置页手动检查、下载进度/取消、断网、哈希不一致删除、未知来源引导和系统确认安装。任务执行中全部更新动作必须被阻止,心跳与前台服务继续运行。
  • 上传或设为当前属于发布动作,安装会改变设备应用版本;没有用户独立授权时不得执行。安装后系统可能关闭无障碍服务,只能由用户在系统设置重新开启。

Chrome 订单回填扩展验证(#316)

从仓库根目录执行:

cd chrome-extension
npm install
npm test
node --check service-worker.js
node --check content.js
node --check popup.js

自动化测试只使用合成 DOM 与 Chrome API mock,覆盖列表商品行负向选择、双展开与延迟字段、解析/冲突、启动互斥、停止、错误终态、扫描延迟增长、详情恢复、提交恢复、冻结配置、超时和可重试项。真实 PDD 浏览器点击、扩展安装和真实 Admin 上传不属于自动化验证,必须取得独立授权并在结果中明确区分。