Рекомендации
За годы работы с различными командами и проектами мы выявили набор рекомендаций, которых советуем придерживаться при работе с Tuist и проектами Xcode. Эти рекомендации не являются обязательными, но они помогут структурировать проекты так, чтобы их было проще поддерживать и масштабировать.
Xcode#
Нежелательные подходы#
Конфигурации для моделирования удалённых сред#
Многие организации используют конфигурации сборки для моделирования различных удалённых сред (например, Debug-Production или Release-Canary), но у такого подхода есть недостатки:
- Несогласованность: Если в графе зависимостей есть несоответствия конфигураций, система сборки может использовать неверную конфигурацию для некоторых целей.
- Сложность: В проектах может накопиться длинный список локальных конфигураций и удалённых сред, которые трудно анализировать и поддерживать.
Конфигурации сборки предназначены для хранения различных настроек сборки, и проектам редко требуется больше, чем просто Debug и Release. Потребность в моделировании разных сред можно решить иначе:
- В сборках Debug: Вы можете включить в приложение все конфигурации, доступные при разработке (например, конечные точки), и переключать их во время выполнения. Переключение можно реализовать через переменные среды запуска схемы или через интерфейс внутри приложения.
- В сборках Release: Для релиза можно включить только ту конфигурацию, к которой привязана сборка, и исключить логику переключения конфигураций во время выполнения с помощью директив компилятора.
Хотя Tuist поддерживает нестандартные конфигурации и упрощает их управление по сравнению с обычными проектами Xcode, вы получите предупреждения, если конфигурации не согласованы в графе зависимостей. Это помогает обеспечить надёжность сборки и предотвращает проблемы, связанные с конфигурациями.
Сгенерированные проекты#
Папки сборки#
Tuist 4.62.0 добавил поддержку папок сборки (синхронизированных групп Xcode) — функции, появившейся в Xcode 16 для уменьшения конфликтов при слиянии.
Хотя шаблоны с подстановочными знаками в Tuist (например, Sources/**/*.swift) уже устраняют конфликты слияния в сгенерированных проектах, папки сборки дают дополнительные преимущества:
- Автоматическая синхронизация: структура проекта остаётся синхронизированной с файловой системой — не нужно перегенерировать проект при добавлении или удалении файлов
- Рабочие процессы, удобные для ИИ: помощники и агенты могут изменять кодовую базу без запуска перегенерации проекта
- Более простая настройка: задавайте пути к папкам вместо управления явными списками файлов
Мы рекомендуем использовать папки сборки вместо традиционных атрибутов Target.sources и Target.resources для более эффективного процесса разработки.
let target = Target(
name: "App",
buildableFolders: ["App/Sources", "App/Resources"]
)
let target = Target(
name: "App",
sources: ["App/Sources/**"],
resources: ["App/Resources/**"]
)
Зависимости#
Фиксация разрешённых версий на CI#
При установке зависимостей Swift Package Manager на CI мы рекомендуем использовать флаг --force-resolved-versions для обеспечения детерминированных сборок:
tuist install --force-resolved-versions
Этот флаг гарантирует, что зависимости разрешаются с использованием точных версий, зафиксированных в Package.resolved, что исключает проблемы, вызванные недетерминизмом при разрешении зависимостей. Это особенно важно на CI, где критична воспроизводимость сборок.
Кэшированная установка зависимостей в GitHub Actions#
Для сгенерированных проектов используйте tuist/install для установки зависимостей, зафиксированных в Package.resolved, и их кэширования между запусками. Он автоматически использует тома кэша на Tuist Runners и кэш GitHub на других раннерах.
name: Generate project
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
generate:
runs-on: tuist-macos
steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v4
- uses: tuist/install@v1
- run: tuist generate --no-open
Для проекта в подкаталоге укажите путь относительно 체크아웃нутого репозитория:
- uses: tuist/install@v1
with:
path: apps/ios
См. справочник по действию для дополнительных параметров.
Разработка с агентами и рабочие деревья#
Агенты и люди всё чаще работают параллельно: разработчик держит открытым рабочее дерево для проверяемой функции, пока один или несколько агентов итерируют по своим веткам в соседних рабочих деревьях. Несколько решений по проекту делают этот процесс гораздо удобнее.
Используйте папки сборки для изменений, выполняемых агентом#
Когда агент добавляет или удаляет файлы, всё, что зависит от списка файлов в Project.swift, требует выполнения tuist generate перед повторной сборкой проекта. Папки сборки переносят эту ответственность на синхронизированные группы Xcode, поэтому изменения в дереве файлов больше не вызывают перегенерацию.
Совместите это с generated-projects навыком, который обучает агентов повседневным рабочим процессам проекта Tuist.
Не изолируйте кэш для каждого рабочего дерева#
Tuist следует спецификации базовых каталогов XDG, поэтому по умолчанию все рабочие деревья на одной машине совместно используют ~/.cache/tuist и ~/.local/state/tuist. Это именно то, что нужно: хелперы, скомпилированные в одном рабочем дереве, плагины, загруженные в другом, и бинарные файлы из кэша модулей, полученные третьим, — все они повторно используемы.
Параллельные вызовы tuist в разных рабочих деревьях безопасно выполнять одновременно. Не указывайте TUIST_XDG_CACHE_HOME на путь, локальный для рабочего дерева, если вам не нужна изоляция; в противном случае каждое рабочее дерево будет заново прогревать хелперы, плагины и бинарные файлы.
Сохраняйте временные данные SwiftPM отдельно для каждого рабочего дерева#
Swift Package Manager имеет собственные механизмы управления путями. --scratch-path — это изменяемое рабочее состояние, по умолчанию равное .build, а --cache-path — общая директория кэша. Эти два пути не следует обрабатывать одинаково, когда активно несколько рабочих деревьев.
Поведение tuist install по умолчанию в Tuist уже хранит временные данные SwiftPM в директории пакета, поэтому каждое рабочее дерево получает собственный .build. Сохраняйте эту изоляцию. Одна общая директория временных данных SwiftPM может смешивать клоны, промежуточные результаты сборки, плагины, макросы и файлы блокировок из несвязанных веток.
Если вы передаете аргументы SwiftPM через tuist install -- ... или через installOptions в Tuist.swift, используйте общий --cache-path, если хотите ускорить загрузку зависимостей, но оставьте --scratch-path незаданным или укажите путь, локальный для рабочего дерева:
import ProjectDescription
let tuist = Tuist(
project: .tuist(
installOptions: .options(
passthroughSwiftPackageManagerArguments: [
"--cache-path",
"/Users/Shared/swiftpm/cache/xcode-16-macos",
]
)
)
)
Используйте обертку или переменную окружения CI для пути к кэшу, если он должен различаться в зависимости от Xcode, инструментария Swift или платформы. Не добавляйте в репозиторий общий --scratch-path.
Если состояние зависимостей выглядит поврежденным только в одном рабочем дереве, удалите директорию .build этого рабочего дерева и снова запустите tuist install. Если общий кэш SwiftPM вызывает подозрения во всех рабочих деревьях, используйте swift package purge-cache перед повторной установкой зависимостей.
Опирайтесь на кэш модулей#
Кэш модулей делает параллельную работу с рабочими деревьями управляемой. Поскольку Tuist вычисляет детерминированный хеш для каждой цели, два рабочих дерева, указывающие на ветки с общей историей, будут использовать одни и те же бинарные файлы. Запускайте tuist cache при каждом коммите в main из CI; локально tuist generate в каждом рабочем дереве загружает из кэша всё возможное и собирает только то, что действительно изменилось в вашей ветке.
Если рабочее дерево возвращается к сборке из исходного кода, когда вы ожидали попадания в кэш, следуйте шагам отладки хеширования; недетерминированные хеши (обычно вызванные абсолютными путями в проекте) являются наиболее частой причиной, и они явно проявляются при сравнении двух рабочих деревьев.
Ускорьте разрешение Swift-пакетов с помощью реестра#
Каждое рабочее дерево разрешает Swift-пакеты независимо. В проекте с большим графом зависимостей это быстро накапливается. Переход на Реестр Tuist позволяет избежать повторного клонирования git-историй и сокращает время разрешения с минут до секунд.
Предоставьте агентам доступ к аналитике проекта#
Когда сборки и тесты запускаются во многих рабочих деревьях, самое полезное, что может сделать агент, — это определить, какие из этих запусков показали регрессию, какие тесты нестабильны или как изменился размер бандла. Tuist предоставляет эти данные через MCP-сервер и пакет Skills. Выберите один вариант для каждого рабочего процесса и придерживайтесь его; смешивание обоих для одной задачи часто приводит к непоследовательному поведению агента.