2 个版本

0.0.8 2023 年 9 月 15 日
0.0.0 2023 年 4 月 9 日

#1263 in 开发工具

Apache-2.0

160KB
4K SLoC

peckish

peckish(区分大小写)是一个用于重新打包 Linux 软件组件的工具。

例如,假设你是应用程序开发者。你刚刚开发了一款酷炫的应用,并希望分发它。然而,打包是 困难的。不同的包格式有不同的操作方式 - 例如,Arch 有 x86_64any 作为架构,而 Debian 有十多种,并将 "x86_64" 称为 "amd64" -- 而且很难记住所有这些细节。这还伴随着为每种包格式确定适当的 CLI 标志。有多少人能在第一次尝试时就写出一个 有效的 tar 命令? :P

这个问题相当普遍

至少在自托管的社区中,似乎越来越常见,提供两种安装方法:Docker 或 shell 脚本安装器。似乎许多新的项目甚至不使用本机包管理器,如 dpkg 或 rpm,这让我不愿意使用它们。

https://yotam.net/posts/the-audacity-of-piping-curl-to-bash/

从头开始编译 Linux 内核比从头开始构建 Debian 包要容易。

它非常复杂;最终它只是一个存档。我讨厌不得不这样做。

https://news.ycombinator.com/item?id=34787228

无需摩擦即可构建包的影响不容小觑。我为所有我的应用程序发布了 Arch Linux 包,因为编写 PKGBUILD 只需要几分钟。然后,有一次,我尝试提供 Debian 包,但尝试了几个小时后,我还是放弃了,因为工具的官僚主义太复杂了。

https://news.ycombinator.com/item?id=34923960

[...] 我过去也创建过自己的 RPM 和 DEB 包;但至少在我几年前做这件事时,它不如 arch 上的 PKGBUILD 有效。

https://news.ycombinator.com/item?id=35014171

官方文档是一个问题。它是面向构建符合完整策略的包,这些包可以被接受到官方仓库的Debian维护者。制作.deb包不需要任何这些垃圾。它会阻止人们为自己的程序或私人用途创建Debian包。

https://news.ycombinator.com/item?id=34788350

如果我的包管理器有Oh My Zsh包

这是作者没有抓住重点。为什么curl | bash如此常见,是因为开发者不喜欢为每个发行版打包,包括MacOS、FreeBSD,等等。如果你真的认为curl | bash是问题,那么你应该排队为你的发行版打包你使用的软件。相反,总是别人的问题。

包管理器对用户来说很棒……对其他人来说,一个多语言系统,带有晦涩的技术政策,以及更晦涩的人为政策……不是理想的选择。

https://news.ycombinator.com/item?id=33832401

peckish旨在解决这个问题。与其用各种晦涩的工具篡改你的文件,启动Docker容器或虚拟机来尝试构建软件包并确保它们可以安装或有效,以及其他所有痛苦,你只需编写一个基本的YAML文件,任务就完成了!peckish会完成剩下的工作,无需调用特定于发行版的工具!

此外,peckish使重新打包软件变得更加容易。你可以将DEB转换为RPM,或将Docker镜像转换为文件系统上的平面文件,或者将tar包转换为适用于基于DEB、RPM或Arch的发行版的可安装软件包。

peckish允许你在所有这些格式之间进行转换

  • 文件系统上的平面文件
  • tar包
  • 可安装的Debian软件包
  • 可安装的Arch Linux软件包
  • 可运行的Docker镜像
  • 可安装的RPM软件包
  • ext4文件系统镜像(wip)

peckish基于“工件”和“生产者”的概念。工件是你系统上存在的软件包的一些元数据,生产者是接受工件并产生新工件的东西。例如,从一个tar包生成DEB或RPM软件包。

功能

注意事项

  • peckish是0.x.y!请相应地对待。也许不要在生产环境中运行它。
  • 编写文档很困难,我不是最擅长这个。一些问题可能只能通过阅读源代码或打开一个问题来回答。报告缺失和/或损坏的文档有助于每个人!
  • peckish不是一个构建系统或包管理器。它不关心你的代码是如何构建或安装的,只关心将包从一种格式转换到另一种格式。
  • peckish不能保证文件被放置在包中的正确位置,只能保证包是有效的。例如,如果你将DEB转换为RPM,你需要确保RPM中的文件被安装到正确的位置。
  • peckish不能保证所有依赖项都正确地放入了包中。确保你的包是静态链接的,或者所有依赖项都包含在包中是你的责任。
  • peckish主要针对我的用例进行了测试。请请请请报告错误!
  • 使用饥渴模式生产的软件包很可能质量不足,无法被接受到发行版的官方仓库中。请不要浪费发行版维护者的时间,提交一大堆饥渴生成的软件包。

社区

饥渴是amyware discord服务器的一部分。

如果你喜欢我所做的,可以考虑在Patreon上支持我。

使用方法

在项目的根目录下创建一个peckish.yaml文件。

# whether to chain outputs, ie each artifact output is the input to the next
# producer. defaults to `false` if not specified.
chain: false

# metadata about the package. required, even if you're only producing a file or
# a tarball. this is because it's just easier than trying to play the "is there
# enough metadata to build the package" game.
metadata:
  name: "my-cool-pkg"
  # many distros want versions that end in -#, which is a revision number for
  # the package. this is required if you are producing an Arch/Deb/RPM/similar
  # package.
  version: "0.1.0-1"
  description: "a package"
  # suggested format: "me <[email protected]>"
  author: "me"
  # the architecture of the system the package is built for. this is usually
  # the same as the architecture of the system you're building on. will be
  # automatically set to the correct value for the target package format, ex.
  # x86_64 -> amd64 for debian.
  arch: "amd64"
  license: "Apache-2.0"

