Developing iOS Apps on Windows with GitHub Actions and XcodeGen
Two iOS apps—the encrypted messenger Dark Message and the HVAC engineering calculator—are published on the App Store. They were fully developed on Windows without a MacBook. The process: code is written locally, with building and signing on virtual macOS machines in GitHub Actions. Time from pushing to the repository to building on an iPhone is 15 minutes.
This bypasses the Xcode requirement for macOS. GitHub provides free runners with macOS, where Xcode is installed. Setup includes an Apple Developer Account, XcodeGen for generating the project from YAML, a CI/CD pipeline, and signing certificates.
Development Paths for Different Skill Levels
Choice of approach depends on skills:
- Vibe coding with AI: Claude Code generates SwiftUI code from descriptions. Works in the terminal on Windows. Example prompt: "iOS app in SwiftUI, AES-256-GCM encryption with PBKDF2, input/decryption screens."
- Programmer without a Mac: Your own Swift code + AI sets up infrastructure (XcodeGen, GitHub Actions, certificates).
- Hardcore: Manual project structure, YAML config, pipeline. Iterations via TestFlight without local preview.
Installing Claude Code:
npm install -g @anthropic-ai/claude-code
claude
AI creates files, edits based on feedback. No preview, but cloud builds compensate.
Step 1: Apple Developer Account from Russia
Create an Apple ID at appleid.apple.com (country ≠ Russia). Register at developer.apple.com/programs/enroll as an Individual. Payment $99/year—use a foreign card (Bybit or similar). Access to App Store Connect within 24–48 hours.
Step 2: Project Structure and XcodeGen
XcodeGen generates .xcodeproj from project.yml without Xcode. Example config:
name: DarkMessage
options:
bundleIdPrefix: com.darkmessage
deploymentTarget:
iOS: "15.0"
xcodeVersion: "15.0"
targets:
DarkMessage:
type: application
platform: iOS
sources:
- path: Sources
resources:
- path: Resources
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.darkmessage.ios
MARKETING_VERSION: "1.0.0"
CURRENT_PROJECT_VERSION: "1"
SWIFT_VERSION: "5.9"
TARGETED_DEVICE_FAMILY: "1,2"
INFOPLIST_VALUES:
UILaunchScreen: {}
dependencies: []
Repository structure:
Sources/: App.swift, Views/, Models/, Services/ (CryptoService.swift).Resources/Assets.xcassets/.project.yml..github/workflows/build.yml.
YAML advantages: compact (30 lines), no Git conflicts, editable in VS Code.
Step 3: Repository and GitHub Actions
Initialization:
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/user/repo.git
git push -u origin main
Actions runners with macOS build the project: xcodegen generate, xcodebuild, signing, upload to TestFlight/App Store.
Step 4: Code Signing without a Mac
Required:
- Distribution Certificate (.p12).
- Provisioning Profile (.mobileprovision).
- App Store Connect API Key.
Generate CSR on Windows with OpenSSL:
openssl genrsa -out ios_dist.key 2048
openssl req -new -key ios_dist.key -out ios_dist.csr -subj "/CN=Your Name/[email protected]"
Upload CSR to developer.apple.com/account/resources/certificates → Apple Distribution → download .cer. Convert to .p12:
openssl x509 -inform der -in ios_dist.cer -inkey ios_dist.key -out ios_dist.p12
Provisioning Profile: developer.apple.com → Profiles → + → App Store → bundle ID → certificate.
API Key: App Store Connect → Users and Access → Keys → + → App Manager.
Store secrets in GitHub Settings → Secrets: CERTIFICATE_P12_BASE64, PROVISIONING_PROFILE_BASE64, APPSTORE_API_KEY.
Step 5: Workflow YAML for CI/CD
Example .github/workflows/build.yml (simplified):
name: Build iOS
on: [push]
jobs:
build:
runs-on: macos-13
steps:
- uses: actions/checkout@v4
- name: Generate Xcode project
uses: maxim-lobanov/setup-xcodegen@v1
with:
xcodegen-version: '2.35.0'
- run: xcodegen generate
- name: Import certificate
env:
CERTIFICATE_P12: ${{ secrets.CERTIFICATE_P12_BASE64 }}
run: |
echo $CERTIFICATE_P12 | base64 --decode > cert.p12
security import cert.p12 -k ~/Library/Keychains/login.keychain
# ... signing, archive, upload
Full workflow includes xcodebuild archive, xcrun altool or xcrun notarytool for the App Store.
Key Points
- GitHub Actions with macOS are free for public repos (2000 min/month).
- XcodeGen simplifies project management without Xcode.
- Code signing is automated via base64-encoded secrets.
- Iterations: 15 minutes from push to TestFlight.
- Suitable for one-off projects; for production, a Mac speeds up development.
— Editorial Team
No comments yet.