xtask: drop the licences --check gate; THIRD-PARTY-LICENSES.txt is a release artifact

The file is no longer committed: dependency pull requests from forks failed CI only because
it was out of date. The Dependabot workflow that regenerated it is gone. licences now fails
when a shipped crate names no licence and carries no licence file.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 13:24:45 -04:00
1 parent 840b4b7dc5
commit 21072a23de
7 files changed
+27 -25

No files matched your search

+12 -14
View File
@@ -1,8 +1,8 @@
//! `cargo xtask licences [--check]`: THIRD-PARTY-LICENSES.txt, the licences of every crate built
//! into the shipped programs (fieldcraft, fieldcraft-cli, fieldcraft-web), read from
//! `cargo metadata` and the crates' own licence files, so a release download can carry them.
//! `--check` (part of `cargo xtask ci`) fails when the committed file is out of date, e.g. after a
//! dependency changed.
//! `cargo xtask licences`: THIRD-PARTY-LICENSES.txt, the licences of every crate built into the
//! shipped programs (fieldcraft, fieldcraft-cli, fieldcraft-web), read from `cargo metadata` and
//! the crates' own licence files. The release workflow generates it before packaging, so every
//! download carries it; it is not committed. Which licences are allowed is cargo-deny's
//! `[licenses]` policy (deny.toml), checked on every pull request.
use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::path::Path;
@@ -14,17 +14,9 @@ use crate::cargo;
pub const FILE: &str = "THIRD-PARTY-LICENSES.txt";
const ROOTS: &[&str] = &["fieldcraft", "fieldcraft-cli", "fieldcraft-web"];
pub fn run(root: &Path, check: bool) -> Result<(), String> {
pub fn run(root: &Path) -> Result<(), String> {
let text = generate()?;
let path = root.join(FILE);
if check {
let old = std::fs::read_to_string(&path).unwrap_or_default();
if old.replace("\r\n", "\n") != text {
return Err(format!("{FILE} is out of date (dependencies changed): run `cargo xtask licences` and commit it"));
}
println!("licences: {FILE} is up to date");
return Ok(());
}
std::fs::write(&path, &text).map_err(|e| format!("{}: {e}", path.display()))?;
println!("licences: wrote {FILE} ({} KB)", text.len() / 1024);
Ok(())
@@ -87,6 +79,12 @@ fn generate() -> Result<String, String> {
});
}
crates.sort_by(|a, b| (&a.name, &a.version).cmp(&(&b.name, &b.version)));
// A package must say what its licence is: a release never ships a crate it cannot account for.
let unresolved: Vec<String> =
crates.iter().filter(|c| c.license.is_empty() && c.files.is_empty()).map(|c| format!("{} {}", c.name, c.version)).collect();
if !unresolved.is_empty() {
return Err(format!("no licence (Cargo.toml `license` or a licence file) for: {}", unresolved.join(", ")));
}
Ok(render(&crates))
}
+4 -6
View File
@@ -27,9 +27,8 @@ commands:
app-icon draw the application icon family (assets/app-icon) with VectorCraft, then
write the iconset, icns, ico and Icon Composer document (macOS: sips,
iconutil, magick; actool for Assets.car when available)
licences [--check]
write THIRD-PARTY-LICENSES.txt (the licences of every shipped crate);
--check fails when it is out of date
licences write THIRD-PARTY-LICENSES.txt (the licences of every shipped crate; the
release workflow runs it before packaging, the file is not committed)
test [--heavy] [CARGO ARGS] [-- TEST ARGS]
build the tests with the ci profile, then run every test binary at once;
--heavy runs only the ignored tests instead (heavy verification and corpus
@@ -44,7 +43,7 @@ commands:
--bless freezes a passing case's results in its fixture.json; --quick skips
cases marked slow (release build)
wasm cargo check every library crate and the web app for wasm32-unknown-unknown
ci fmt --check, assets, licences --check, layers, clippy -D warnings, then the tests
ci fmt --check, assets, layers, clippy -D warnings, then the tests
(not the heavy ones) with the wasm check alongside (stops at the first failing
step)
";
@@ -57,7 +56,7 @@ fn main() -> ExitCode {
Some("assets") => assets::run(&root()),
Some("icons") => icons::run(&root(), &rest),
Some("app-icon") => app_icon::run(&root()),
Some("licences") => licences::run(&root(), rest.contains(&"--check")),
Some("licences") => licences::run(&root()),
Some("test") => {
let (heavy, rest) = match rest.split_first() {
Some((&"--heavy", after)) => (true, after),
@@ -200,7 +199,6 @@ fn cmd_ci() -> Result<(), String> {
c.args(["fmt", "--all", "--", "--check"]);
run(c, "cargo fmt --check")?;
assets::run(&root())?;
licences::run(&root(), true)?;
cmd_layers()?;
let mut c = cargo();
c.args(["clippy", "--workspace", "--all-targets", "--profile", "ci", "--", "-D", "warnings"]);