Raises the platform floor to 27 and Swift 6.4. No API changes. If you are
still on OS 26 or Swift 6.3, stay on 1.0.x: SwiftPM does not consider
platforms when resolving versions, so a package whose deployment target is 26
and that depends on from: "1.0.0" will resolve to 1.1.0 and then fail to
build. Pin with .upToNextMinor(from: "1.0.6").
Also fixes three CI gates that could not fail on what they were added to catch
(see Fixed), and cleans up dead code, tools, and docs.
Changed
- The platform floor is now macOS / iOS / tvOS / watchOS 27 and Swift 6.4
(swift-tools-version: 6.4), following macOS 27 and Swift 6.4 going GA on
2026-09-15. ZPLKitVerifieris still unavailable on watchOS. The earlier stated reason
(Vision's Swift API needs watchOS 27) was incomplete: watchOS 27 has
DetectBarcodesRequestbut its SDK has noRecognizeTextRequestat all.- CI: the floor, cross-platform, and docs jobs moved from the hosted
macos-26/ Xcode 26.6 image to the hostedxcode-27image, pinned to
Xcode 27.0. visionOS joined the cross-platform build matrix. The Linux and
WebAssembly jobs moved to theswift:6.4containers and the 6.4.0 Wasm SDK
(both still run 184 tests). The test-output check that was copied into
three jobs now lives inScripts/check-test-output.sh. - CI: the per-module coverage gate moved from the hosted floor job to the
self-hostedbuild-and-testjob. GitHub's hosted macOS 27 VM cannot run
Vision text recognition (e5rt_e5_compiler_compile call failedon every
RecognizeTextRequest), so the hosted job setsZPLKIT_SKIP_VISION_OCR=1
to skip the two suites that need OCR. Every other environment, including a
plain localswift test, runs them.
Removed
- Dead conditional-compilation branches in Apple-only targets: the
non-Compressionfallback in the^GFparser and aGlibcimport in
ZPLKitPrinter, neither of which could ever compile.
Fixed
-
RenderFixturesexits non-zero when any fixture fails to render. -
DitherTestPrintdefaulted both printers to the same host, which also
skipped the pause between the two jobs. -
Docs: the
PrinterCommandexample called an API that does not exist;~JA
is now consistently described as cancelling all jobs;IntelligentMailis
listed under 1D barcodes in the DocC topics; CONTRIBUTING no longer describes
Xcode 27 beta bugs or a macOS test-count floor that no longer exist. -
The coverage gate could not fail on a module that vanished from the
report.Scripts/coverage.shlooped over the modules llvm-cov reported,
never over its own floor list, and 1.0.6 justified the gate on the premise
that a dropped test target takes its module's coverage toward zero. That
premise is wrong:ZPLKitPrinteris linked only byZPLKitPrinterTests, so
when that bundle stops running the module does not sink, it leaves the report
altogether. The script then printed "All modules at or above their coverage
floors" and exited 0. Since the test-count assertion had been relaxed to
"greater than zero" in the same release, a silently dropped
ZPLKitPrinterTestspassed every job. The gate now iterates the floor list,
and a module named there and missing from the report is a hard failure.
Verified by removing the builtZPLKitPrinterTestsbundle: previously green,
now fails. -
Module names no longer depend on llvm-cov's path shortening. The script
read the module from the first path component of the text report's filename
column, butllvm-cov reportstrips the longest common path prefix. Over the
whole suite the rows readZPLKit/Elements/Aztec.swift; over a single target
they readAztec.swift, every module became unrecognised, and the run passed
with nothing enforced. It now readsllvm-cov export -summary-only, whose
JSON carries absolute paths. Reported numbers are unchanged (86.77% line,
80.25% region). -
A failing test under WebAssembly now fails CI. The Wasm job treated any
non-zeroswift testexit as "this toolchain cannot host tests yet",
printed a notice and passed, including for a genuine test failure or a
runtime trap, which is the class of regression the step exists to catch. It
now degrades to a notice only when the test runner produced no output at all
(an SDK or link failure, which never reaches the runner) and fails the job
when tests ran and failed. -
A test-count step that found no count now says so. Under
pipefail, a
no-matchgrepin the counting pipeline aborted the step before its own
error message could print, so "nothing ran" failed the job with no
diagnostic.