CircleCI 缓存密钥臭虫, 它寂静地服务于您的构建结构依赖
The CircleCI Cache Key Bug That's Silently Serving Your Builds Stale Dependencies
你的CircleCI管道是绿色的。 每一份工作都会通过 然而你的应用程序却与一个月没有运出过的依赖性版本相呼应——没有人承诺,没有人碰上它,它只是悄悄地出现在制作中. 如果你追过这样的虫子 罪犯几乎不是你的密码 这是你的缓存钥匙。 这是五分钟的读取和十五分钟的修补。 快赢周五,部署到你的 失败模式 CircleCI 的依赖缓存工作在一个简单的合同上: 当依赖性改变(通常是锁文件检查和)时, 您会从一个会改变的事物中计算出一个密钥, 您会保存/ 恢复一个与该密钥相绑的缓存 。 合同以三种具体、极为常见的方式中断: 你检查错误的文件。 看起来很合理,直到有人通过...
你的CircleCI管道是绿色的。 每一份工作都会通过 然而你的应用程序却与一个月没有运出过的依赖性版本相呼应——没有人承诺,没有人碰上它,它只是悄悄地出现在制作中. 如果你追过这样的虫子 罪犯几乎不是你的密码 这是你的缓存钥匙。 这是五分钟的读取和十五分钟的修补。 快赢周五,部署到你的 失败模式 CircleCI 的依赖缓存工作在一个简单的合同上: 当依赖性改变(通常是锁文件检查和)时, 您会从一个会改变的事物中计算出一个密钥, 您会保存/ 恢复一个与该密钥相绑的缓存 。 合同以三种具体、极为常见的方式中断: 你检查错误的文件。 似乎很合理,直到有人在不触碰的情况下撞倒了过渡性依赖。 验收不动. CircleCI快乐地手回上周的. 做前缀匹配, 人们觉得它确实匹配。 CircleCI首先尝试您的主要密钥,然后按顺序倒入,第一个是针对已存在的缓存条目进行前缀匹配——而不是"给我最新的精确匹配". 如果您的还原 keys 列表过于粗糙( 例如只是) , 您可以恢复从一个完全不同的分支所建的缓存, 其锁文件完全不同, 任务不会失败 。 它只会悄悄地安放一无所有(cache hit,看到模块"在那里"),或者运行在错误的版本上. 没有版本出逃舱门. 当你不可避免地需要强迫每个人的缓存失效——一个被腐蚀的缓存条目,一个包管理器迁移,一个锁文件格式的改变——时,没有便宜的方法可以做到这一点,因为关键格式的设计从未考虑到手动快取. 每一个都沉默地失败了。 无红色 X. 日志无出错 。 3天后,一个臭虫报告 没有人可以在当地繁殖 因为当地是好的。 固定 替换您当前缓存块的形状 : 4 个特定修改, 每个修改上面的失败模式之一 : 检查锁定文件, 而不是列表 。 / / / / – 任何实际贴出您解析的版本 。 唯一一个"什么都没有改变"的文件 是关于你依赖树的真实声明 (或者,或者)作为安装命令,永远. 这是您尚未修复的失败模式的安全网: 如果缓存确实恢复了 stale, 被冻结的安装拒绝静静地进行不匹配的锁文件, 而不是悄悄地调和它 。 你希望那份工作红了 而不是跟错树绿了 从最具体到最小的顺序, 并停止一个级别 不足"匹配任何东西。" 分会范围精确匹配第一,分会范围前缀第二,全球前缀最后,作为全新的分会真正最后的手段. 不要仅仅有作为你唯一的倒计时——这是让分支完全用不同的锁文件恢复缓存的一行. 当您需要一个干净的字串时, 跳出主要版本的符号( ) 。 这是你的手动缓存器。 因为它被烤入了密钥本身,强迫每个人无效是一行的PR,而不是CircleCI的支持票或者通过项目设置UI手取核子缓存的旅行. 验证它真的有用 不只是运送YAML的改变 并相信它。 在确认行为的同时, 加入一个单行声明工作步骤, 为期一周 : 调整软件包名称以适应之前被咬过的任何依赖, 或是您团队最想知道的运出错误版本 。 如果这个grep失败了,你的缓存和你的锁文件已经相去甚远——现在它在CI,而不是静静地,在生产上都大失所望. 单簧管陷阱 如果你在Yarn/npm工作空间或一个有多个锁文件的单列波上,校验和功能只将你告诉它的东西散开. 在 repo root 中,无法捕捉到对工作空间软件包自身依赖性的更改,除非您的软件包管理器将分辨率写回了根锁文件(大多数是,但为您验证). 如果你有嵌入的锁文件 不该有的