chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
An older run's pictures no longer overwrite the newest's
.changeset/check-images-older.mdnew+7−0
| @@ -0,0 +1,7 @@ | ||
--- | ||
default: patch | ||
--- | ||
| ||
# `knotless checks --images` keeps the newest run's pictures | ||
| ||
When the checks listed hold more than one run of a workflow, as a branch's reruns or a pull's heads do, an older run's picture no longer overwrites the newest's of the same name. The older one is saved beside it, named for its commit too: `look notifications-desktop-light 450b27ae11f7.webp`. | ||
crates/knotless/src/checks.rs+3−0
| @@ -285,6 +285,8 @@ fn scan_prefix(owner: &str, key: &str, filter: &Filter<'_>) -> String { | ||
pub struct Picture { | ||
/// The workflow whose check made it. | ||
pub workflow: String, | ||
/// The commit that check ran at, cut to 12 characters. | ||
pub commit: String, | ||
/// What it shows. | ||
pub alt: String, | ||
pub mime: String, | ||
| @@ -315,6 +317,7 @@ pub async fn pictures(ctx: &Ctx, checks: &[Check], most: usize) -> Vec<Picture> | ||
let bytes = theirs.ok()?.get_blob(&i.image.link.cid).await.ok()?; | ||
Some(Picture { | ||
workflow: c.record.workflow.clone(), | ||
commit: c.record.commit.chars().take(12).collect(), | ||
alt: i.alt.clone(), | ||
mime: i.image.mime_type.clone(), | ||
bytes, | ||
crates/knotless/src/cli.rs+15−3
| @@ -1326,13 +1326,25 @@ async fn command( | ||
let wait = std::time::Duration::from_secs(wait); | ||
let checks = crate::checks::wait(ctx, &url, filter, logs, wait).await?; | ||
// The pictures the checks made, as files to open, each named | ||
// for its workflow and what it shows. | ||
// for its workflow and what it shows. The checks come newest | ||
// first, so the newest run keeps a picture's name; an older | ||
// run's of the same name is named for its commit too, and one | ||
// older still at that commit is left out, never written over | ||
// the newer. | ||
let mut saved = Vec::new(); | ||
if let Some(dir) = images { | ||
std::fs::create_dir_all(&dir)?; | ||
for p in crate::checks::pictures(ctx, &checks, usize::MAX).await { | ||
let mut taken = std::collections::HashSet::new(); | ||
let pictures = crate::checks::pictures(ctx, &checks, usize::MAX).await; | ||
let named = pictures.iter().filter_map(|p| { | ||
let ext = p.mime.strip_prefix("image/").unwrap_or("bin"); | ||
let name = format!("{} {}.{ext}", p.workflow, p.alt).replace('/', "-"); | ||
let plain = format!("{} {}", p.workflow, p.alt); | ||
let names = [plain.clone(), format!("{plain} {}", p.commit)]; | ||
let names = names.map(|n| format!("{n}.{ext}").replace('/', "-")); | ||
let name = names.into_iter().find(|n| taken.insert(n.clone())); | ||
name.map(|name| (name, p)) | ||
}); | ||
for (name, p) in named { | ||
std::fs::write(dir.join(&name), &p.bytes)?; | ||
saved.push(dir.join(name)); | ||
} | ||
crates/knotless-run/tests/run.rs+6−1
| @@ -4209,9 +4209,14 @@ fn a_private_repository_runs_in_its_space() { | ||
let (code, out) = owner.cli(&["checks", &url, "--log", "--images", dir], b""); | ||
assert_eq!(code, 0, "{out}"); | ||
assert!(out.contains("==> break\nbroken\n"), "{out}"); | ||
// Of both runs: the commit that made it, as found, and the push. | ||
// Of both runs: the commit that made it, as found, and the push, each | ||
// a file of its own, the older's named for its commit too. | ||
let shown = out.lines().filter(|l| l.starts_with("image\t")).count(); | ||
assert_eq!(shown, 64, "{out}"); | ||
assert_eq!(std::fs::read_dir(&saved).unwrap().count(), 64); | ||
let found = checks[1]["commit"].as_str().unwrap(); | ||
let older = format!("{dir}/fail page 00 {}.png", &found[..12]); | ||
assert!(out.contains(&format!("image\t{older}\n")), "{out}"); | ||
| ||
// Nothing of it is in the runner's public repo. | ||
let public = reqwest::blocking::get(format!( | ||
docs/reference/cli.md+4−1
| @@ -213,7 +213,10 @@ queue](../design/merge-queue.md). | ||
or the ref, the commit's first 12 characters, `startedAt` and any | ||
`skipped` note, tab-separated. `--log` follows it with the log, and | ||
`--images` ends the list with an `image` line per picture saved, then a | ||
tab and its path, named `<workflow> <alt>.<ext>` with `/` as `-`. | ||
tab and its path, named `<workflow> <alt>.<ext>` with `/` as `-`. The | ||
newest run keeps that name; an older run's picture of the same name is | ||
`<workflow> <alt> <commit>.<ext>`, the commit's first 12 characters, and | ||
one older still at that commit is not saved, so none is written over. | ||
`--queue` takes a bare branch name. `--commit` takes a commit's hex ID or | ||
at least its first 4 digits, as `git log --oneline` prints them, in either | ||
case; anything else fails with `a commit is its hex ID, or at least its | ||