Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,70 @@ jobs:
github.ref_name == 'main'
run: |
docker compose push ubuntu

ios:
name: iOS
runs-on: macos-15
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "stable"
- name: Generate test data
run: |
cd data-generator/swift-datagen
go run .
cp *.arrow ../../Tests/ArrowTests/
- name: Select iOS Simulator
run: |
# Pick the first iPhone on the newest available iOS.
#
# Example pipeline on macos-15 runner
#
# xcrun simctl list devices available (filtered to iPhone):
# -- iOS 18.5 --
# iPhone 16 Pro (E8B81AE5-...) (Shutdown)
# iPhone 16 (394B9336-...) (Shutdown)
# -- iOS 18.6 --
# iPhone 16 Pro (37C8BF13-...) (Shutdown)
# iPhone 16 (E040B4E8-...) (Shutdown)
# -- iOS 26.2 --
# iPhone 17 Pro (20A8DB5D-...) (Shutdown)
# iPhone 16 (02BBE218-...) (Shutdown)
#
# -> awk: prefix each iPhone line with its iOS version
# 18.5 iPhone 16 Pro (E8B81AE5-...) (Shutdown)
# 18.5 iPhone 16 (394B9336-...) (Shutdown)
# 18.6 iPhone 16 Pro (37C8BF13-...) (Shutdown)
# 26.2 iPhone 17 Pro (20A8DB5D-...) (Shutdown)
# 26.2 iPhone 16 (02BBE218-...) (Shutdown)
#
# -> sort -t. -k1,1nr -k2,2nr: sort by iOS version descending
# 26.2 iPhone 17 Pro (20A8DB5D-...) (Shutdown)
# 26.2 iPhone 16 (02BBE218-...) (Shutdown)
# 18.6 iPhone 16 Pro (37C8BF13-...) (Shutdown)
# 18.5 iPhone 16 Pro (E8B81AE5-...) (Shutdown)
#
# -> head -1: take the first line (newest iOS)
# 26.2 iPhone 17 Pro (20A8DB5D-...) (Shutdown)
#
# -> grep -oE: extract the simulator UDID
# 20A8DB5D-3B2A-48CF-BA79-07E054563A31
SIMULATOR_ID=$(xcrun simctl list devices available 2>/dev/null | \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment that shows example output of xcrun ... and each filter something like the following?

# Example:
#   (xcrun ... output)
#   ->
#   (awk ... output)
#   -> 
#   (sort ... output)
#   -> 
#   (head -1 output)
#   ->
#   (grep ... output)

It'll help us when the command line doesn't work as expected.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a example from real macos-15 runner output.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also add real device run it would would mostly fail on real device

awk '/-- iOS/{os=$3} /iPhone/{print os, $0}' | \
sort -t. -k1,1nr -k2,2nr | head -1 | \
grep -oE '[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}')
if [ -z "$SIMULATOR_ID" ]; then
echo "Error: no iPhone simulator found"
xcrun simctl list devices available
exit 1
fi
echo "SIMULATOR_ID=$SIMULATOR_ID" >> "$GITHUB_ENV"
echo "Selected simulator: $SIMULATOR_ID"
- name: Test on iOS Simulator
run: |
xcodebuild test \
-scheme Arrow-Package \
-destination "platform=iOS Simulator,id=$SIMULATOR_ID" \
-only-testing ArrowTests
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new iOS CI job only runs xcodebuild test with -only-testing ArrowTests, which won’t compile (or run) ArrowFlightTests and may not even build the ArrowFlight target. This leaves a gap where the package can be declared iOS-supported but still regress for ArrowFlight on iOS without CI catching it. Consider adding an additional xcodebuild build step for the ArrowFlight scheme (or otherwise ensuring all package products compile) on the selected simulator destination.

Suggested change
-only-testing ArrowTests
-only-testing ArrowTests
- name: Build ArrowFlight for iOS Simulator
run: |
xcodebuild build \
-scheme ArrowFlight \
-destination "platform=iOS Simulator,id=$SIMULATOR_ID"

