打包

打包/BundlerSetupInTests

默认启用 安全 支持自动更正 版本添加 版本更改

启用

0.4

0.5

此 Cop 会标记从测试目录内部进行的 require "bundler/setup" 调用。

示例

# bad
require "foo"
require "bundler/setup"

# good
require "foo"

打包/GemspecGit

默认启用 安全 支持自动更正 版本添加 版本更改

启用

0.1

0.1

避免使用 git ls-files 生成文件列表。下游通常需要在没有 git 的环境中构建您的包(有意为之)。相反,请使用一些纯 Ruby 替代方案,例如 DirDir.glob

理由

Debian 中的包是在干净的环境中构建的(sbuildschroot 等),在构建过程中,构建会失败,并出现以下错误:
Invalid gemspec in [<gem_name>.gemspec]: No such file or directory - git

为每个 Ruby 包添加 git 作为依赖项是不正确的,也不推荐这样做。此外,源包由发布的 tarball 组成(通常从 GitHub/GitLab 发布页面下载或从 .gem 文件转换而来,使用 gem fetch foo 获取),这些 tarball 在构建过程中被解压缩。因此,即使我们将 git 添加为构建依赖项,它仍然会失败,因为 Debian 包源树 **不是 git 仓库**。即使包在 git 中维护,它也会作为 tarball 上传到存档,没有任何版本控制信息。

因此,这里唯一的解决方法是修补掉 git 的使用,并在进行 Debian 维护时使用一些简单的 Ruby 替代方案,例如 DirDir.glob,甚至 Rake::FileList

不仅是 Debian 或其他操作系统打包的情况/示例,还有其他一些情况,例如

  • ruby-core 在其 CI 系统中运行其测试套件,针对未打包的 Ruby 压缩包,该压缩包没有 .git 目录。这意味着他们需要覆盖 bundler gemspec 以不使用 git。
    实际上,现在已经不再需要了,因为 git 已经从 bundler 的 gemspec 中删除了.

  • 如果您在没有 git 的裸 Docker 镜像上构建应用程序,并且您指向一个使用 git 的 gemspec 的 git 源代码 gem,您将收到以下警告:No such file or directory - git ls-files (Errno::ENOENT)。例如,如果您在 Gemfile 中使用以下代码
    gem "foo", git: "https://github.com/has-git-in-gemspec/foo"

最初,默认 gemspec 模板中的 git ls-files 是为了让发布第一个 gem 的用户不会无意中将工件发布到其中。最近版本的 bundler 不会让您在工作目录中有未提交的文件时发布,因此这种风险较低。

示例

# bad
Gem::Specification.new do |spec|
  spec.files         = `git ls-files`.split("\n")
  spec.test_files    = `git ls-files -- spec`.split("\n")
end

# good
Gem::Specification.new do |spec|
  spec.files         = Dir["lib/**/*", "LICENSE", "README.md"]
  spec.test_files    = Dir["spec/**/*"]
end

# bad
Gem::Specification.new do |spec|
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
    `git ls-files -z`.split("\\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
  end
end

# good
require "rake/file_list"

Gem::Specification.new do |spec|
  spec.files         = Rake::FileList["**/*"].exclude(*File.read(".gitignore").split)
end

# bad
Gem::Specification.new do |spec|
  spec.files         = `git ls-files -- lib/`.split("\n")
  spec.test_files    = `git ls-files -- test/{functional,unit}/*`.split("\n")
  spec.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
end

# good
Gem::Specification.new do |spec|
  spec.files         = Dir.glob("lib/**/*")
  spec.test_files    = Dir.glob("test/{functional,test}/*")
  spec.executables   = Dir.glob("bin/*").map{ |f| File.basename(f) }
end

打包/RequireHardcodingLib

默认启用 安全 支持自动更正 版本添加 版本更改

启用

0.4

0.5

此 cop 会标记 require 调用,这些调用来自映射到 "lib" 目录的任何位置,但源自 lib/ 的除外。

示例

# bad
require "../lib/foo/bar"

# good
require "foo/bar"

# bad
require File.expand_path("../../lib/foo", __FILE__)

# good
require "foo"

# bad
require File.expand_path("../../../lib/foo/bar/baz/qux", __dir__)

# good
require "foo/bar/baz/qux"

# bad
require File.dirname(__FILE__) + "/../../lib/baz/qux"

# good
require "baz/qux"

打包/RequireRelativeHardcodingLib

默认启用 安全 支持自动更正 版本添加 版本更改

启用

0.2

0.5

避免使用 require_relative 与 lib 的相对路径。请改用 require

理由

Debian 拥有一个 测试基础设施,该基础设施旨在测试已安装形式的软件包,即更接近最终用户使用的方式,而不是开发人员针对其工作的方式。为了使这能够正常工作,测试套件必须加载系统范围内安装的代码,而不是源代码树中的代码。从测试中使用 require_relativelib 目录会使这变得不可能,但它也会使测试看起来不像使用 gem 中代码的客户端代码。因此,我们建议测试代码使用主库代码,而无需 require_relative

因此,当使用相对路径时,最终会得到一个 LoadError,指出
无法加载此文件 — /[PKGBUILDDIR]/foo.

我们要强调的是,在 lib/ 中使用 require_relative 没有任何问题,只是从你的测试代码到 lib 目录使用它会阻止“测试系统范围内安装的库”用例。

因此,仍然建议使用 require_relative,只是对它有一个例外。

示例

# bad
require_relative "lib/foo"

# good
require "foo"

# bad
require_relative "../../lib/foo/bar"

# good
require "foo/bar"

# good
require_relative "foo/bar/bax"
require_relative "baz/qux"