iOS Build System
This guide explains how the iOS build system is structured, including Xcode schemes, build configurations, provisioning profiles, and Fastlane lanes.
Architecture Overview
Xcode Schemes
A scheme defines what targets to build, what configuration to use, and what actions to perform. Each environment has its own scheme.
Available Schemes
| Scheme | Configuration | Bundle ID | Purpose |
|---|---|---|---|
dev.pivot3 | Dev.debug / Dev.release | jobs.pivot.dev | Development builds |
dev2.pivot3 | Dev2.debug / Dev2.release | jobs.pivot.dev2 | Development 2 builds |
qa.pivot3 | QA.debug / QA.release | jobs.pivot.qa | QA/Staging builds |
pivot3 | Debug / Release | com.pivot3 | Production builds |
Scheme Files Location
ios/pivot3.xcodeproj/xcshareddata/xcschemes/
├── dev.pivot3.xcscheme
├── dev2.pivot3.xcscheme
├── qa.pivot3.xcscheme
└── pivot3.xcscheme
Build Configurations
Each scheme uses specific build configurations that define compiler flags, bundle IDs, and signing settings.
Configuration Mapping
Configuration Details
| Configuration | Use Case | Code Signing | Optimization |
|---|---|---|---|
*.debug | Local development | Development | None |
*.release | TestFlight / Distribution | AdHoc or App Store | Full |
Provisioning Profiles
Provisioning profiles link your app to a specific team, bundle ID, and set of devices.
Profile Types
| Type | Purpose | Used For |
|---|---|---|
| Development | Local device testing | Running on physical devices during development |
| AdHoc | TestFlight internal | Beta testing via TestFlight |
| App Store | Production release | App Store distribution |
Profile Naming Convention
Fastlane Match creates profiles with this naming pattern:
match [Type] [Bundle ID]
Examples:
- match AdHoc jobs.pivot.dev
- match AdHoc jobs.pivot.dev2
- match AdHoc jobs.pivot.qa
- match AppStore com.pivot3
Profile Storage
All profiles are stored in the pivot-mob-cert Git repository:
pivot-mob-cert/
├── certs/
│ ├── distribution/ # AdHoc & App Store certificates
│ └── development/ # Development certificates
└── profiles/
├── adhoc/
│ ├── AdHoc_jobs.pivot.dev.mobileprovision
│ ├── AdHoc_jobs.pivot.dev2.mobileprovision
│ └── AdHoc_jobs.pivot.qa.mobileprovision
└── appstore/
└── AppStore_com.pivot3.mobileprovision
Fastlane Configuration
Fastlane automates the build and deployment process.
Lane Structure
Lane Definitions
Each environment has its own lane in fastlane/Fastfile:
# Development lane
lane :dev do
app_store_connect_api_key(...)
latest_testflight_build_number(app_identifier: "jobs.pivot.dev")
increment_build_number(...)
match(type: "adhoc", app_identifier: "jobs.pivot.dev")
copy_files(source: "...development.plist", destination: "...")
build_app(scheme: "dev.pivot3", configuration: "Dev.release")
pilot(app_identifier: "jobs.pivot.dev")
end
# Development 2 lane
lane :dev2 do
# Same structure, different identifiers
app_store_connect_api_key(...)
match(type: "adhoc", app_identifier: "jobs.pivot.dev2")
build_app(scheme: "dev2.pivot3", configuration: "Dev2.release")
pilot(app_identifier: "jobs.pivot.dev2")
end
Build Settings in Xcode
Bundle ID Configuration
Bundle IDs are configured per-configuration in project.pbxproj:
Build Settings > Signing & Capabilities > Bundle Identifier
Dev.debug: jobs.pivot.dev
Dev.release: jobs.pivot.dev
Dev2.debug: jobs.pivot.dev2
Dev2.release: jobs.pivot.dev2
QA.debug: jobs.pivot.qa
QA.release: jobs.pivot.qa
Debug: com.pivot3
Release: com.pivot3
Provisioning Profile Configuration
Build Settings > Signing & Capabilities > Provisioning Profile
Dev.release: match AdHoc jobs.pivot.dev
Dev2.release: match AdHoc jobs.pivot.dev2
QA.release: match AdHoc jobs.pivot.qa
Release: match AppStore com.pivot3
GitHub Actions Workflow
Each branch triggers a specific workflow.
Workflow Structure
# .github/workflows/ios-dev2-build.yml
name: iOS Dev2 Build
on:
push:
branches: [development2]
jobs:
build:
uses: ./.github/workflows/ios-build.yml
with:
environment: "Dev2"
fastlane_lane: "dev2"
secrets: inherit
Reusable Workflow
All iOS builds use a shared workflow (.github/workflows/ios-build.yml) that:
- Checks out the code
- Sets up Ruby and Node.js
- Installs dependencies
- Configures SSH for certificate access
- Runs the specified Fastlane lane
Troubleshooting
Common Issues
"No matching provisioning profile"
Cause: Profile not synced or doesn't include required capabilities.
Solution:
bundle exec fastlane match adhoc --app_identifier jobs.pivot.dev2 --force
Only use --force when you need to regenerate. This invalidates existing profiles.
"Code signing is required"
Cause: Wrong build configuration selected.
Solution: Ensure you're using the release configuration for distribution builds:
build_app(
scheme: "dev2.pivot3",
configuration: "Dev2.release" # Not Dev2.debug
)
"Missing capability in provisioning profile"
Cause: App capability (like Sign in with Apple) not enabled in the profile.
Solution:
- Enable capability in Apple Developer Portal
- Regenerate profile:
fastlane match adhoc --force
Next Steps
- Creating New Environments - Add development3, development4, etc.
- Deployment Guide - Manual deployment process