Skip to main content

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​

SchemeConfigurationBundle IDPurpose
dev.pivot3Dev.debug / Dev.releasejobs.pivot.devDevelopment builds
dev2.pivot3Dev2.debug / Dev2.releasejobs.pivot.dev2Development 2 builds
qa.pivot3QA.debug / QA.releasejobs.pivot.qaQA/Staging builds
pivot3Debug / Releasecom.pivot3Production 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​

ConfigurationUse CaseCode SigningOptimization
*.debugLocal developmentDevelopmentNone
*.releaseTestFlight / DistributionAdHoc or App StoreFull

Provisioning Profiles​

Provisioning profiles link your app to a specific team, bundle ID, and set of devices.

Profile Types​

TypePurposeUsed For
DevelopmentLocal device testingRunning on physical devices during development
AdHocTestFlight internalBeta testing via TestFlight
App StoreProduction releaseApp 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:

  1. Checks out the code
  2. Sets up Ruby and Node.js
  3. Installs dependencies
  4. Configures SSH for certificate access
  5. 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
warning

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:

  1. Enable capability in Apple Developer Portal
  2. Regenerate profile: fastlane match adhoc --force

Next Steps​