ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI编排实践:DeepSeek Harness+GitHub Actions实现Windows打包流水线

AI编排实践:DeepSeek Harness+GitHub Actions实现Windows打包流水线 那次给客户发新版我照旧手动开虚拟机出 Windows 安装包装完才发现忘了把 VC 运行库打进去。客户现场装不上运维和技术支持在群里轮番我那个下午我基本是在导日志和重新打包里度过的。当天晚上我就下了决心出包这件事必须自动化而且要让 AI 参与编排。之前我一直在用 ZCode 这类 AI 编程工具写辅助脚本。说实话它帮我写过不少打包脚本和配置文件但我的真实需求不只是“生成代码”而是一条能复用的、可审计的构建流程从代码提交到跑测试再到出 Windows 包、生成更新说明。ZCode 管不到这一步我需要的其实是一个可以编排 Agent 的“工头”而不是一个聊天窗口。后面我切到了 DeepSeek Harness用 GitHub Actions 把 Windows 打包整个搬到了云端流水线。现在这套链路已经稳定跑了几个月。流程变成了推送一个 tagGitHub Actions 在 Windows runner 上拉代码、装依赖、跑测试、打 exe、上传 artifact我再下载做签名和分发。这篇不是复刻官方文档我会把换工具的决策过程、Harness 的部署细节、Actions 流水线的排坑经历都摊开写。如果你也被“手动出包”折磨过或者想让 AI 真正参与构建流程而不是停留在聊天框里这篇应该对你有用。1. 离开 ZCode 的真实原因不是它不够好而是它管不到流程1.1 ZCode 解决过的问题我不否认说句公道话ZCode 最早确实解决了我一部分问题。它是面向编程场景的 AI 工具直接对接模型来生成和修改代码。最常用的场景是让它帮我写 PyInstaller 的 spec 文件、补 requirements.txt、生成 gitignore、甚至解释某些报错。对一个经常跟多环境打交道的开发者来说这比反复查文档快得多。但用着用着你会发现这类工具的核心交互模式是“对话”。你问一句它答一句你让它改一处它生成一段 diff。适合“点状”任务不适合“链式”任务。我要的 Windows 打包流程是线性的确定版本号 → 更新依赖 → 跑单测 → 编译 exe → 收集产物 → 生成更新日志。每一步之间有依赖关系需要按顺序执行还要能重复跑。对话式工具每次都要重新交代上下文天生就做不好这件事。1.2 三个让我最终决定下车的点第一个是黑盒顾虑。当时社区里有一些关于 ZCode 数据传输行为的讨论我没有实锤也不会去下“它一定偷代码”这种结论。但这里有个很现实的问题我手上有企业内部项目的源码公司安全红线是代码不允许未经审批外发。一个闭源的、数据上报策略无法审计的工具我没办法在项目里长期使用。哪怕你只有 1% 的怀疑面对核心代码库这 1% 都赌不起。第二个是流程颗粒度不对。ZCode 的定位是“写代码”可我缺的不是代码是“代码写完之后的事情”。举个例子我有个工具打包时需要把版本号写进 exe 的属性页、同时更新一个 version.json 给自动更新服务用。这个逻辑不复杂但需要稳定重复执行。我更希望有一个配置化的方式把这类操作固定下来而不是每次让 AI 重新生成一遍逻辑偶尔还会生成出参数对不上的版本。第三个是多任务并行。我希望“构建助手”“代码审查助手”“更新日志助手”能同时跑或者按 DAG 编排顺序执行。ZCode 的对话形态撑不起这种多智能体场景。DeepSeek Harness 正好是开源的多智能体编排框架主 Agent 下面可以挂不同的 Skill 和 Plugin模型后端也能切换适合我把整个构建流程抽象成可执行的技能。1.3 拆掉重来时我给自己定的标准决定切换工具前我列了一个需求清单拿来衡量新方案是否合格可审计配置全文本化数据流向明确能私有化部署模型。可编排能把代码检查、构建、打版本、生成日志串成一条流水线。可编程控制能通过 CLI 或 API 触发能被 CI 调用。可回退升级新版本后能方便退回旧版本不被工具绑架。按这个清单筛选下来DeepSeek Harness 最合适的点在于它是开源的Skill 机制能把“Windows 打包”定义成一个流程模板而且它支持接入本地模型。GitHub Actions 则负责解决“在哪里跑构建”的问题。两者配合才算是把我要的闭环补齐了。2. DeepSeek Harness 部署要点从安装到第一个 Skill2.1 Harness 的架构认知它不是一个聊天框是一个调度系统开始装之前建议你先建立一个整体认知。DeepSeek Harness 本质上是多智能体的运行与编排环境你在里面定义“谁在什么时候调用什么工具用哪个模型回答问题”。我习惯用一个类比来解释它像一条生产流水线模型是工人Skill 是工序卡Plugin 是外挂设备而 Harness 本体是那个安排先后顺序的工头。工头不亲手拧螺丝但它知道先拧哪颗、后拧哪颗流程不对还能停下来求助。我跑起来之后发现这套抽象对工程场景特别受用。因为 Windows 打包本身就是一个流程你可以在 Harness 里显式定义“先提取代码变更列表再跑测试最后执行打包脚本”每一步的输入输出都能追踪。这比在对话窗口里让 AI 凭感觉生成一段脚本要可靠得多。2.2 安装与初始化动手前先看这两条安装没什么神秘的官方仓库 README 里写得很清楚。大致是拉取代码、创建虚拟环境、安装依赖。我个人习惯把仓库克隆到/opt/harnessLinux 上或D:\Tools\harnessWindows 上然后用虚拟环境隔离依赖避免污染全局 Python。初始化时它会在用户目录下生成配置目录里面包含模型配置、Skill 目录、Plugin 目录和日志文件。第一次跑会让你选择模型后端。这里有两个方向连云端 API或者接本地模型。我的建议是前期先用 API 把流程跑通后面再根据隐私需求切本地模型。不要一上来就在本地部署大模型先把编排逻辑跑通了模型后端随时可以换。2.3 配置模型密钥不进仓库配置模型时我只强调一点API Key 不要写进任何 YAML 或配置文件再提交到 Git。Harness 支持从环境变量读取密钥我会在配置里写成api_key: ${DEEPSEEK_API_KEY}然后在本地或 CI 的环境变量里注入真实值。这不是小题大做我见过太多人把 key 提交进仓库几小时内就被爬虫扫走。如果你要接本地模型路径也不复杂。Harness 的模型后端支持 OpenAI 兼容协议所以 Ollama、vLLM、LocalAI 这类服务都可以。我本地试过用 Ollama 跑 Qwen 系列模型配置 base_url 指向http://127.0.0.1:11434/v1就能接通。这样在需要处理高敏感代码摘要时可以一键切到本地方案代码完全不出内网。2.4 写一个 Windows 打包 Skill把流程固化下来Skill 是 Harness 里最核心的扩展单位。一个 Skill 本质上是一个定义文件加若干可执行脚本。定义文件里写清楚这个技能是干嘛的、支持哪些指令、允许调用哪些命令、输出什么结果。下面的示例是我的win_buildSkill 的核心配置骨架name: win_build description: 在 Windows 环境下执行桌面工具打包包括版本号注入和产物收集 allowed_tools: - git - python - pip - pyinstaller steps: - name: ensure_deps command: pip install -r requirements.txt - name: inject_version command: python scripts/inject_version.py --version {{ version }} - name: build_exe command: pyinstaller --clean --onefile --name app windows_main.py - name: collect_output command: python scripts/collect_output.py重点在于allowed_tools这一项。它相当于给 AI 划了一条命令边界你只能调用这几个可执行文件不在列表里的命令一律拒绝。我踩过坑之后才意识到这一步不是可选项是必选项。第一次没配边界AI 分析打包产物体积时居然想直接执行Remove-Item来清理“无用文件”幸好 Harness 会弹确认我及时拦住了。给 AI 限定工具边界跟给外包员工开权限账号是一个道理最小权限才能不闯祸。2.5 关于版本回退清理缓存比换代码更重要DeepSeek Harness 迭代很快我也遇到过新版本行为变化导致 Skill 跑不通的情况。搜索时看到不少人问“怎么退回到 v0.1.5-rc.2”这个我熟。除了在 Git 里切回对应 tag还要注意清掉 Harness 的缓存目录尤其是 Skill 编译缓存和对话历史缓存。只回退代码不清理缓存你切回去会发现新版本的残留配置还在问题依旧。正确的操作顺序是先进仓库执行git checkout v0.1.5-rc.2再删掉用户目录下 Harness 的缓存目录最后重新初始化配置。退版本之前最好把当前版本里的 Skill 配置备份一份回退之后直接恢复省得重新配。3. 用 GitHub Actions 把 Windows 打包变成流水线3.1 为什么我选了 GitHub Actions而不是 Jenkins 或商业打包服务选择 GitHub Actions 之前我对比过几个方案。Jenkins 我熟功能也强大但需要在公司维护一台常驻服务器。团队里没人愿意当这个“Jenkins 保姆”插件升级、构建节点维护、权限管理都是持续成本。商业云打包服务我也看过但有几个痛点一是打包过程在别人服务器上需要上传源码敏感的内部项目不敢传二是定制能力受平台限制很多冷门依赖装不上。GitHub Actions 的好处是 runner 可以托管也可以自建工作流描述是纯文本 YAML天然适合代码审查。Windows runner 官方直接提供 Windows Server 环境Python、PowerShell、常见构建工具都是现成的不需要自己初始化系统。而且 Actions 的计费对私有仓库也有免费额度小项目基本够用。对个人开发者和中小团队来说它是目前综合成本最低的方案。3.2 完整 Workflow 配置从拉代码到传产物下面这份 YAML 是我实际在用的简化版去掉了内部通知部分只保留核心流程name: build-windows on: workflow_dispatch: push: tags: - v* jobs: build: runs-on: windows-latest steps: - name: Checkout uses: actions/checkoutv4 - name: Setup Python uses: actions/setup-pythonv5 with: python-version: 3.11 - name: Cache pip uses: actions/cachev3 with: path: ~\AppData\Local\pip\Cache key: ${{ runner.os }}-pip-${{ hashFiles(**/requirements.txt) }} restore-keys: | ${{ runner.os }}-pip- - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pyinstaller - name: Inject version run: python scripts/inject_version.py --version ${{ github.ref_name }} - name: Build exe run: pyinstaller --clean --onefile --name app windows_main.py - name: Upload artifact uses: actions/upload-artifactv4 with: name: app-windows-x64 path: dist/app.exe触发条件我设置了两条workflow_dispatch支持手动触发方便临时出包push带标签自动触发比如推送v1.4.0这个 tag 就自动开始构建。这样版本发布和出包天然绑定不会出现“代码改了但忘打包”的尴尬。Setup Python一步我固定用 3.11不是因为最新版不好而是老项目里有几个依赖库在 Python 3.12 上还有兼容问题。如果你的项目是新的建议直接在测试环境试跑 3.12 或 3.13能用就用新版。跑在旧版本上只是求稳不代表新版本不行。3.3 版本号注入tag 不是摆设要真正写进产物很多人打出来的 exe 在“文件属性 → 详细信息”里看不到版本号就是因为构建时没有注入版本信息。我把github.ref_name也就是你推送的 tag比如v1.4.0作为参数传给inject_version.py脚本里会做两件事把版本号写入version.txt供程序读取同时更新 PyInstaller 的版本资源文件。这样打出来的 exe属性页里能正确显示产品版本自动更新服务也能通过接口拿到版本号做比对。你可能会问tag 名是v1.4.0直接拿来用不会带上v吗对所以脚本里要处理一下去掉前导的vimport argparse parser argparse.ArgumentParser() parser.add_argument(--version, requiredTrue) args parser.parse_args() version args.version.lstrip(v) print(fversion{version}) # 示例写入 version.txt with open(version.txt, w, encodingutf-8) as f: f.write(version)这个细节看着小实际影响很大。版本号写不进去后续的自动更新和问题追溯全都会乱套。3.4 自建 Runner 还是用托管的 windows-latest如果你只是打包公开项目直接用 GitHub 托管的windows-latest就够了省心。但像我兼顾公司内部项目就不得不考虑代码不出内网、依赖私有源、需要挂内部数字证书这几个因素。这种情况下自建 Runner 反而更合适。我列过一张对比表你可以直接参考对比维度托管 Runnerwindows-latest自建 Runner运维成本零官方维护需要自己装环境、打补丁源码安全代码会上到 GitHub 服务器代码留在内网或指定机器依赖访问只能访问公网依赖源可访问内网私有源证书安装无法长期保存内部证书可以预装企业证书网络策略受限于 GitHub 服务可配合企业网络策略我现在的方案是混合使用公开项目走托管 Runner内部项目走自建 Runner。这样既省了公共项目的运维成本又保住了内部项目的安全红线。4. AI 编排 云端构建的完整链路从 PR 到发布包4.1 用 Harness 做“PR 体检”把无效构建提前拦下来流水线跑顺之后新的问题是每次 PR 都触发构建但有些改动只是文档说明或注释调整根本不需要出包。构建本身要花费几分钟跑多了浪费额度。我在 Harness 里做了一个pr_reviewSkill让它充当“体检医生”。PR 创建或更新时它会把变更文件列表和 git diff 的统计信息交给模型判断这次变更是否影响最终产物。如果只是README.md或.github/workflows下的文档变动它直接评论一个“无需打包”如果涉及核心代码或依赖文件它会评论“建议出包请维护者确认”。这一步最开始我只让它在本地输出结论后来接了 GitHub CLI 让它把结果写成 PR 评论团队其他人也能看到。效率提升很明显无效构建减少了一半以上。需要说明的是这里我只把文件列表和 diff 统计发给模型不会把完整源码外发隐私方面是安全的。4.2 自动生成 Changelog让 AI 只读提交历史不直接动仓库以前每个版本发布我都要翻一遍 git log手动整理哪些是新增、哪些是修复。现在这个活也交给 DeepSeek Harness 了。在 Actions 里增加一个步骤读取git log中从上一个 tag 到当前 tag 的提交信息通过 DeepSeek API 分类汇总生成结构化的更新说明。我画个最简单的实现思路用 Python 调用 APIimport json import os import requests commits os.popen(git log --oneline v1.3.0..v1.4.0).read().strip() prompt f 根据以下 git 提交记录生成中文更新日志。 要求按「新增」「修复」「优化」三类分组每条不超过30字。 提交记录 {commits} resp requests.post( https://api.deepseek.com/chat/completions, headers{ Authorization: fBearer {os.environ[DEEPSEEK_API_KEY]}, Content-Type: application/json, }, json{ model: deepseek-chat, messages: [{role: user, content: prompt}], temperature: 0.3, }, timeout60, ) data resp.json() changelog data[choices][0][message][content] print(changelog)我特意强调一点这个脚本只是“生成”更新日志不会把日志直接推回仓库。Changelog 推到发布描述里还是需要人工确认的。因为 AI 偶尔会漏掉破坏性变更或者把同一件事拆成两条写。自动化能做到“帮你起草”但“确认发布”这个动作还是要留给人。这是我在踩过几次坑之后坚持的原则。4.3 签名和分发自动化止步于“签名”是正确的GitHub Actions 可以自动构建但不能替你完成真正意义上的代码签名。注意区别生成一个自签名证书谁都能做但用自签名证书签出来的 exe在 Windows 上依然会触发 SmartScreen 警告用户要额外点几步才能运行。企业正式分发必须用受信任的 EV 证书这类证书通常要求硬件密钥存储、严格的私钥管理。我不会把 EV 证书的私钥放进 CI 服务器风险太大了。所以我的流程是Actions 把打好的 exe 和版本文件上传为 artifact我下载之后在本地或专用签名机上用硬件令牌完成签名再推到内部更新服务器或发给客户。自动化完成了 90% 的重复劳动签名这 10% 保留人工兜底是安全和效率的平衡点。4.4 跑通后的时间账整套链路跑通后我算过一笔时间账。以前手动走一遍 Windows 打包流程包括开虚拟机、装依赖、跑测试、打 exe、整理产物大约需要 1.5 到 2 小时。现在从推送 tag 到 artifact 就绪流水线自动跑完大约 10 到 15 分钟这段时间我可以去干别的。更重要的是以前“上次能成这次不能成”的玄学问题基本消失了因为每次构建都从同一套干净的 Windows 环境开始环境差异导致的怪问题被直接消灭掉了。5. 排坑实录Windows 打包流水线常见故障速查5.1 Windows runner 环境三大坑第一个坑是执行策略。GitHub Actions 的 Windows runner 默认用的是 PowerShell但 PowerShell 脚本默认执行策略是 Restricted直接跑.ps1脚本会报错。解决办法是在脚本前加powershell -ExecutionPolicy Bypass -File或者直接改用shell: bash来执行命令Actions 的 Windows runner 自带 Git Bash很多命令在 bash 里跑反而省心。第二个坑是路径分隔符。GITHUB_WORKSPACE在 Windows runner 上指向D:\a\repo\repobash 脚本里要用正斜杠才能正常拼接。我经常看到有人混合使用$GITHUB_WORKSPACE\scripts\foo.py和python $GITHUB_WORKSPACE/scripts/foo.py因为转义问题报“路径不存在”。建议全程统一用正斜杠Windows 的 API 是能认正斜杠的。第三个坑是杀毒软件扫描。Windows runner 上跑着 Windows Defender构建完成后它可能会对新生成的 exe 做扫描这本身不会报错但如果你的构建脚本紧接着就要读取这个 exe偶尔会碰上文件被占用的报错。遇到这种情况可以在构建步骤后加一个短暂的等待重试逻辑或者用sleep 5缓解。当然如果你打包的工具本来就容易被误报那是另一个要单独处理的话题。5.2 DeepSeek Harness 配置类问题先说“本地模型思考模式回空”的问题。我有段时间给 Harness 接本地模型发现设置成深度思考模式后模型偶尔会返回空内容。排查下来是参数的问题本地小模型对temperature和top_p的敏感度很高某些采样参数组合下模型会陷入低置信度循环最终产出空回复。把temperature调低到 0.3 左右同时把max_tokens设置得足够大情况就缓解了。如果还是空就把流式输出关掉再试。再说“Skill 执行越界”的问题。我在前面提到Skill 必须配置allowed_tools白名单。但白名单不是万能的AI 仍然会尝试用允许的命令做不允许的事比如用 Python 的os.remove删文件而 Python 本身在allowed_tools里。解决办法有两个层面一是在 Skill 的指令提示里写明“禁止删除构建目录以外的文件”二是在 Harness 的执行确认机制上保留高危操作的人工审批。这两个我都在用缺一不可。还有一个很细节的问题API 超时。当提交记录特别多时请求 DeepSeek API 生成 changelog 可能会超过默认超时时间。我的脚本里把timeout设成了 60 秒并且加了重试逻辑。第一次超时后等几秒再试基本都能成功。如果你的提交量很大建议分批处理比如按目录或者按时间切块一次传的提交记录控制在合理范围内。5.3 超实用速查表现象常见原因解决办法PowerShell 脚本不能执行执行策略限制加-ExecutionPolicy Bypass构建脚本报“路径不存在”路径分隔符混用统一用正斜杠exe 生成后被占用/杀毒误报Defender 扫描构建后加等待或重试逻辑版本号没有写进 exe版本资源文件未注入构建前执行inject_version.py本地模型返回空内容采样参数不匹配调低temperature关闭流式AI 尝试执行计划外命令Skill 边界没划清配置allowed_tools 高险操作人工确认API 调用超时上下文过长加长 timeout加重试分批请求回退 Harness 版本后行为异常缓存未清理退 tag 后清缓存再初始化artifact 名称显示异常名称含中文或特殊字符artifact 名称只用英文、数字、连字符依赖安装缓慢缓存未生效配置 actions/cache 缓存 pip我个人的体会是这套链路跑通之后最大的收获不是省了多少时间而是出包结果的一致性。以前手动出包能不能成功一半看机器状态一半看运气现在每次构建都从同一个干净环境开始流程固化参数沉淀成代码产品的发布动作真正变得可控了。如果你也想往这个方向改造我建议别一上来就追求“AI 全自动出包”。先做最小闭环用一个简单的 GitHub Actions workflow 把一次 Windows 打包跑通哪怕只是打一个 hello world 的 exe。跑通之后再加版本号注入、缓存优化。最后再接 DeepSeek Harness 的智能体检和 changelog 生成。这样每一步都有明确的验证点出问题也知道是哪个环节的锅。最后再分享一个小技巧把 Harness 生成的构建建议直接写成 GitHub PR 评论比任何 IM 通知都管用。因为评论和代码变更绑定在一起点开 PR 就能看到来龙去脉事后追溯也方便。就用这个习惯收尾希望你下次出包也能安心地把时间花在真正需要人的事情上。
返回列表