打包
打包/GemspecGit
默认启用 | 安全 | 支持自动更正 | 版本添加 | 版本更改 |
---|---|---|---|---|
启用 |
是 |
否 |
0.1 |
0.1 |
避免使用 git ls-files
生成文件列表。下游通常需要在没有 git 的环境中构建您的包(有意为之)。相反,请使用一些纯 Ruby 替代方案,例如 Dir
或 Dir.glob
。
理由
Debian 中的包是在干净的环境中构建的(sbuild、schroot 等),在构建过程中,构建会失败,并出现以下错误:
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 替代方案,例如 Dir
或 Dir.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_relative
到 lib
目录会使这变得不可能,但它也会使测试看起来不像使用 gem 中代码的客户端代码。因此,我们建议测试代码使用主库代码,而无需 require_relative
。
因此,当使用相对路径时,最终会得到一个 LoadError
,指出
无法加载此文件 — /[PKGBUILDDIR]/foo
.
我们要强调的是,在 lib/
中使用 require_relative
没有任何问题,只是从你的测试代码到 lib
目录使用它会阻止“测试系统范围内安装的库”用例。
因此,仍然建议使用 require_relative
,只是对它有一个例外。