跳到内容
GitHub 仓库 论坛 RSS-新闻订阅

Snapcraft 峰会蒙特利尔

Brian J. Cardiff

在 2019 年 6 月 11 日至 6 月 13 日期间举办的 Snapcraft 峰会蒙特利尔 上,来自不同开源项目的参与者齐聚一堂,以高效的方式进行迭代和协作,这在没有峰会的情况下需要花费更多的时间和资源。他们共同的目标是提高每个项目在 snapcraft.io 商店中的存在感。这次活动的亮点在于能够与不同项目的幕后人员会面,分享过去的经验和当前的想法。

每天,项目都取得了稳定的进展。一些项目并不陌生于这个平台,因此他们寻求改进和解决问题。其他项目则了解了隔离功能、商店得以实现的各个组件,并迈出了整合这些组件的第一步。每天结束时,都会对近 40 个项目进行大规模的状态检查,并在 forum.snapcraft.io 上发布总结。

在深入探讨 Crystal 本身的技术变更之前,我想提一下我与一些人进行了交流、分享想法和工作,这些交流、想法和工作无疑会对未来的提案产生影响。这些人包括来自 **rustup** 的 Daniel Silverstone、来自 **TravisCI** 的 Ana Rosas & María de Antón、来自 **Julia** 的 Alex Arslan & Jeff Bezanson、来自 **NixOS** 的 Graham Christensen 以及来自 **Snapcraft** 的 Sergio Schvezov。与他们的会面帮助我更好地了解了一些项目的各个方面、挑战和解决方案,这些方面、挑战和解决方案并非一目了然。我再怎么强调与他们会面的乐趣都不过分。

有什么新内容?

  1. Crystal 在 snapcraft.io/crystal 中拥有一个新的官方分发方式,适用于 10 个 Linux 发行版(并且还在不断增加…)
  2. Crystal 应用程序可以打包并作为 snap 进行分发。
  3. 现在,可以使用一种简单的方法安装 nightly 原生软件包。
  4. 当在 crystal: nightly 中指定时,TravisCI 将使用上述方法。

Crystal snap

您可以在全新的 snapcraft.io/crystal 页面中找到 snap 安装说明。

商店包含通道的概念,这有助于使用 *edge*、*beta*、*candidate* 和 *stable* 版本支持发布流程。

CI 脚本已更新,以便每天晚上将 *master* 的内容发布到 edge 通道。因此,nightly 版本现在可在此处获得,以及在 crystal-lang/crystal:nightly docker 镜像中,以及在构建本身的工件中。

在标记和发布新版本后,该软件包也将可用于 edge 通道,并且将手动移至 stable 通道。目前,预计不会使用 beta 和 candidate 通道,但将来可以使用它们的能力非常棒。

由于 Crystal snap 在 *classic* 隔离级别中运行(稍后将详细介绍),因此从 Ubuntu 软件包中的终端进行安装的命令为

$ sudo snap install crystal --classic        # For stable releases
$ sudo snap install crystal --edge --classic # For nightly releases

TravisCI 集成

Travis 需要处理大量内容来支持不同的语言和配置。考虑到即将发布的新版本,使用一种更加统一的方式来安装它们无疑会简化他们的工作量(人力和计算机资源)。

Travis 渴望通过 snap 开始为语言提供支持,而我们也渴望重新提供 nightly 版本。

从现在起,在 travis.yml 文件中使用 crystal: nightly 时,将使用 edge 通道中的 snap。在接下来的几个月里,crystal: latest 仍然会使用当前托管在我们软件包仓库中的 .deb 软件包。最终,将使用 stable 通道中的 snap。

一个额外的优势是,我们的软件包仓库将不会收到来自 CI 构建的流量。

将 Crystal 应用程序打包为 snap

一旦 snapcraft#2598 合并并发布(编辑:已在 Snapcraft 3.7 中发布!),构建一个将打包应用程序的 snap 将变得非常容易。如果您不熟悉 snapcraft,请不要错过 它的介绍

假设存在一个声明了目标、依赖项等的 shard.yml

name: hello

targets:
  hello:
    main: src/hello.cr

# ... stripped ...

一个用于声明所有部分的基本 snapcraft.yaml 文件如下所示

name: crystal-hello
version: "1.0"
description: Create the hello snap
summary: Create the hello snap

grade: devel
confinement: strict

apps:
  crystal-hello:
    command: bin/hello

parts:
  crystal-hello:
    plugin: crystal

安装生成的 snap 后,$ crystal-hello 将调用 ./bin/hello。当然,您可以调整名称并避免使用 crystal- 前缀。

构建 .snap 时,将发生以下操作

  1. 通过 $ shards install --production 安装依赖项。
  2. 通过 $ shards build --production 构建所有目标。
  3. ./bin 中的所有可执行文件打包到最终的 .snap 中。
  4. 打包运行这些二进制文件所需的所有链接库(通过 ldd 检测)。

如果应用程序需要一些默认情况下不可用的 C 库,则需要将它们列为 build-packages

如果您等不及,可以获取 PR 代码并将其用作 本地插件

Crystal snap 的一些技术细节

在开始开发 Crystal snap 时,我们试图使其在 *strict* 隔离级别中运行。使其在 strict 模式下运行的挑战是如何让主机和 snap 的库和工具链共存。

安装 snap 时,无法声明任何软件包依赖项(例如在 .deb 软件包中)。因此,需要默认包含所有库才能获得流畅的新体验。

一旦用于编译的程序变得更加高级,或者某个 shard 库链接到某个 C 库,用户将需要处理与如何找到这些库相关的打包方面的一些抽象泄漏。

这就是我们坚持使用 *classic* 隔离模式的主要原因。问题是如何让用户知道某些 Linux 发行版的原生软件包需要作为安装后步骤才能获得。

目前的解决方案 是,使用 snap 安装的 crystal 命令实际上是一个包装器,它会检查编译器是否可以成功用于简单的程序。如果在该检查中出现问题,则会显示一条有关所需软件包的消息。

在进行这项工作时,我们推动在 CircleCI 中对其 snap 支持 进行一些更新,他们的响应时间非常快。

版本管理

商店使用名为 channel 的概念。每个通道都提供单个版本。通道的完整名称为 <track>/<risk>/<branch>,其中默认 track 称为 *latest*。

如前所述,最新版本将可用于 latest/stable 通道,而 nightly 版本将可用于 latest/edge 通道。我们已经设置了 CI,以便能够根据需要提供一些 latest/edge/<feature-branch>

虽然 crystal 尚未达到 1.0,但这种方案已经足够了。您可以访问最新的稳定版本,*以及* 将来的版本。

就如何处理商店中对遵循 semver 的项目的显式版本可用性进行了一些讨论。一般共识是,为每个 Major.minor 版本创建一个 *track*,只在商店中保留最新的 Major.minor.patch。在这种方案中,一些项目可能会将 latest track 保持为空,以迫使用户做出明确的决定。我们最终会遵循哪种方案目前还没有定论。


感谢 Canonical、Travis CI 以及所有参与的人,为我们带来了一个很棒的星期!