ARTICLE DETAIL

资讯详情

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

Swissquote 千应用规模下的 Renovate 依赖自动化实践:从 700 个 PR 风暴到每周 2 小时维护

Swissquote 千应用规模下的 Renovate 依赖自动化实践:从 700 个 PR 风暴到每周 2 小时维护 Swissquote 千应用规模下的 Renovate 依赖自动化实践从 700 个 PR 风暴到每周 2 小时维护【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate本文基于 Renovate 官方仓库收录的 Swissquote 用户案例 编写作者为 Swissquote Bank 首席软件工程师 Stéphane Goetz。Swissquote 在 1000 生产应用中用 Renovate 自动化依赖更新历经四年实践沉淀出一套可复制的工程方法论——从最初的PR 打地鼠到分组、排程、自动合并再到自建调度器支撑 857 个仓库。读完本文你将理解为什么保持依赖最新比想象中复杂并掌握一套可直接落地的 Renovate 启用路径与配置策略。Swissquote Bank 拥有超过 1000 个运行于生产环境的应用程序涵盖服务services、守护进程daemons、Web 应用等多种形态它们的年龄从几天到十几年不等。在软件维护的众多议题中依赖管理是其中最具普遍性的一个第三方依赖就像一柄悬顶之剑sword of Damocles你永远不知道哪一个新问题会迫使你放下手头一切去升级软件。依赖安全在过去几年成为热议话题Log4Shell 漏洞、供应链攻击、SSL 根证书过期事件以及依赖自身引入的 bug都在提醒我们依赖带来的双重性——每个依赖在解决一个问题的同时也会给软件带来新的风险。而本文给出的答案正如标题所示保持依赖持续更新用自动化工具把这件事变成日常而非救火。为什么不想升级行不通有人会反驳如果新版本引入新的安全问题呢比如某个依赖的新版本恰好是供应链攻击的受害者从不更新反而能避开被感染的版本。这个论点听起来合理但你的应用并不存在于真空中——许多外部因素会在某个时刻强迫你升级而且往往发生在最不合适的时机。外部因素变化被迫改造应用假设应用运行的机器已过时需要迁移到新机器。看似装上去就行但现实通常是新版操作系统不允许安装过时的运行时runtime你需要为新硬件寻找兼容的运行时应用的依赖与新的运行时不兼容必须一并升级于是一个单一变更变成了组合变更每一步都可能以不同方式出错。所依赖的库被发现新漏洞如文章开头所述这可能演变成全员上阵的紧急事件。想象一个遗留应用持续集成CI常年失败——甚至可能根本不存在。部署一个库更新需要多长时间答案往往令人绝望。团队积累的依赖版本过多过杂只要团队或公司存在得够久这种状况几乎必然发生。升级库不只是 bump 版本号有时还意味着用一个库替换另一个库。如何看待你的依赖火车与认知负荷把软件想象成一列火车你是火车头每个依赖是一节车厢。火车头能拉动几十甚至上百节车厢但总有极限大脑同理每个依赖都在增加认知负荷cognitive load。举例来说如果项目里用了三个不同的缓存库你以及现在和未来的同事可能都需要了解每个库的工作原理。面对以下两个项目你更愿意接手哪个一个依赖基本保持最新、升级依赖后跑通部署流水线就能继续日常工作的项目一个几年无人触碰、每个依赖都已过时、CI 在所有分支上全红如果还在运行的话的项目这不是夸大其词——作者表示见过非常接近这些情况的真实案例。不妨自问有多少次你创建了项目却从未升级过它的依赖有多少次你回到旧项目想用新库却因为另一个库版本过旧不兼容而无法使用在你们的所有应用上升级某一个依赖能有多快时间推移项目来来去去你很可能同时拥有十年历史的老项目和刚创建的新项目有的用最新版 Java 最新版 Spring有的库略微过时还有的在使用七年没有发版的老框架。每家公司都有一两个仍在运行的老古董项目大家谈论时一笑置之但一旦有人提出要改动它气氛就紧张起来。Swissquote 的三种依赖升级策略作者识别出团队升级依赖的三种主流做法只做关键修复仅更新带有 CVE 的依赖机会主义童子军法则接手项目时先升级依赖再做业务任务定期更新手动或用工具每隔几周例行升级策略一只做关键修复每当某个库发布修复漏洞的更新安全团队会紧盯关键漏洞并迅速警告所有受影响团队。Swissquote 还配置了 GitHub 的 Dependabot Alerts通知团队发现漏洞以及应升级到哪个安全版本。这个策略大体可行但风险很高如果项目很久未被触碰根据漏洞严重程度需要升级的依赖数量可能很多升级耗时将显著增加。策略二机会主义童子军法则规则很简单接到项目任务后第一步是升级它的依赖然后再开始实现任务。这类似于在每个业务项目上顺手偿还一部分技术债有助于在漏洞出现时保持主动并为所有项目维持一条基线。策略三定期更新依赖听起来容易每隔几周检查过时的依赖bump 版本跑 CI通过就推送。但能不能自动化于是 Renovate 登场了。试试 Renovate2019 年 11 月作者发现 Renovate 提供了可配合私有包仓库private package registries在本地运行的 Docker 镜像。应用会自动创建拉取请求PR告知依赖更新CI 自动构建让你知道合入是否安全。首次尝试时Swissquote 启用了 30 个仓库一个 cron 任务每小时运行并创建 PR——第一个月收到了700 个 PR陷入了无休止的PR 打地鼠每合并一个另一个立刻顶上。Renovate 的真正优势在于高度可配置且配置可以共享。Swissquote 很早就为团队创建了带自定义策略的共享配置shared configuration核心策略包括将minor和patch依赖的 PR分组Group PRs内部依赖internal dependencies可在一天中任意时间创建 PR第三方依赖third party dependencies只在周末创建 PR这大幅降低了 PR 噪音第二个月收到 400 个 PR第三个月只有 200 个。从依赖自动化中学到的五件事代码覆盖率要能预警刚开始时团队漏掉了一些破坏性更新——构建是绿的但应用一部署就崩。必须先确信测试覆盖率能兜住升级风险。足够自信后自动合并是必须的团队在约 100 个仓库上启用了 Renovate通常每周只花1–2 小时就能保持依赖最新。走在最前沿流血的不是前沿是你第一时间升级到新 major 版本可能踩坑。曾多次遇到 patch 版本破坏库的情况通常第二天就有修复但团队仍花了几个小时调试为什么更新破坏了应用并为此开了不少 Issue、提了一些 PR。升级与发布解耦由于团队主要提供库library不希望每次依赖升级都发布新版本这会在下游产生 PR 噪音。他们决定仅在关键升级或贡献后发布并用一个仪表盘提示某个仓库超过 30 天未发布。关于 Renovate 的评价接下来的部分看起来像广告或赞助内容不是。我们只是这个产品的忠实粉丝。Swissquote 被 Renovate 的 Docker 镜像轻松上手所吸引而最终确认选择的是它海量的功能与配置选项详见 Configuration Options。团队喜爱的特性与选项包括共享配置presetsSwissquote 为所有仓库设置了一套默认配置每个团队可在此基础上扩展自己的实践参见 Presets 概念与 GitHub Dependabot alerts 集成提升漏洞 PR 优先级、尽快发送安全修复 PR参见 vulnerabilityAlerts 配置项规则可全局定制也可按包定制参见 packageRules 配置项支持私有包仓库参见 Private Packages 入门支持 70 语言与包管理器Maven、Docker、npm、Docker Compose、Python 等参见 支持的 Manager 列表customManagers选项以自定义方式使用依赖时可将任意文本模式转换为依赖参见 customManagers 配置项Renovate 提供本地部署on-premise选项也可使用 Mend Renovate App。Swissquote 没有使用官方 on-premise 方案而是基于开源 Docker 镜像自建了调度器。四年后的数据自建调度器的理由以下数据更新于 2023 年 11 月。Swissquote 从 2019 年开始使用 Renovate最初使用现已弃用的renovate/proDocker 镜像以 GitHub App 形式安装供早期采用者使用。很快他们撞上了最大的限制这个 Docker 镜像串行地one after another处理所有仓库单轮循环耗时数小时且日志没有按仓库分离排查非常困难。因此他们自建了调度器每小时将所有仓库排队运行GitHub App 事件则触发单个仓库运行同时开始收集指标并按仓库单独存储日志。以下是截至 2023 年 11 月的一些统计857 个仓库启用了 Renovate约占 2000 个活跃仓库的四成多11000 个 PR自安装以来被合并上个月合并了239 个 PR由于要反复克隆海量项目Renovate 机器上两块 SSD 先后报废团队不强制任何团队使用 Renovate各团队可为每个项目自行决定是否启用。调度器如何工作调度器是一个 Node.js 应用维护一个内存队列in-memory queue并启动 Docker 容器来运行 Renovate。调度器定期向 InfluxDB 发送数据点再通过 Grafana 展示。仪表盘上的所有信息来自三类测量数据队列Queue每 5 分钟发送一次队列大小与当前运行中的任务数Webhook收到 GitHub webhook 请求时发送该事项处理时长的数据点运行Runs每次运行后发送运行时长、成功与否以及创建/更新/合并/关闭的 PR 数量队列由 webhook或按固定间隔重新入队所有仓库来填充。每个仓库启动一个 Renovate Docker 镜像并将其日志管道输出到文件。这让团队能够并行运行 10 个 worker——技术上可以更多但团队决定不冲击自家的 GitHub 实例。Swissquote 中 Renovate 的未来目前并非所有团队都在使用 Renovate有些团队仍偏好手动更新依赖。Swissquote 计划为所有仓库的关键依赖启用 Renovate并希望让它足够有用、足够简单从而被更多团队采纳到更广泛的依赖上。你应该如何开始使用 Renovate如果这篇文章说服了你以下是经过验证的启动路径先手动升级再启用 Renovate如果已知软件非常过时不要立刻启用 Renovate——你会被 PR 淹没Swissquote 深有体会。先花时间手动升级所有能升的npm outdated、mvn versions:display-dependency-updates或你所用包管理器的等价命令可以帮助你起步测试应用并提交这些变更。认真阅读首个配置 PR启用 Renovate 后会收到一个用于添加配置文件的 PR务必仔细阅读这个首个 PR它会解释你将收到什么类型的 PR 以及何时收到。务必设定排程schedule否则一天 24 小时都可能收到 PR。Swissquote 将所有第三方依赖排程在周末测试通过则自动合并周一早上再调查失败的 PR。关于schedule的语义与 Cron 写法可参考 Configuration Options 中的 schedule 章节它只是允许创建分支的时间窗口而不会主动触发运行官方建议每个排程窗口至少留 3–4 小时并优先使用五段式 Cron 语法分钟位必须用*。分组 PR如果每个 PR 都要过 CI负担会很重。当大多数 PR 都能通过后就可以开始将 minor 和 patch 更新分组使每个仓库只收到单个 PR代价是问题排查变得更复杂。以 90 个启用 Renovate 的仓库为例Swissquote 平均每周只需调查4 个 PR其余全部自动合并。一段时间后启用自动合并确保测试足够可靠避免把未经测试、上线即崩的升级合入。automerge的具体行为可参考 Configuration Options 中的 automerge 章节。这一切努力值得吗答案是肯定的。Swissquote 花了将近一年——比预想长得多——才追上技术栈中所有依赖的最新版本。但当测试足够可靠、可以启用 PR 自动合并后团队对更新软件栈所做的工作感到满意他们知道当计划外变更到来时自己已经准备好了。这一天在 2021 年 12 月到来——Log4Shell爆发。瑞士报价银行只花了几个小时就发布了刚合并的 PR部署了少数受影响的应用并通知了依赖其库的团队。事实上因为那一周 Log4j 漏洞接连被发现他们不得不这样快速响应了三次。最后请记住保持依赖最新不只是工具问题更是流程问题。每个团队都需要回答这些问题何时合并这个 PR如何处理构建失败的 PR外部库的新 major 版本与其他库尚不兼容怎么办何时发布这源源不断的库更新想要白天、夜里还是仅周末收到 PRSwissquote 已经为自己的场景找到了答案而你的答案需要你来决定。从本文的实践中可以看到依赖自动化真正的价值不在于消灭维护工作而在于把被迫在错误时间救火变成任何时候都能从容应对——这需要工具、测试覆盖率、排程与分组策略、自动合并机制以及一个明确的发布流程共同支撑。【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表