# the artifact being used as input to the pipeline.
input:
  name: "some file"
  type: "file"
  paths:
    - "./path/to/file"

# the producers being used as outputs. see `docs/` for more info about each
# producer.
output:
  - name: "tarball"
    type: "tarball"
    path: "./whatever.tar"

  - name: "debian package"
    type: "deb"
    path: "./whatever.deb"
    # a list of changes to inject into the filesystem. this lets you move,
    # copy, symlink, etc. files and directories within the artifact before it's
    # written to disk. see `docs/injections.md` for more info.
    injections:
      - "move-file"
      - "cleanup"

# the actual injections that are applied to output artifacts. these are
# specified in their own group to allow for reuse between multiple producers.
injections:
  move-file:
    type: "move"
    src: "/path/to/file"
    dest: "/new/path/to/file"
  cleanup:
    type: "delete"
    path: "/path"

建议使用场景

  • 轻松地将软件包打包到更多发行版中
  • 提取软件包,无需记住神秘的CLI标志
  • 无需Dockerfile即可创建Docker镜像
  • 创建一个可以在其他发行版上安装的软件包,无需手动重新打包
  • 使用Rust编程语言创建/操作软件包

crates.io: https://crates.io/crates/peckish

MSRV 1.71。

// artifacts
use peckish::prelude::builder::*;
use peckish::prelude::*;

let file_artifact = FileArtifactBuilder::new("example file artifact".into())
    .add_path("./examples/a".into())
    .build()?;

let tarball_producer = TarballProducerBuilder::new("example tarball producer".into())
    .path("test.tar.gz".into())
    .build()?;

let tarball_artifact = tarball_producer.produce(&file_artifact).await?;

// pipelines
use peckish::prelude::pipeline::*;
use peckish::prelude::*;

let file_artifact = ...;

let tarball_producer = ...;

let debian_producer = ...;

let config = PeckishConfig {
    input: ConfiguredArtifact::File(file_artifact),
    output: vec![
        ConfiguredProducer::Tarball(tarball_producer),
        ConfiguredProducer::Deb(debian_producer),
    ],
    chain: false,
};

let pipeline = Pipeline::new();
let out = pipeline.run(config).await?;
println!("produced {} artifacts", out.len());

GitHub Actions

peckish的GitHub Actions可以在queer/actions找到。

- name: "install peckish!"
  uses: "queer/actions/peckish_install@mistress"
  with:
    token: "${{ secrets.GITHUB_TOKEN }}"
- name: "run peckish!"
  uses: "queer/actions/peckish_run@mistress"

可重复构建

饥渴尝试尊重SOURCE_DATE_EPOCH。如果你发现它没有尊重的地方,请提出问题或PR。

路线图

软件包/工件格式

目标/希望是支持所有这些格式。未列出的格式可能会在未来出现在列表中。目前不支持但可能将来支持的格式也可能永远不支持。

  • 平面文件 "file"
  • 架构软件包 "arch"
  • 归档文件 "tarball"
  • Debian软件包 "deb"
  • Docker镜像 "docker"
  • RPM软件包 "rpm"
  • 文件系统和虚拟机镜像 "ext4"
    • 进行中
  • OCI镜像 "oci"
    • 进行中
  • appimage "appimage"
  • Flatpak?
    • 需要更多研究

其他

  • 透明处理压缩
  • [进行中] SOURCE_DATE_EPOCH 对可重复构建的支持
  • 更好的文档
  • 支持GitHub Actions以简化使用
  • 更好的错误消息
  • 或许有一天能达到1.0.0版本?

概念

饥渴围绕工件生产者的概念构建。

工件是你系统上存在的某些数据,可以被打包;工件本身不包含这些数据,只包含元数据。例如,一个FileArtifact是你系统上文件路径的列表。一个TarballArtifact是一个归档文件的路径。一个DebArtifact是一个.deb文件的路径。以此类推。

生产者更有趣。生产者实际上是进行打包的东西:它们以工件作为输入,并产生一个新的工件作为输出。例如,一个 TarballProducer 可能以 FileArtifact 作为输入,并产生一个 TarballArtifact 作为输出,一个 DebProducer 可能以 TarballArtifact 作为输入,并产生一个 DebArtifact 作为输出,等等。

饥渴的工件和生产者围绕着内存文件系统的概念。而不是在磁盘上扭曲东西,饥渴将所有东西都移动到内存中,对其进行操作,然后将它刷新回磁盘。这允许对软件工件进行简单的操作,因为更改它们只是在内存文件系统中注入一些更改,并在生产者中使用元数据重新打包。不需要了解除其内存文件系统表示之外的先前工件。

杂项

为什么叫饥渴的(peckish)?

如果你非常认真,"饥渴的"听起来有点像"package"。

  • floppy-disk:异步文件系统外观
  • disk-drive:多 floppy-disk 工具
  • flopfloppy-disk 归档外观
  • smoosh:自动魔法异步(重新)压缩
  • nyoom:为 floppy-disk 的文件系统遍历器
  • flail:为 ext4 的 floppy-disk 外观

许可证

版权 2023-至今 amy null

根据 Apache 许可证版本 2.0("许可证");除非您遵守许可证,否则不得使用此文件。您可以在以下位置获得许可证副本:

https://apache.ac.cn/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则在许可证下分发的软件按"原样"基础分发,不提供任何形式(明示或暗示)的保证或条件。有关许可证的具体语言,请参阅许可证。

依赖项

~67MB
~1M SLoC