Building¶
DashPilot is a plain Xcode project with no package manager, no code generation step and no bootstrap script. Cloning it and opening it is the whole setup.
Requirements¶
| Requirement | Version |
|---|---|
| Xcode | A version including the iOS 26.5 SDK or newer |
| iOS deployment target | 26.5 |
| Swift | Swift 5 language mode, with SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor |
| Dependencies | None |
| Targets | DashPilot, plus the DashPilotWidgets extension it embeds |
The deployment target is iOS 26.5. Check xcodebuild -showsdks and select a compatible installed
simulator. The Interval 4B verification host uses Xcode 27.1; that is a tested host, not a new
minimum deployment target.
Schemes¶
Both schemes are shared and committed, under
DashPilot.xcodeproj/xcshareddata/xcschemes, so -scheme DashPilot means the same thing in a fresh
clone, in CI and on a machine that has had the project open for months. Per-user Xcode state
(xcuserdata) stays out of the repository, and one of the things it holds is a flag that switches
off Xcode's automatic creation of a scheme for a target. A project whose schemes are not tracked
therefore builds or does not build from the command line depending on files nobody can see.
In Xcode¶
Open DashPilot.xcodeproj, choose the DashPilot scheme and an iOS simulator, then build and run.
The scheme covers the app, the DashPilotWidgets extension it embeds, the DashPilotTests domain
suite and the DashPilotUITests journeys. There is a DashPilotWidgets scheme too, and it is only
useful for previews: the extension cannot run on its own, and the Live Activity it draws is requested
by the app.
From the command line¶
xcodebuild build \
-project DashPilot.xcodeproj \
-scheme DashPilot \
-destination 'platform=iOS Simulator,name=iPhone 17'
xcodebuild test \
-project DashPilot.xcodeproj \
-scheme DashPilot \
-destination 'platform=iOS Simulator,name=iPhone 17'
Substitute any installed iPhone simulator for iPhone 17. To see what is installed:
For the clean verification build, include the app, embedded widget and both test targets together:
xcodebuild clean build-for-testing -project DashPilot.xcodeproj -scheme DashPilot \
-destination 'platform=iOS Simulator,name=iPhone 17' \
-derivedDataPath DerivedData CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO
Then run each complete suite using test-without-building with the same destination and derived
data path. Keep UI tests serial with -parallel-testing-enabled NO. See Testing.
The typeface¶
DashPilot is set in SF Pro, the system typeface, and bundles no font: there is no font file, no
UIAppFonts entry and no font license in the app or the widget extension. The reasons are in the
design system. DashPilot's own source code is MIT
(LICENSE).
FontBundleInvariantTests pins what a font change must not disturb: no UIAppFonts entry and no
font file or font license in the app bundle, the widget extension still embedded and carrying no
font, and NSSupportsLiveActivities, the location background mode and the When In Use usage
description all still declared. ProjectFileInvariantTests reads the project file for two things the
bundle cannot show: no file reference is an absolute path on one machine, and no font folder is a
member of the widget target.
Signing¶
The app target carries a development team for local device runs. Simulator builds do not need it,
and CI passes CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO so that no Apple Developer account
is required to build or test the project. Nothing in the repository signs or archives for
distribution.
Building the documentation site¶
The documentation is MkDocs Material. It is entirely separate from the app: Python is never required to build or run DashPilot itself.
mkdocs serve publishes a live-reloading copy on http://127.0.0.1:8000/.
To reproduce exactly what CI checks:
strict is on in mkdocs.yml as well, so a broken internal link, a missing anchor or a page left
out of the navigation fails the build rather than shipping. The generated site/ directory is
ignored by Git and must never be committed.
Continuous integration¶
One workflow covers the app and two the documentation:
| Workflow | Trigger | What it does |
|---|---|---|
ci.yml |
Pull requests, pushes to main, a weekly schedule, v* tags, manual dispatch |
Builds the app and both test bundles for an iOS simulator on a GitHub-hosted macOS runner, then runs the whole domain suite and every UI journey as separate steps |
docs-check.yml |
Pull requests touching docs/, mkdocs.yml, requirements-docs.txt, the README or itself |
Runs mkdocs build --strict on Ubuntu. It validates only and never deploys |
docs.yml |
Pushes to main touching documentation, and manual dispatch |
Builds the site and deploys it to GitHub Pages through the Actions artifact |
The runner details, including how the Xcode version and the simulator destination are chosen, are under Testing.