Zum Inhalt springen

ios-project-setup

Type Skill
Plugin awl-ios · v0.0.6
Invoke /awl-ios:ios-project-setup
Source plugins/awl-ios/skills/ios-project-setup/SKILL.md

Start a new iOS project from the AWL template or bring an existing one in line with it — Tuist Project.swift with App, Feature, and test targets pinned to minIosVersion, Swift 6 settings (approachable concurrency, main-actor default isolation), SwiftLint and SwiftFormat, the mise plus Brewfile toolchain, fastlane lanes with the .env split, 1Password CLI secrets, the GitLab pipeline shape (lint and test in parallel, SAST, Danger coverage gate, VulnTracker). Use when the user says “set up an iOS project”, “new iOS app”, “align with the template”, “add a feature module”, “migrate to Swift 6”, “add fastlane”, “set up CI for iOS”, “where do secrets go”, or a Tuist, xcconfig, or .gitlab-ci.yml question comes up on an iOS repo. NOT for writing tests (use awl-testing testing-swift), not for day-to-day build and simulator commands (use awl-ios-ref), not for KMP shared Kotlin code or the Android side (use awl-android kotlin-expert).

Trigger phrases: set up an iOS project · new iOS app · align with the template · add a feature module · migrate to Swift 6 · add fastlane · set up CI for iOS · where do secrets go

The source of truth is ios-infra/templates/project-template-ios on GitLab. Copy files from the template rather than writing them from memory, and read SETUP.md there when a step below is not enough.

Situation Path Read
Green-field app Copy the template, run sh rename_project.sh, then work through the checklist below in order all references
Existing Tuist project drifted from the template Diff Project.swift, .mise.toml, Brewfile, .swiftlint.yml, .swiftformat, fastlane/, .gitlab-ci.yml against the template and adopt section by section the reference for each section
Existing .xcodeproj project without Tuist Write a Project.swift that mirrors the current targets, move sources into buildable folders, gitignore the project file, then continue as a Tuist project references/project-structure.md
Only Swift 6 migration Add the three build settings, fix the errors, keep everything else references/project-structure.md, then swift-optimization
Only CI or secrets Keep the code, replace .gitlab-ci.yml, fastlane/, and the env files references/ci-pipeline.md, references/fastlane-secrets.md
KMP project with an iOS shell Same layout under iosApp/, but no API_BASE_URL, no Feature framework, and import Shared; see kmp-template/iosApp/README.md references/project-structure.md

Work top to bottom, because each step feeds the next.

  1. Toolchain. brew bundle from the Brewfile, mise install for Tuist, bundle install for fastlane. Pin Xcode in .xcode-version and Ruby in .ruby-version. Read references/toolchain.md when a tool is missing or the versions differ.
  2. Project definition. Project.swift with the app target, its test target, and one framework per feature plus its tests. All four use deploymentTargets: .iOS(minIosVersion), so a feature never compiles against a different SDK floor than the app. Read references/project-structure.md for the full target, scheme, configuration, and xcconfig layout.
  3. Swift 6 settings. In the project-level settings.base: SWIFT_VERSION = 6.0, SWIFT_APPROACHABLE_CONCURRENCY = YES, SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor. They apply to every target, so a feature framework gets the same isolation model as the app.
  4. Lint and format. Copy .swiftlint.yml and .swiftformat, add the SwiftLintBuildToolPlugin package to the app and feature targets, and extend included: in .swiftlint.yml when you add source folders. The template lists only ProjectTemplate/Sources and ProjectTemplate/Tests, so a new Feature/Sources folder is unlinted until you add it.
  5. Generate and build. tuist install && tuist generate --no-open, then build the staging scheme. Fix Swift 6 errors before adding fastlane, because fastlane build compiles in release mode and hides warnings behind gym output.
  6. fastlane and secrets. Keep fastlane/.env.staging and .env.prod committed with <VAR>_OP_REF pointers; never a bare secret. Run op signin, then bundle exec fastlane resolve_all_secrets --env staging to prove every reference resolves. Read references/fastlane-secrets.md for the lanes and the env split.
  7. Signing. Bundle IDs in the xcconfigs and env files, bundle exec fastlane certificates --env staging for match profiles. The xcconfigs use CODE_SIGN_STYLE = Manual with match Development for Debug and match AppStore for Release.
  8. CI. Copy .gitlab-ci.yml, add the GitLab variables SLACK_URL, LOCO_API_KEY, FASTLANE_GIT_DEPLOY_TOKEN (masked, environment-scoped), and set up the Apple App Store integration. Read references/ci-pipeline.md for the stage layout and why Danger waits for the test job.
  9. Localization and Firebase. Loco project and LOCO_* env values, GoogleService-Info-<env>.plist under Configurations/Firebase/. awl-ios-ref covers the Loco workflow.
  10. Project docs. Fill README.md placeholders, keep CLAUDE.md, commit .claude/settings.json with the marketplace entry so the team gets the awl-general and awl-testing plugins.
  • Secrets never land in a committed file. .env.staging and .env.prod are committed, so they hold op:// references only. fastlane/.env is gitignored and exists as an env-agnostic fallback for machines without op.
  • .xcodeproj and .xcworkspace are gitignored. Every developer and every CI job regenerates from Project.swift.
  • Feature and test targets share minIosVersion with the app. A lower target on a framework compiles against older availability and hides API misuse until runtime.
  • The SwiftLintBuildToolPlugin runs on every build, which is why before_all in the Fastfile disables Xcode’s plugin fingerprint validation. Keep those defaults write lines when editing the Fastfile.
  • Danger reads coverage from the pipeline API, so the danger-review-security override must keep needs: - job: test. Removing it makes the coverage check read a stale or missing value.
  • Only main, testing, production, merge requests, and schedules create pipelines. Feature branch pushes without an MR produce no pipeline by design.
Terminal-Fenster
tuist install && tuist generate --no-open
bundle exec fastlane lint --env staging
bundle exec fastlane test --env staging
bundle exec fastlane resolve_all_secrets --env staging

Then open an MR from a feature branch and confirm that lint, test, semgrep-sast, secret_detection, and danger-review-security all appear.

  • awl-ios-ref for the build, run, and Loco command loop once the project exists
  • swiftui-expert-skill and swift-optimization for code that fits the Swift 6 settings
  • awl-testing:testing-swift for the tests that feed the coverage gate
  • awl-cicd:gitlab-cicd for GitLab components shared with other stacks