holger-rs/xtask/src/main.rs
//! `holger-logo` — the one picture on holger.rs's front page.
//!
//! ## What used to be here, and where it went
//!
//! This binary was `holger-ops`: the whole estate side of holger.rs — the
//! secrets file, the Cloudflare zone, the Proton Mail record set, the machine
//! spec and its emitters, and the step-by-step front plan. **All of that MOVED
//! to `private-holger-ops`**, where it sits beside the terraform declaration
//! that makes the machine, on the same pattern as `private-gunnar-ops`.
//!
//! It moved rather than being copied, and that was the point: two copies of a
//! DNS record set is how they disagree, and the grey-cloud decisions in that
//! one (`repo` and `grpc` stay grey forever) are the kind that cost an
//! afternoon each to learn.
//!
//! ## What stayed, and why
//!
//! The picture. It converts an asset that lives in THIS repository
//! (`.nornir/assets/holger-znippy-logo.png`) and writes into a directory in
//! this repository (`holger-front/assets/`), so it belongs where its files
//! are — an ops repository would have to reach across a checkout boundary to
//! run it, and the file it produced would be committed somewhere else than the
//! page that names it.
//!
//! Pure Rust, both halves: `image` decodes and resamples, `image-webp`
//! encodes. `cwebp` is not invoked and is not installed.
mod logo;
use std::path::PathBuf;
use std::process::ExitCode;
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
let refs: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
match run(&refs) {
Ok(out) => {
print!("{out}");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("\nREFUSED: {e}\n");
ExitCode::FAILURE
}
}
}
const USAGE: &str = "\
holger-logo — the picture on holger.rs's front page
logo [--from FILE] [--out FILE]
convert the owner's PNG to the WebP the front page carries.
Pure Rust; no cwebp, no libwebp FFI.
The estate — secrets, DNS, Proton Mail, the machine spec and the front plan —
moved to `private-holger-ops`. Run `cargo xtask` there.
";
fn run(args: &[&str]) -> Result<String, String> {
match args {
[] | ["help"] | ["-h"] | ["--help"] => Ok(USAGE.to_string()),
["logo", rest @ ..] => logo_verb(rest),
// The verbs that left are refused BY NAME and told where they went. An
// operator who types `dns plan` here had a plan; `unknown command`
// would send them looking for a regression that is not one.
[verb, ..]
if matches!(*verb, "dns" | "mail" | "estate" | "front" | "secrets-check" | "releases") =>
{
Err(format!(
"`{verb}` moved to `private-holger-ops` and is `cargo xtask {verb} …` there.\n \
The estate — the secrets file, the Cloudflare zone, the Proton record set, the\n \
machine spec and its emitters, and the front plan — lives beside the terraform\n \
that makes the machine. This binary keeps only the picture."
))
}
other => Err(format!("unknown command `{}`.\n{USAGE}", other.join(" "))),
}
}
fn flag<'a>(args: &'a [&'a str], name: &str) -> Option<&'a str> {
args.iter()
.position(|a| *a == name)
.and_then(|i| args.get(i + 1))
.copied()
}
fn logo_verb(args: &[&str]) -> Result<String, String> {
let from = flag(args, "--from").map(PathBuf::from).unwrap_or_else(|| {
// THE REPOSITORY'S OWN ASSET is the default, not a copy in a downloads
// folder: the picture the readme shows and the picture the front page
// carries are the same file, converted, and there is no second place to
// update.
repo_root().join(".nornir/assets/holger-znippy-logo.png")
});
let out = flag(args, "--out")
.map(PathBuf::from)
.unwrap_or_else(|| repo_root().join(logo::PUBLISHED));
let c = logo::convert(&from, &out)?;
Ok(format!(
" from {} {}x{} {} bytes\n to {} {}x{} {} bytes ({}%)\n\n \
lossless VP8L, encoded by image-webp — pure Rust, no cwebp and no libwebp FFI.\n",
c.source.display(),
c.source_dims.0,
c.source_dims.1,
c.source_bytes,
c.out.display(),
c.out_dims.0,
c.out_dims.1,
c.out_bytes,
(c.out_bytes * 100) / c.source_bytes.max(1),
))
}
/// The repository root, from this crate's own manifest directory. Not the
/// current directory: `cargo run` from anywhere must write the picture to the
/// same place.
pub fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.canonicalize()
.unwrap_or_else(|_| PathBuf::from("."))
}
#[cfg(test)]
mod tests {
use super::*;
/// ★ **The verbs that moved are refused BY NAME and say where they went.**
/// An operator who types `dns plan` in this repository had a plan; "unknown
/// command" would send them hunting for a regression that is not one.
#[test]
fn the_verbs_that_moved_say_where_they_went() {
for verb in [
"dns",
"mail",
"estate",
"front",
"secrets-check",
"releases",
] {
let e = run(&[verb, "plan"]).unwrap_err();
assert!(e.contains("private-holger-ops"), "`{verb}`: {e}");
assert!(
e.contains(verb),
"`{verb}` is not named in its own refusal: {e}"
);
}
}
/// The usage says what is left and where the rest is, so `--help` answers
/// the question somebody actually has.
#[test]
fn the_usage_names_the_one_verb_and_the_repository_that_has_the_others() {
assert!(USAGE.contains("logo"));
assert!(USAGE.contains("private-holger-ops"));
}
#[test]
fn an_unknown_command_is_refused_and_shows_the_usage() {
let e = run(&["logs"]).unwrap_err();
assert!(
e.contains("logs") && e.contains("private-holger-ops"),
"{e}"
);
}
}