返回资讯中心
外部精选
软件工程
#开发者实时流

开源工具 Shiplist 发布:检查镜像和包内实际包含的文件

来源标题:Show HN: Shiplist – Know what files are in your images and packages

Shiplist 要求仓库中每个文件必须归入某个清单,并在构建各阶段前移除对应清单,CI 在文件未归入任何清单时报错。它还会检查 Docker 镜像、npm 包、gem、wheel、crate 等 tar 或 zip 包实际包含的文件。工具为小型静态 Rust 二进制,适用于 CI 流水线、Docker 构建和发布流程。

Hacker News 最新nathan_f772026/11/13 · 今天29 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

shiplist 把仓库里的每个文件都归入唯一一个清单,并在构建的各个阶段之前移除对应的清单。只要有文件没被列入任何清单,CI 就会失败,因此每个新增文件都必须明确决定是否要随包发布。随后它还会检查实际发布的内容:Docker 镜像、npm 包、gem、wheel、crate,或任何其他 tar 或 zip 文件。 $ shiplist check Files in no list (add each to exactly one list): config/partner_rates.yml 它是一个小巧的静态 Rust 二进制文件,适用于 CI 流水线、Docker 构建和发布工作流。当构建产物要离开你的掌控时,它最有价值:比如用于本地部署的镜像,或者任何人都能从 registry 下载的包。 .dockerignore 或 Dockerfile 里的 rm -rf 本质上是一份“要排除的文件”清单,所以任何新文件在有人把它加进清单之前都会默认被打包:一个带着测试密钥的安装脚本、一个内部笔记文件夹、一个新工具的配置。而测试是在完整仓库上运行的,所以即使镜像里缺少代码要读取的文件,测试也可能照样通过。 这些清单的工作方式类似复式记账:一个清单(通过 exclude)排除掉的文件,必须被另一个清单认领;而一个文件被两个清单同时认领则是错误。因此,新增或修改一个模式,绝不会悄悄地把文件移入或移出你的镜像:任何重叠都会让检查失败,由人来决定。 brew install docspring/tap/shiplist 使用 Cargo,从 crates.io 安装: cargo install shiplist --locked 在 GitHub Actions 中,这个 action 会按 tag 安装 release,并先校验二进制的构建来源:

  • uses: DocSpring/shiplist@v0.1.1
  • run: shiplist check 或者从 releases 下载适用于 Linux(x86_64 或 arm64,静态)或 macOS 的二进制文件。每个 release 都带有构建来源证明,可用 gh attestation verify <file> --repo DocSpring/shiplist 校验。 在仓库根目录放置 .shiplist.yml(或使用 --config <path>): version: 1 stages: [test, production] remove_before: test: include:
  • '.*' # dotfiles at the root
  • docs/
  • assets/ # compiled into public/ by the build
  • path: node_modules/ untracked: true # git never has it: no stale-pattern error, and prune deletes it exclude:
  • .shiplist.yml # the tests don't need it, but production removes it (see below) production: include:
  • .shiplist.yml
  • test/
  • bin/ exclude:
  • bin/server # the app runs it: claimed by keep keep: include:
  • app/
  • bin/server
  • Procfile

Files that must never be in a build, tracked or not. verify fails on any of them.

forbid:

  • '**/*.map'
  • '**/.env*'

Untracked files the build adds, which verify and prune --no-git allow

build_output:

  • public/ stages 按顺序列出各个阶段。一个文件在某个阶段之前被移除,那么在之后的所有阶段里它都不存在。每个阶段都需要一个 remove_before 清单。 当一个文件的路径匹配某个清单的某个 include 模式,且不匹配该清单的任何 exclude 模式时,这个文件就属于该清单。 keep 保存每个阶段都会保留的文件。 模式 模式始终相对于仓库根目录。 ** 必须是一个完整的路径组件。shiplist 会拒绝 .**/*,因为在许多 glob 库中它会静默地只匹配一层目录。它同样拒绝以 /、./ 或 ! 开头的模式:请把例外项放进清单的 exclude。 命令 作用 shiplist check 除非每个被跟踪的文件都恰好属于一个清单、每个模式都匹配到一个被跟踪的文件、且每个 exclude 都把它自己清单中的某个文件排除出去,否则失败。 shiplist list <stage> 打印在某个阶段仍然存在的被跟踪文件。--removed 打印在该阶段或之前被移除的文件。 shiplist explain <path>... 显示哪些模式匹配某个路径,以及它在每个阶段会经历什么。 shiplist prune <stage> 删除在该阶段或之前被移除的文件。如果某个目录下所有被跟踪的文件都被移除,该目录会连同其中的所有内容一起删除。 shiplist verify <stage> --dir <dir> 如果目录中存在该阶段不该有的文件、匹配 forbid 的文件,或者不属于任何清单且不在 build_output 中的文件,则失败。 shiplist verify <stage> --image <tar> --root /app 对用 docker save 保存的镜像做同样的检查,无需 Docker 即可读取。--root 指定仓库文件在镜像内的位置。 shiplist verify <stage> --archive <file> --root <dir> 对包或任何 tar、.tar.gz、zip 文件做同样的检查:npm 和 Python 源码包、.crate、Helm charts、wheels、.nupkg、.jar、.gem 和 Hex 包。--root 用于剥掉包把所有内容放进去的那层文件夹,比如 npm 的 package/。 check、list 和 prune 在 git 工作树的顶层运行,或者在某个自带 .shiplist.yml 的子目录中运行,比如 monorepo 里的某个包。它们绝不会把一个仓库的配置应用到它的某个子目录上。 check 和 verify 在发现问题时以 1 退出,所有命令在出错时(无效配置、未知阶段)以 2 退出。 prune 会删除文件,所以只有在 CI=true(或 CI=1)时才会运行,或者在没有任何未提交改动的工作树上加 --yes 运行。--dry-run 打印它将要删除的内容。--no-git 改为遍历目录而不是询问 git,适用于没有 .git 的目录树,比如 Dockerfile 的某个构建阶段。在没有 git 的情况下,每个文件都必须属于某个清单或匹配 build_output,否则不会删除任何东西。 $ shiplist explain bin/server bin/server remove_before.production: include bin/, but exclude bin/server keep: include bin/server => keep: kept at every stage 在 CI 中 每次 push 时检查配置,在测试前执行 prune,并在构建镜像前对一个干净的副本执行 prune:

GitHub Actions

  • run: shiplist check
  • run: shiplist prune test # GitHub Actions sets CI=true
  • run: bundle exec rspec

Build the image from a clean copy of the repository

git clone . build/src shiplist prune production --dir build/src rm -rf build/src/.git docker build -f Dockerfile build/ docker save my-app:latest -o my-app.tar shiplist verify production --image my-app.tar --root /app 在 Dockerfile 中,可以在某个构建阶段运行它: FROM my-app:latest AS pruned COPY shiplist /usr/local/bin/shiplist COPY .shiplist.yml /tmp/.shiplist.yml RUN CI=true shiplist --config /tmp/.shiplist.yml prune on-premise --dir /app --no-git 包

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →