From 8debb6c420598e2eed77294cf4a32b5769409680 Mon Sep 17 00:00:00 2001 From: aiongg Date: Fri, 23 Oct 2026 20:10:26 +0000 Subject: [PATCH 1/4] xtask: the panic hunt without nextest builds with the HEIF decoder --- xtask/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 545bce9d23..0a90684252 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -231,8 +231,9 @@ fn cmd_gate_tests(panic_hunt: bool) -> Result<(), String> { c.args(["--run-ignored", "only", "-E", "binary_id(photocraft-engine::panic_hunt)"]); } } else if panic_hunt { - // `-- --ignored` across the workspace would run every ignored test, not only the hunt. - c.args(["test", "-p", "photocraft-engine", "--locked", "--test", "panic_hunt", "--", "--ignored"]); + // `-- --ignored` across the workspace would run every ignored test, not only the hunt. The + // engine has no `heif` feature of its own; it reaches the decoder through photocraft-io. + c.args(["test", "-p", "photocraft-engine", "--locked", "--features", "photocraft-io/heif", "--test", "panic_hunt", "--", "--ignored"]); } else { eprintln!("note: cargo-nextest is not installed, running cargo test (cargo install cargo-nextest --locked)"); c.arg("test").args(GATE_ARGS).args(&TEST_TARGETS[1..]); From 55219688281efabc02e23b8e4858aa2a4db2e8c2 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 23 Oct 2026 16:47:12 -0400 Subject: [PATCH 2/4] ci(sonar): don't cancel superseded runs on main, so coverage is published --- .github/workflows/sonarcloud.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index ecee45a6d8..e78fe1ea3b 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -11,7 +11,8 @@ permissions: concurrency: group: sonarcloud-${{ github.ref }} - cancel-in-progress: true + # A push to main is the run that publishes coverage; superseded runs there would never finish. + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: sonarcloud: From 6d4b9690ab4238308c5200b7632d01f56635213d Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 23 Oct 2026 17:06:29 -0400 Subject: [PATCH 3/4] deps: roxmltree 0.21 in photocraft-io and photocraft-engine (#8973) --- Cargo.lock | 4 ++-- crates/engine/Cargo.toml | 2 +- crates/io/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1df0af69ac..ce466ec9d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4837,7 +4837,7 @@ dependencies = [ "photocraft-text", "photocraft-vector", "rayon", - "roxmltree 0.20.0", + "roxmltree 0.21.1", "same-file", "serde", "serde_json", @@ -4928,7 +4928,7 @@ dependencies = [ "photocraft-vector", "proptest", "resvg", - "roxmltree 0.20.0", + "roxmltree 0.21.1", "serde_json", "thiserror 2.0.21", ] diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml index 2ccb98f81b..c0c412fa1d 100644 --- a/crates/engine/Cargo.toml +++ b/crates/engine/Cargo.toml @@ -38,7 +38,7 @@ craft-print = { workspace = true } # Photoshop `.kys` shortcut sets (`edit.keyboardShortcuts` `importKys`); already in the tree # through photocraft-ui-egui and usvg. -roxmltree = "0.20" +roxmltree = "0.21" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tempfile = "3" diff --git a/crates/io/Cargo.toml b/crates/io/Cargo.toml index 261c16481c..9b4ab1f416 100644 --- a/crates/io/Cargo.toml +++ b/crates/io/Cargo.toml @@ -39,7 +39,7 @@ blake3 = { version = "1.8", default-features = false, features = ["pure"] } # pdn.rs inflates Paint.NET's gzip pixel chunks. flate2 = { workspace = true } # ora.rs reads OpenRaster's stack.xml (already in the tree through usvg). -roxmltree = "0.20" +roxmltree = "0.21" # SVG import (svg.rs): usvg parses, resvg rasterises what the shape model can't hold. Both are # already in the tree through the UI's icon loader; text shaping needs the fonts feature set. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] From 4991f6377e871f54bdefb324cda0debb25606c54 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 23 Oct 2026 17:11:00 -0400 Subject: [PATCH 4/4] packaging(macos): retry stapling when Apple's ticket lookup drops (#8995) * packaging(macos): retry stapling when Apple's ticket lookup drops The 0.15.0 release's macOS job failed after both notarizations were accepted: stapling the DMG lost its connection to Apple's CloudKit ticket service (error 68). Retry stapling up to five times with a growing pause before failing the job. Co-Authored-By: Claude Opus 5.5 * packaging(macos): retry stapler validation too The re-run of the 0.15.0 macOS job stapled the DMG, then lost the CloudKit connection in `stapler validate` (error 68 again). Retry staple + validate as a pair in package.sh, and retry the validation verify.sh does. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- packaging/macos/package.sh | 24 ++++++++++++++++++++---- packaging/macos/verify.sh | 13 ++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/packaging/macos/package.sh b/packaging/macos/package.sh index 1b0974a340..b4be928efd 100755 --- a/packaging/macos/package.sh +++ b/packaging/macos/package.sh @@ -97,6 +97,24 @@ notarize() { fi } +# Stapling and validating both look the ticket up in Apple's CloudKit service. Right after +# notarization that lookup can drop the connection ("The network connection was lost", error 68) +# even though the ticket exists, so retry the pair a few times before failing the release. +staple() { + local file="$1" attempt + for attempt in 1 2 3 4 5; do + if xcrun stapler staple "$file" && xcrun stapler validate "$file"; then + return + fi + if [ "$attempt" = 5 ]; then + echo "error: stapling $(basename "$file") failed after $attempt attempts" >&2 + exit 1 + fi + echo "stapling $(basename "$file") failed (attempt $attempt); retrying in $((attempt * 20))s" >&2 + sleep $((attempt * 20)) + done +} + # ---- PhotoCraft.app ---------------------------------------------------------------------------- echo "==> assembling $APP" mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" @@ -123,8 +141,7 @@ codesign --verify --strict --deep --verbose=2 "$APP" if [[ "$NOTARIZE" = 1 ]]; then ditto -c -k --keepParent "$APP" "$WORK/PhotoCraft-notarize.zip" notarize "$WORK/PhotoCraft-notarize.zip" - xcrun stapler staple "$APP" - xcrun stapler validate "$APP" + staple "$APP" spctl --assess --type execute -vvv "$APP" fi @@ -149,8 +166,7 @@ sign "$DMG" codesign --verify --strict --verbose=2 "$DMG" if [[ "$NOTARIZE" = 1 ]]; then notarize "$DMG" - xcrun stapler staple "$DMG" - xcrun stapler validate "$DMG" + staple "$DMG" spctl --assess --type open --context context:primary-signature -vvv "$DMG" fi diff --git a/packaging/macos/verify.sh b/packaging/macos/verify.sh index 7521d44e03..46f779c2cf 100755 --- a/packaging/macos/verify.sh +++ b/packaging/macos/verify.sh @@ -70,6 +70,17 @@ assess() { return 1 } +# `stapler validate` asks Apple's CloudKit service too, which sometimes drops the connection +# (error 68) though the ticket is there. +validate_staple() { + local attempt + for attempt in 1 2 3 4 5; do + xcrun stapler validate "$1" && return 0 + [[ "$attempt" = 5 ]] || sleep $((attempt * 20)) + done + return 1 +} + for f in "$DMG" "$CLI_ZIP"; do if [[ ! -f "$f" ]]; then echo "error: missing $f" >&2 @@ -126,7 +137,7 @@ fi echo "==> $(basename "$DMG")" codesign --verify --strict --verbose=2 "$DMG" if [[ "$STRICT" = 1 ]]; then - xcrun stapler validate "$DMG" || fail "no notarization ticket stapled to the DMG" + validate_staple "$DMG" || fail "no notarization ticket stapled to the DMG" assess --assess --type open --context context:primary-signature -vv "$DMG" \ || fail "Gatekeeper rejects the DMG" fi