Copilot uses AI. Check for mistakes.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ xcuserdata/
# Release
/apache-arrow-swift-*.tar.gz*
/dev/release/.env

# Generated test data (intermediate output from Go generator)
/data-generator/swift-datagen/*.arrow
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import PackageDescription
let package = Package(
name: "Arrow",
platforms: [
.macOS(.v10_15)
.macOS(.v10_15),
.iOS(.v15)
],
Comment on lines 23 to 28
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declaring .iOS(.v15) at the package level makes it easy for consumers to expect both Arrow and ArrowFlight to be usable on iOS. Right now the iOS CI job only exercises ArrowTests, so it’s possible for ArrowFlight to drift out of iOS compatibility unnoticed. Consider either (a) expanding iOS CI to compile/build the ArrowFlight product too, or (b) explicitly documenting that iOS support applies only to the core Arrow library if that’s the intent.

Copilot uses AI. Check for mistakes.
products: [
.library(
Expand Down Expand Up @@ -70,6 +71,11 @@ let package = Package(
.testTarget(
name: "ArrowTests",
dependencies: ["Arrow", "ArrowC"],
resources: [
.copy("testdata_bool.arrow"),
.copy("testdata_double.arrow"),
.copy("testdata_struct.arrow")
Comment on lines +75 to +77
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we copy them from ../../data-genrator/swift-datagen/?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately SwiftPM's .copy() only accepts paths within the target's source directory, so referencing ../../data-generator/swift-datagen/ isn't possible. Instead I've committed the three generated .arrow files directly (they're small -- 650 to 810 bytes). This ensures the package resolves cleanly without needing to run the Go generator first. The CI still regenerates them, so if the generator changes, any drift will be caught.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. But we don't want to add auto generated files into this repository.
Let's copy to Tests/ArrowTests/ manually (or by script) instead of adding them to this repository.

],
Comment on lines +74 to +78
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test target declares .copy("testdata_*.arrow") resources, but those .arrow files are not present under Tests/ArrowTests/ in this branch. SwiftPM validates resource paths when loading the package, so this will break swift build/dependency resolution unless the files are checked in (or generated by a build tool plugin). Either commit these files (and keep them tracked), or switch to a generation approach that guarantees the resources exist before SwiftPM evaluates the package graph (e.g., a SwiftPM build-tool plugin), otherwise consumers will not be able to build the package.

Suggested change
resources: [
.copy("testdata_bool.arrow"),
.copy("testdata_double.arrow"),
.copy("testdata_struct.arrow")
],

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've committed the three .arrow files. The CI still regenerates them from the Go data generator, so the data should be fresh. This is the only way I was able to find.

swiftSettings: [
// build: .unsafeFlags(["-warnings-as-errors"])
]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Then add `Arrow` to your target's dependencies:
2. Enter the repository URL: `https://github.com/apache/arrow-swift.git`
3. Select your desired version rules and click **Add Package**

## Supported Platforms

- macOS 10.15+
- iOS 15.0+
- Linux (Ubuntu)

## Getting Started

For API documentation and usage examples, see the [documentation on Swift Package Index](https://swiftpackageindex.com/apache/arrow-swift/documentation).
Expand Down
24 changes: 15 additions & 9 deletions Tests/ArrowTests/IPCTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,14 @@ func checkStructRecordBatch(_ result: Result<ArrowReader.ArrowReaderResult, Arro
return recordBatches
}

func currentDirectory(path: String = #file) -> URL {
return URL(fileURLWithPath: path).deletingLastPathComponent()
func testDataURL(_ filename: String) throws -> URL {
guard let url = Bundle.module.url(forResource: filename, withExtension: "arrow") else {
throw ArrowError.ioError(
"Test data file \(filename).arrow not found in bundle. "
+ "Run the Go data generator first."
Comment on lines +112 to +113
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The failure message in testDataURL tells contributors to “Run the Go data generator first,” but the .arrow files are now checked into Tests/ArrowTests and bundled as SwiftPM resources. This can be misleading when the real issue is a missing/incorrect test resource configuration. Consider updating the message to mention verifying the test resources in Package.swift (and running the generator only when regenerating/updating the committed testdata).

Suggested change
"Test data file \(filename).arrow not found in bundle. "
+ "Run the Go data generator first."
"Test data file \(filename).arrow not found in test bundle. "
+ "Verify that the .arrow test resources are correctly declared in Package.swift, "
+ "and run the Go data generator only when regenerating or updating the committed test data."

Copilot uses AI. Check for mistakes.
)
}
return url
}

func makeSchema() -> ArrowSchema {
Expand Down Expand Up @@ -266,7 +272,7 @@ final class IPCStreamReaderTests: XCTestCase {

final class IPCFileReaderTests: XCTestCase { // swiftlint:disable:this type_body_length
func testFileReader_double() throws {
let fileURL = currentDirectory().appendingPathComponent("testdata_double.arrow")
let fileURL = try testDataURL("testdata_double")
let arrowReader = ArrowReader()
let result = arrowReader.fromFile(fileURL)
let recordBatches: [RecordBatch]
Expand Down Expand Up @@ -300,14 +306,14 @@ final class IPCFileReaderTests: XCTestCase { // swiftlint:disable:this type_body
}

func testFileReader_bool() throws {
let fileURL = currentDirectory().appendingPathComponent("testdata_bool.arrow")
let fileURL = try testDataURL("testdata_bool")
let arrowReader = ArrowReader()
try checkBoolRecordBatch(arrowReader.fromFile(fileURL))
}

func testFileWriter_bool() throws {
// read existing file
let fileURL = currentDirectory().appendingPathComponent("testdata_bool.arrow")
let fileURL = try testDataURL("testdata_bool")
let arrowReader = ArrowReader()
let fileRBs = try checkBoolRecordBatch(arrowReader.fromFile(fileURL))
let arrowWriter = ArrowWriter()
Expand All @@ -321,7 +327,7 @@ final class IPCFileReaderTests: XCTestCase { // swiftlint:disable:this type_body
throw error
}
// write file record batches to another file
let outputUrl = currentDirectory().appendingPathComponent("testfilewriter_bool.arrow")
let outputUrl = FileManager.default.temporaryDirectory.appendingPathComponent("testfilewriter_bool.arrow")
switch arrowWriter.toFile(outputUrl, info: writerInfo) {
case .success:
try checkBoolRecordBatch(arrowReader.fromFile(outputUrl))
Expand All @@ -331,14 +337,14 @@ final class IPCFileReaderTests: XCTestCase { // swiftlint:disable:this type_body
}

func testFileReader_struct() throws {
let fileURL = currentDirectory().appendingPathComponent("testdata_struct.arrow")
let fileURL = try testDataURL("testdata_struct")
let arrowReader = ArrowReader()
try checkStructRecordBatch(arrowReader.fromFile(fileURL))
}

func testFileWriter_struct() throws {
// read existing file
let fileURL = currentDirectory().appendingPathComponent("testdata_struct.arrow")
let fileURL = try testDataURL("testdata_struct")
let arrowReader = ArrowReader()
let fileRBs = try checkStructRecordBatch(arrowReader.fromFile(fileURL))
let arrowWriter = ArrowWriter()
Expand All @@ -352,7 +358,7 @@ final class IPCFileReaderTests: XCTestCase { // swiftlint:disable:this type_body
throw error
}
// write file record batches to another file
let outputUrl = currentDirectory().appendingPathComponent("testfilewriter_struct.arrow")
let outputUrl = FileManager.default.temporaryDirectory.appendingPathComponent("testfilewriter_struct.arrow")
switch arrowWriter.toFile(outputUrl, info: writerInfo) {
case .success:
try checkStructRecordBatch(arrowReader.fromFile(outputUrl))
Expand Down
Binary file added Tests/ArrowTests/testdata_bool.arrow
Binary file not shown.
Binary file added Tests/ArrowTests/testdata_double.arrow
Binary file not shown.
Binary file added Tests/ArrowTests/testdata_struct.arrow
Binary file not shown.
Loading