This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 75cbbd782 ci: refresh Swift xlang cache by toolchain (#3811)
75cbbd782 is described below

commit 75cbbd782286888c108c6ef25f4a29bb62970d15
Author: Shawn Yang <[email protected]>
AuthorDate: Thu Jul 2 20:33:15 2026 +0530

    ci: refresh Swift xlang cache by toolchain (#3811)
    
    ## Why?
    
    Swift xlang CI can restore an exact primary SwiftPM cache but still
    rebuild SwiftSyntax and the release peer from scratch when the cached
    build artifacts were produced with a different Swift/Xcode toolchain or
    build shape. Because actions/cache does not save a replacement on a
    primary-key hit, that stale cache can remain ineffective across runs
    with no Swift source changes.
    
    ## What does this PR do?
    
    - Adds a Swift/Xcode toolchain fingerprint step before the Swift package
    cache restore.
    - Includes the toolchain fingerprint and xlang release build shape in
    the Swift cache key and restore prefix.
    - Keeps the existing package/source hash so real Swift input changes
    still get their own cache key.
    
    ## Verification
    
    - Did not run local tests per request.
    - Ran static whitespace check: `git diff --check`.
    - Remote CI: https://github.com/apache/fory/actions/runs/28591161385
    - Attempt 1 seeded Swift 6.1.2 / Xcode 16.4 cache: Swift prebuild 6m46s,
    total Swift Xlang job 7m55s.
    - Attempt 2 landed on Swift 6.3.2 / Xcode 26.5, missed by design due
    different toolchain key, saved a second cache: prebuild 9m13s, total
    10m57s.
    - Attempt 3 landed on Swift 6.3.2 / Xcode 26.5 again and hit the new
    key: restored 139,300,755 bytes, prebuild 1m51s, total 3m12s.
    - PR checks are passing or skipped by path filters.
---
 .github/workflows/ci.yml                           | 41 +++++++++++++++++++---
 .../apache/fory/idl_tests/IdlRoundTripTest.java    |  9 ++++-
 .../java/org/apache/fory/xlang/SwiftXlangTest.java | 17 +++++++--
 3 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9f07a6b14..d98bddbc1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -460,20 +460,36 @@ jobs:
           key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
             ${{ runner.os }}-maven-
+      - name: Compute Swift package cache key
+        id: swift-package-cache
+        run: |
+          {
+            swift --version
+            xcodebuild -version
+          } > "$RUNNER_TEMP/swift-toolchain.txt"
+          cat "$RUNNER_TEMP/swift-toolchain.txt"
+          echo "toolchain=$(shasum -a 256 "$RUNNER_TEMP/swift-toolchain.txt" | 
cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
       - name: Cache Swift package dependencies and build artifacts
+        id: swift-build-cache
         uses: actions/cache@v4
         with:
           path: |
             ~/.swiftpm
             ~/Library/Caches/org.swift.swiftpm
             swift/.build
-          key: ${{ runner.os }}-${{ runner.arch }}-swiftpm-${{ 
hashFiles('swift/Package.resolved', 'swift/Package.swift', 'swift/Sources/**') 
}}
+          key: ${{ runner.os }}-${{ runner.arch }}-swiftpm-xlang-release-${{ 
steps.swift-package-cache.outputs.toolchain }}-${{ 
hashFiles('swift/Package.resolved', 'swift/Package.swift', 'swift/Sources/**') 
}}
           restore-keys: |
-            ${{ runner.os }}-${{ runner.arch }}-swiftpm-
+            ${{ runner.os }}-${{ runner.arch }}-swiftpm-xlang-release-${{ 
steps.swift-package-cache.outputs.toolchain }}-
       - name: Prebuild Swift xlang peer for cache reuse
         run: |
           cd swift
+          if [[ "${{ steps.swift-build-cache.outputs.cache-hit }}" == "true" 
&& -x .build/release/ForyXlangTests ]]; then
+            echo "Using cached Swift xlang peer at 
swift/.build/release/ForyXlangTests"
+            echo "FORY_SWIFT_PEER_PREBUILT=1" >> "$GITHUB_ENV"
+            exit 0
+          fi
           swift build -c release --disable-automatic-resolution --product 
ForyXlangTests
+          echo "FORY_SWIFT_PEER_PREBUILT=1" >> "$GITHUB_ENV"
       - name: Run Swift Xlang Test
         env:
           ENABLE_FORY_DEBUG_OUTPUT: "1"
@@ -507,19 +523,36 @@ jobs:
             ${{ runner.os }}-maven-
       - name: Generate Swift IDL test code
         run: python ./integration_tests/idl_tests/generate_idl.py --lang swift
+      - name: Compute Swift IDL package cache key
+        id: swift-idl-package-cache
+        run: |
+          {
+            swift --version
+            xcodebuild -version
+          } > "$RUNNER_TEMP/swift-toolchain.txt"
+          cat "$RUNNER_TEMP/swift-toolchain.txt"
+          echo "toolchain=$(shasum -a 256 "$RUNNER_TEMP/swift-toolchain.txt" | 
cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
       - name: Cache Swift IDL package build artifacts
+        id: swift-idl-build-cache
         uses: actions/cache@v4
         with:
           path: |
             integration_tests/idl_tests/swift/idl_package/.build
             integration_tests/idl_tests/swift/idl_package/.swiftpm
-          key: ${{ runner.os }}-${{ runner.arch }}-swift-idl-package-${{ 
hashFiles('integration_tests/idl_tests/swift/idl_package/Package.swift', 
'integration_tests/idl_tests/swift/idl_package/Package.resolved', 
'swift/Package.swift', 'swift/Package.resolved', 'swift/Sources/ForyMacro/**') 
}}
+          key: ${{ runner.os }}-${{ runner.arch }}-swiftpm-idl-debug-${{ 
steps.swift-idl-package-cache.outputs.toolchain }}-${{ 
hashFiles('integration_tests/idl_tests/swift/idl_package/Package.swift', 
'integration_tests/idl_tests/swift/idl_package/Package.resolved', 
'integration_tests/idl_tests/swift/idl_package/Sources/**', 
'integration_tests/idl_tests/swift/idl_package/Tests/**', 
'swift/Package.swift', 'swift/Package.resolved', 'swift/Sources/**') }}
           restore-keys: |
-            ${{ runner.os }}-${{ runner.arch }}-swift-idl-package-
+            ${{ runner.os }}-${{ runner.arch }}-swiftpm-idl-debug-${{ 
steps.swift-idl-package-cache.outputs.toolchain }}-
       - name: Prebuild Swift IDL package
         run: |
           cd integration_tests/idl_tests/swift/idl_package
+          if [[ "${{ steps.swift-idl-build-cache.outputs.cache-hit }}" == 
"true" && -f .build/fory-swift-idl-prebuilt ]]; then
+            echo "Using cached Swift IDL package build artifacts"
+            echo "FORY_SWIFT_IDL_PREBUILT=1" >> "$GITHUB_ENV"
+            exit 0
+          fi
           swift build --disable-automatic-resolution --build-tests
+          touch .build/fory-swift-idl-prebuilt
+          echo "FORY_SWIFT_IDL_PREBUILT=1" >> "$GITHUB_ENV"
       - name: Run Swift IDL package tests
         env:
           ENABLE_FORY_DEBUG_OUTPUT: "1"
diff --git 
a/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
 
b/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
index 8f3beb681..b6b9123f0 100644
--- 
a/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
+++ 
b/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
@@ -117,6 +117,7 @@ import tree.TreeForyModule;
 import tree.TreeNode;
 
 public class IdlRoundTripTest {
+  private static final String SWIFT_IDL_PREBUILT_ENV = 
"FORY_SWIFT_IDL_PREBUILT";
 
   @Test
   public void testAddressBookRoundTripCompatible() throws Exception {
@@ -813,7 +814,13 @@ public class IdlRoundTripTest {
             compatible
                 ? "IdlRoundTripTests/testAddressBookRoundTripCompatible"
                 : "IdlRoundTripTests/testAddressBookRoundTripSchemaConsistent";
-        command = Arrays.asList("swift", "test", "--filter", swiftTest);
+        command = new ArrayList<>(Arrays.asList("swift", "test"));
+        if ("1".equals(System.getenv(SWIFT_IDL_PREBUILT_ENV))) {
+          // CI cache keys include generated Swift IDL sources, package 
inputs, and toolchain
+          // identity. Trust that explicit signal instead of letting SwiftPM 
rebuild after checkout.
+          command.add("--skip-build");
+        }
+        command.addAll(Arrays.asList("--filter", swiftTest));
         peerCommand.environment.put("ENABLE_FORY_DEBUG_OUTPUT", "1");
         break;
       case "javascript":
diff --git 
a/java/fory-core/src/test/java/org/apache/fory/xlang/SwiftXlangTest.java 
b/java/fory-core/src/test/java/org/apache/fory/xlang/SwiftXlangTest.java
index 15b1b9877..5f64af5a6 100644
--- a/java/fory-core/src/test/java/org/apache/fory/xlang/SwiftXlangTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/xlang/SwiftXlangTest.java
@@ -42,6 +42,7 @@ public class SwiftXlangTest extends XlangTestBase {
   private static final Logger LOG = 
LoggerFactory.getLogger(SwiftXlangTest.class);
   private static final String SWIFT_EXECUTABLE = "swift";
   private static final String SWIFT_PEER_TARGET = "ForyXlangTests";
+  private static final String SWIFT_PEER_PREBUILT_ENV = 
"FORY_SWIFT_PEER_PREBUILT";
   private static final File SWIFT_WORK_DIR = new File("../../swift");
   private static final Path SWIFT_WORK_DIR_PATH = SWIFT_WORK_DIR.toPath();
   private static final Path SWIFT_PEER_BINARY_PATH =
@@ -70,8 +71,16 @@ public class SwiftXlangTest extends XlangTestBase {
     }
     Assert.assertTrue(swiftInstalled, "swift is required for SwiftXlangTest");
 
+    if ("1".equals(System.getenv(SWIFT_PEER_PREBUILT_ENV))) {
+      // CI cache keys include Swift package inputs and toolchain identity. 
Trust that explicit
+      // signal instead of file mtimes because restored cache entries can 
predate checkout files.
+      usePeerBinary();
+      LOG.info("Completed ensurePeerReady for Swift xlang tests");
+      return;
+    }
+
     if (isPeerBinaryUpToDate()) {
-      swiftPeerBinaryPath = SWIFT_PEER_BINARY_PATH.toAbsolutePath().toString();
+      usePeerBinary();
       LOG.info("Completed ensurePeerReady for Swift xlang tests");
       return;
     }
@@ -103,6 +112,11 @@ public class SwiftXlangTest extends XlangTestBase {
     }
     Assert.assertTrue(built, "failed to build Swift xlang peer target " + 
SWIFT_PEER_TARGET);
 
+    usePeerBinary();
+    LOG.info("Completed ensurePeerReady for Swift xlang tests");
+  }
+
+  private void usePeerBinary() {
     Path peerBinary = SWIFT_PEER_BINARY_PATH;
     Assert.assertTrue(
         Files.isRegularFile(peerBinary),
@@ -111,7 +125,6 @@ public class SwiftXlangTest extends XlangTestBase {
         Files.isExecutable(peerBinary),
         "Swift xlang peer binary is not executable: " + 
peerBinary.toAbsolutePath());
     swiftPeerBinaryPath = peerBinary.toAbsolutePath().toString();
-    LOG.info("Completed ensurePeerReady for Swift xlang tests");
   }
 
   @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to