Skip to content

Swift 6.4 / Xcode 27 に移行する - #48

Merged
temoki merged 6 commits into
mainfrom
swift-6.4
Sep 19, 2026
Merged

temoki merged 6 commits into
mainfrom
swift-6.4

Conversation

@temoki

@temoki temoki commented Sep 14, 2026 •

Copy link
Copy Markdown
Owner

Note

マージは保留中です。 Xcode 27 が正式にリリースされ、GitHub の macOS ランナーにも正式版が入ってから、CI を回し直して再確認します(#49 の検証もそのときに行います)。 Xcode 27 RC版が macOS Runnerに入った。

概要

Xcode 27(Swift 6.4)への移行です。swift-tools-version を 6.4 に上げ、CI も Xcode 27 に移します。

ライブラリのソースコードは変えていません。 Xcode 27 RC(Swift 6.4)で、警告もエラーもなくビルドできました。変えたのは、CI を Xcode 27 ランナー(macOS 27)で動かすためのテストと CI 設定です(下の「CI を通すための修正」を参照)。

利用者への影響

  • 動作要件が Swift 6.4+ / Xcode 27+ に上がります(これまでは Swift 6.2+ / Xcode 26+)。
  • 対応 OS(iOS 26+ · macOS 26+ · visionOS 26+ · Linux)は変わりません。
  • CHANGELOG の見出しは Unreleased のままです。次のバージョン番号はリリース時に決めます。

変更内容

ファイル 変更
Package.swift swift-tools-version: 6.2 → 6.4
ci.yml / docs.yml macOS のジョブを macos-15 → xcode-27 ランナーへ
select-xcode/action.yml 既定のメジャーバージョンを 26 → 27
ci.yml(linux) swift:6.2 → swiftlang/swift:nightly-6.4.x-noble
ci.yml(カバレッジ) テスト対象ごとの .xctest をすべて llvm-cov に渡す
CanvasGoldenSnapshotting.swift(新規) Canvas の PNG ゴールデンの比較方法を .canvasGolden として 1 か所に定義
README / CONTRIBUTING / CHANGELOG / CLAUDE.md / bug_report 動作要件と比較方法の記述を更新

CI を通すための修正

1. PNG ゴールデンの比較で、テストプロセスごとクラッシュする

TortoiseUITests が -[NSConcreteValue CGRectValue]: unrecognized selector で異常終了していました。

  • 原因:swift-snapshot-testing(最新の 1.19.4、main でも未修正)の知覚差分の比較が、CIAreaAverage の inputExtent に CIVector ではなく CGRect をそのまま渡しています。macOS 26 までの Core Image はこれを受け付けましたが、macOS 27 では例外になります。
  • macOS 26 で気づかなかった理由:この比較はバイト列が一致しなかったときにしか実行されません。ゴールデンを記録した macOS 26 ではピクセルが完全に一致するため、この処理まで進みません。
  • 対処:perceptualPrecision: 0.98 をやめ、バイト単位の比較(precision: 0.995)にしました。許容誤差は、ずれてよいバイトが 0.5% までです。上流のフォークをブランチ指定で依存に入れる方法は、このパッケージをバージョン指定で使う利用者の依存解決を壊すので採りませんでした。

2. カバレッジの出力で失敗する

Xcode 27 の SwiftPM は、テスト対象ごとに .xctest バンドル(TortoiseCoreTests / TortoiseSVGTests / TortoiseUITests)を作ります。以前の単一の TortoiseGraphicsPackageTests.xctest がなくなったので、全バンドルを -object で llvm-cov に渡すようにしました。ローカルで出力した lcov に、3 モジュールすべてのソースが含まれることを確認しています。

残っている注意点

  • Linux ジョブ:公式の swift:6.4 イメージが Docker Hub にまだないので、それまで 6.4 リリースブランチのナイトリーを使います。公式イメージが出たら差し替えます(TODO コメントあり)。
  • Xcode の選択:xcode-27 ランナーに入っているのは現在 Xcode 27 beta 6 です。CI では Xcode_27.0.0.app(beta 6 へのシンボリックリンク)が選ばれています。
  • 上流への報告:swift-snapshot-testing の不具合は、まず macOS 27 で swift-snapshot-testing の知覚差分比較が CGRectValue 例外でテストプロセスごとクラッシュする #49 に記録しました。再現したのは macOS 27 と Xcode 27 のベータ版なので、正式版で再発するかを確かめてから上流に報告するかを決めます。

確認

  • ローカル(Xcode 27 RC / macOS 26):swift test 全件パス、swift build -c release、swift-format lint --strict
  • ローカル:新しいカバレッジ出力のコマンドで lcov を出力(3 モジュール分)
  • CI(xcode-27 ランナー / macOS 27):Build & Test・Release Build・Linux・swift-format lint すべて成功

Bump swift-tools-version to 6.4 and move CI to the xcode-27 runner image.
The Linux job uses the 6.4 release-branch nightly until the official
swift:6.4 image is published. No source changes were needed: the package
builds without warnings and passes all tests under Swift 6.4.
swift-snapshot-testing's perceptual comparison passes a bare CGRect as
CIAreaAverage's inputExtent, which Core Image on macOS 27 rejects with an
uncaught -[NSConcreteValue CGRectValue] exception, killing the whole
TortoiseUITests process on the xcode-27 runner. Byte-wise comparison with
the same 0.995 precision never enters that path.
SwiftPM in Xcode 27 builds one .xctest bundle per test target instead of a
single TortoiseGraphicsPackageTests.xctest, so the lcov export failed with
"No such file or directory" after all tests had passed. Pass each bundle's
binary to llvm-cov with -object.
@codecov

codecov Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.76%. Comparing base (83941fe) to head (5ee64b6).

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #48   +/-   ##
=======================================
  Coverage   93.76%   93.76%           
=======================================
  Files          16       16           
  Lines         946      946           
=======================================
  Hits          887      887           
  Misses         59       59           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@temoki

temoki commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

The 6.4 release-branch nightly was a stand-in until Docker Hub published
swift:6.4, which it now has.
@temoki
temoki merged commit 72e31e1 into main Sep 19, 2026
6 checks passed
@temoki
temoki deleted the swift-6.4 branch September 19, 2026 02:24
temoki added a commit that referenced this pull request Sep 21, 2026
swift-snapshot-testing 1.19.6 fixes the crash that forced byte-wise comparison
in #48: the perceptual path passed a bare CGRect as CIAreaAverage's inputExtent,
which Core Image on macOS 27 rejected with an uncaught -[NSConcreteValue
CGRectValue] exception, killing the whole test process
(pointfreeco/swift-snapshot-testing#1120).

Floor the dependency at 1.19.6 rather than leaving it at 1.18.0. The perceptual
path is only reached when bytes differ, so an older resolution would keep
passing locally and crash wherever antialiasing drifts.

Verified on macOS 27.0 (26A428) / Xcode 27.0 (27A266a) — the combination that
crashed — by passing two deliberately different renders through
Snapshotting.canvasGolden.diffing.diff, which now reports a difference instead
of taking down the process. A green suite alone would not have shown this: the
goldens match byte for byte on the machine that recorded them, so the perceptual
path never runs.

The goldens themselves are unchanged; perceptual comparison is strictly more
permissive than the byte-wise one they were recorded against.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant