我试图让 Cargo 在 CI 上出现警告时失败,但在本地开发时不会失败。
我有一个可行的解决方案,即在 CI 作业中设置
RUSTFLAGS=“-D warnings”
。这很有效,因为它确实会使本地板条箱的构建失败,但不会导致依赖项板条箱的构建失败(由于—cap-lints
)。
最近,必须在(签入)
.cargo/config
文件中设置一些 rustflags:
[target.’cfg(target_os = “linux”)’]
rustflags = [“some”, “options”]
这不起作用,因为
RUSTFLAGS
优先并且 .cargo/config
标志将被忽略。我不想将 -D warnings
添加到 config
,因为这在开发时可能会很痛苦。
当前的解决方法是在 CI 作业之前调整
config
的脚本:
sed -i "s:\(rustflags = .*\)]:\1, \"-D\", \"warnings\"]:g" .cargo/config
echo '[build]' >> .cargo/config
echo 'rustflags = [ "-D", "warnings"]' >> .cargo/config
这会将
-D warnings
附加到配置中现有的 rustflags
,并且 创建一个额外的包罗万象的 config
条目,以确保 -D warnings
在非 Linux CI 构建上也启用。
这太hacky了;我缺少更好的解决方案吗?
也许这应该是 Cargo 存储库上的一个功能请求,但我不知道理想的解决方案是什么样的。
built::util::detect_ci()
来确定当前构建是否在 CI 下执行。然后您可以使用一个小的构建脚本来设置 cfg
Cargo.toml
[package]
build = true
[build-dependencies]
built = { version = "0.3", default_features = false }
build.rs
fn main() {
if let Some(ci) = built::util::detect_ci() {
// There may be a better way to do this
println!("cargo:rustc-cfg=DENY_WARNINGS");
println!("cargo:warning=Denying warnings because we are in CI \"{}\"", ci);
}
}
请注意,构建脚本的结果被缓存,因此一旦此构建脚本运行并且 Cargo 决定我们是否在 CI 下运行,它将遵循此结果,直到您修改构建脚本或
cargo clean
。这对于本地开发或 CI 来说都不是问题,除非 Scotty 定期向您发送信息。
main.rs 或 lib.rs
#![cfg_attr(DENY_WARNINGS, deny(warnings))]
fn main() {
// This will be a warning locally but fail to compile e.g. if built on Travis
Result::<(), ()>::Err(());
}
使用环境变量覆盖:
CARGO_BUILD_RUSTFLAGS='-D warnings' cargo check
如果您对其工作原理感兴趣,请使用:https://doc.rust-lang.org/cargo/reference/config.html#environment-variables(简而言之,此类环境变量名称是通用的,不仅仅是这个变量名有任何作用)。
如果您在没有环境变量的情况下运行
cargo check
,即使存在编译警告,它也会继续编译。
作为替代解决方案,为了区分“CI严格模式”和“本地宽松模式”,您可以简单地在CI中使用
clippy
,在本地使用cargo check
。 clippy
可以轻松配置为“严格”,如果出现警告则失败。它也是确保整个项目统一良好代码质量的好工具。