Объявление GitHub от 10 сентября 2026 года подтверждает: cache-mode доступен для всех планов и позволяет задавать режим доступа на уровне workflow и Job (официальное объявление). Для Mac CI настройте права под доверие к конкретной задаче: чтение, запись или отсутствие доступа — не выдавайте всем заданиям одинаковые полномочия. Настройка Job имеет приоритет над настройкой workflow; проверьте результат по конфигурации и журналам, а не по скорости сборки.
Симптом: задания используют общий кэш, но вы не можете обосновать, какие из них вправе его изменять.
Быстрое решение: сначала разделите задачи по уровню доверия, затем задайте минимально необходимый режим на уровне Job и проверьте его в контролируемом запуске.
Эта инструкция пригодится разработчикам, которые сопровождают кэш Mac CI и должны разделять права сборочных задач.
Она также адресована инженерам безопасности, проверяющим низкодоверенные события, и платформенным командам, распространяющим правила на несколько репозиториев.
GitHub Actions cache-mode для Mac CI: доступ нужно оценивать по действиям
Кэширование ускоряет повторное получение зависимостей и других промежуточных данных, но само наличие кэша не означает, что каждой задаче нужны одинаковые права. Настройка cache-mode нужна для того, чтобы управлять доступом к кэшу отдельно от обычной логики сборки. Это особенно важно, когда один workflow обрабатывает как изменения доверенной ветки, так и запросы, содержащие код от менее доверенных участников.
Решение принимайте по трём отдельным вопросам:
- Должна ли задача восстанавливать существующий кэш?
- Должна ли она сохранять новые данные?
- Нужно ли ей вообще обращаться к кэшу?
Возможность читать кэш не равна возможности записывать его. Если проверка запроса на слияние только запускает тесты, ей может быть достаточно чтения — при условии, что политика репозитория и модель угроз допускают такое использование. Запись оправдана для доверенного процесса, который формирует кэш для последующих сборок. Если задача не нуждается в кэше, доступ лучше отключить, а не оставлять «на всякий случай».
Режимы и точный синтаксис берите из актуальной документации GitHub по синтаксису workflow: не переносите в конфигурацию значения из примеров, относящихся к другой версии инструмента. Объявление сообщает о поддержке параметра на уровне workflow и Job, но в рабочем репозитории именно проверка актуальной схемы должна определять допустимую запись.
| Вариант доступа | Когда он уместен | Что проверять при приёмке | Если проверка не пройдена |
|---|---|---|---|
| Только восстановление | Задача использует готовые зависимости, но не должна создавать или менять кэш | В журнале подтверждается попытка восстановления, а сохранение не выполняется | Уберите возможность записи на уровне Job и проверьте наследование настроек |
| Только сохранение | Доверенная задача формирует кэш, а чтение ей не требуется по принятой модели | Видно действие сохранения; отсутствие восстановления соответствует замыслу | Проверьте, не нужна ли задаче предварительная загрузка, и явно задайте необходимые права |
| Чтение и запись | Доверенная сборка одновременно использует существующие данные и обновляет кэш | Раздельно подтверждены восстановление и последующее сохранение | Если запись не нужна, перейдите к режиму только для чтения |
| Без доступа | Задача не должна зависеть от общего кэша или влиять на него | В журналах нет успешного обращения к кэшу | Проверьте Job-настройку и вызываемый workflow; не считайте отсутствие ускорения доказательством запрета |
Это матрица принятия решения, а не замена справочнику допустимых значений. В настройке используйте ровно те имена режимов, которые указаны в текущей официальной схеме. Ошибка в строке YAML способна привести к неприменённой конфигурации, поэтому наличие параметра в файле ещё не доказывает, что раннер выполнил нужную политику.
Важно: удачное завершение сборки ничего не говорит о корректности прав на кэш. Сборка может пройти и при более широком доступе, чем вы планировали.
Какие ограничения нужно учесть до изменения конфигурации
Настройка доступа решает конкретную задачу, но не превращает весь workflow в безопасную среду. Прежде чем применять её массово, проверьте ограничения, которые часто остаются незаметными при обычном ревью YAML.
Первое — доверие к источнику кода. Запрос на слияние может содержать изменения, которые не прошли проверку владельцами проекта. Если такой процесс получает право записывать данные, появляется риск кеширования нежелательного содержимого и его последующего использования другими задачами. В документации GitHub по безопасности кэша зависимостей отдельно рассматриваются риски работы с недоверенными данными. Учитывайте не только автора запуска, но и то, какой код исполняется и кто сможет использовать результат.
Второе — особая опасность pull_request_target. Этот тип запуска может работать в контексте базового репозитория, поэтому не следует добавлять в него выполнение кода из недоверенного запроса и давать такой комбинации доступ на запись без отдельного обоснования. GitHub предупреждает о рисках в руководстве по безопасному использованию pull_request_target. Само по себе ограничение кэша не устраняет другие риски, связанные с токенами, секретами и действиями workflow.
Третье — различие между восстановлением и сохранением. Команда может считать, что «кэш включён» означает только загрузку зависимостей, хотя workflow способен также обновлять кэш. Разнесите эти действия в плане проверки: разрешение на чтение и разрешение на запись должны иметь собственные основания.
Четвёртое — приоритет настроек. Широкое правило на уровне workflow не гарантирует одинаковый итог для каждого Job: локальная настройка задания способна изменить эффективный режим. Поэтому аудит только верхней части файла пропустит переопределения.
Пятое — границы кэша не совпадают с границами всего процесса сборки. Артефакты, секреты, токены, скрипты установки и сторонние действия требуют собственной оценки. GitHub описывает дополнительные меры в руководстве по безопасному использованию Actions. Ограничение доступа к кэшу не является полной защитой от компрометации workflow и не позволяет обещать полное устранение отравления кэша.
Job-level cache-mode перекрывает настройку workflow?
Да. По официальному объявлению cache-mode можно задавать на уровне workflow и Job, причём настройка Job имеет приоритет. Практическое следствие: общий режим в начале файла задаёт базовую политику, но итог для конкретного задания может отличаться. Именно поэтому настройки нужно проверять по каждому Job, который обращается к кэшу, а не только по основному YAML-блоку.
Для ревью полезно составить перечень задач, а не просто просмотреть места, где встречается слово «кэш». Для каждой задачи укажите событие, выполняемый код, требуемые операции и фактический уровень настройки. Если один Job запускает тесты для внешнего запроса, а другой публикует доверенную сборку, одинаковая политика для них должна быть осознанным исключением, а не результатом копирования шаблона.
Настройку Job проверяйте в двух местах: в итоговой конфигурации workflow и в журнале фактического запуска. Если журнал не содержит ожидаемого действия с кэшем, это не доказывает, что права ограничены: возможно, код не дошёл до соответствующего шага. Нужен контрольный сценарий, который действительно пытается выполнить операцию, не подвергая опасности рабочие данные.
Может ли pull_request_target записывать данные в кэш?
Не разрешайте запись только потому, что workflow должен ускорять проверки. Если событие обрабатывает код из недоверенного запроса или запускает изменённые им скрипты, расширение полномочий создаёт дополнительный путь для воздействия на данные, которые позже могут использовать другие задания. Риск зависит от состава workflow, источника исполняемого кода и того, какие процессы затем восстанавливают кэш; универсального утверждения «безопасно» здесь нет.
Перед настройкой ответьте на практические вопросы:
- Выполняется ли код из запроса на слияние, а не только доверенный код базовой ветки?
- Может ли задача записать данные, используемые более доверенным процессом?
- Есть ли отдельный Job для действий, которым действительно необходимо обновлять кэш?
- Можно ли вынести запись в запуск, доступный только после проверки изменений?
Если ответы не документированы, оставьте запись закрытой для низкодоверенного задания и сначала разделите workflow. Используйте официальный разбор pull_request_target как обязательную часть ревью, а не как формальную ссылку в комментарии. Такая осторожность снижает риск, но не гарантирует полного устранения кеширования нежелательных данных: важны также ключи, область доступности, исполняемые скрипты и последующее использование кэша.
Перед запуском: настройте проверку по шагам
Шаг 1. Разделите задачи по доверию
Сгруппируйте Jobs по источнику запуска и коду, который они исполняют: доверенные изменения основной ветки, внешние запросы, ручные операции и переиспользуемые workflows. Не смешивайте в одной строке «обычные тесты» и «публикацию сборки», если у них разные уровни доверия или разные права.
Запишите, кому принадлежит ответственность за каждую группу. В небольшом репозитории это может быть владелец workflow, в крупной организации — команда платформы или безопасности. Цель этого шага — не создать дополнительную бюрократию, а сделать очевидным, почему конкретная задача получает возможность читать или менять общий кэш.
Шаг 2. Назначьте минимум необходимых операций
Для каждого Job решите, требуется ли восстановление, сохранение, оба действия или ни одно. Обоснуйте решение через фактическую роль задания. Например, проверка, которой нужно лишь установить зависимости из уже сформированного кэша, не должна автоматически получать полномочия доверенной сборки, создающей этот кэш.
Если задание работает без кэша, отключите доступ и проверьте, не осталось ли скрытой зависимости от ранее сохранённых данных. Не подменяйте анализ предположением, что любой кэш безопасен, если его ключ включает идентификатор ветки или коммита: политика ключей и политика доступа — связанные, но не одинаковые меры.
Шаг 3. Проверьте область действия и приоритет
Сопоставьте настройку workflow с настройками каждого Job. Отдельно зафиксируйте, где есть локальное переопределение и чем оно объясняется. Если команда использует шаблон, включите эту проверку в ревью шаблона, иначе репозитории могут разойтись после очередного копирования конфигурации.
Для кода используйте только актуальный синтаксис из документации GitHub. Убедитесь, что параметр находится на поддерживаемом уровне YAML и что имена режимов соответствуют схеме. Не добавляйте выдуманное значение в качестве временной заглушки: неизвестная строка может остановить workflow или привести к поведению, отличающемуся от ожидаемого.
Шаг 4. Проверьте переиспользуемый workflow
Настройка вызывающего workflow — часть границы полномочий, а не обещание, что вызываемый файл получит неограниченный доступ. По правилам GitHub переиспользуемый workflow не должен расширять предоставленные ему права; сверяйте передачу полномочий с официальным описанием повторного использования workflows и актуальной схемой.
Проверьте конфигурации обеих сторон: вызывающего и вызываемого workflow. Зафиксируйте, что запросил вызывающий процесс, что фактически поддерживает вызываемый и какой режим установлен на уровне Job внутри него. Если вызываемый workflow одновременно используется несколькими репозиториями, не предполагайте, что одна и та же настройка подходит всем: контексты доверия могут различаться.
Шаг 5. Выполните контролируемые сценарии
Проведите проверку в тестовом репозитории или другом контролируемом контексте, где попытка записи не затронет данные, на которые полагаются рабочие задания. Отдельно проверьте сценарий восстановления, сценарий сохранения и сценарий без доступа. Для низкодоверенного события убедитесь, что фактическая конфигурация не предоставляет лишнюю возможность записи.
Сопоставьте ожидаемое поведение с журналом запуска и результатом конкретного шага. Если вы видите только успешную сборку, тест неполон: сборка могла использовать другой путь установки или вообще не обращаться к кэшу. Документация GitHub по управлению кэшами помогает сверить действия с записями кэша, но аудит прав всё равно требует проверки конфигурации и контекста запуска.
Шаг 6. Разделите приёмку кэша и приёмку сборки
Успешное восстановление кэша подтверждает, что данные удалось получить, но само по себе не доказывает корректность прав на запись. Успешное сохранение подтверждает, что операция состоялась, но не отвечает на вопрос, должно ли это задание иметь такую возможность. А успешный Xcode build показывает результат сборки, а не соблюдение модели доступа.
В отчёте фиксируйте эти результаты отдельно:
- Восстановление: было ли оно ожидаемо и видно ли соответствующее действие в журнале.
- Сохранение: требовалось ли оно этому Job и действительно ли оно произошло.
- Сборка: прошёл ли Xcode build после применения политики и не зависел ли результат от неучтённого пути получения зависимостей.
- Конфигурация: совпадает ли эффективный режим с утверждённой матрицей доступа.
Если что-либо не совпало, сначала сузьте права и выясните причину. Не ослабляйте политику только ради того, чтобы добиться привычного поведения: сначала подтвердите, что задача действительно должна выполнять эту операцию.
При разборе журналов маскируйте секреты и не помещайте в отчёт чувствительные данные. Правила хранения учётных данных должны проверяться отдельно; см. рекомендации SSHMac по защите конфиденциальных данных.
Как распространять правила между репозиториями
Для внедрения в нескольких Apple-проектах заведите короткую запись для каждого класса workflow: назначение Job, тип запуска, требуемые операции с кэшем, владелец решения, тестовый сценарий и способ отката. Указывайте не только выбранный режим, но и основание: например, «чтение нужно для зависимостей, запись не нужна, поскольку кэш создаётся доверенным процессом». Так ревьюер сможет проверить логику, не реконструируя её по истории изменений.
Сначала примените политику к репозиторию, представляющему наиболее типичный процесс, и проверьте все варианты запуска, которые реально используются командой. Затем расширяйте правило на похожие проекты, сверяя исключения, а не копируя файл без проверки. Если у репозитория есть pull_request_target, внешние авторы или вызываемые workflows, включайте эти особенности в отдельную проверку.
Откат тоже должен быть определён заранее. Укажите, какой файл или настройку нужно вернуть, кто согласует изменение и как убедиться, что временное расширение доступа удалено после расследования сбоя. Не храните постоянную широкую политику под видом «временной»: без владельца и условия удаления такое исключение обычно становится новым стандартом.
Для оценки качества решения используйте не одну общую оценку, а несколько критериев:
- Минимальность прав — высокая оценка, если каждое разрешение чтения и записи связано с конкретной задачей; ниже, если всем Jobs назначен одинаковый доступ без обоснования.
- Проверяемость — высокая, если сценарии чтения, записи и запрета подтверждены конфигурацией и журналом; ниже, если единственное доказательство — зелёный статус сборки.
- Управление доверием — высокая, если низкодоверенные события и
pull_request_targetпроверены отдельно; ниже, если они наследуют полномочия доверенной сборки без ревью. - Переносимость — высокая, если правила и исключения документированы для переиспользуемых workflow; ниже, если команда полагается на настройки, которые не проверялись на вызывающей и вызываемой сторонах.
Такой качественный рейтинг не заменяет техническую проверку, но показывает, где именно решение слабое. Если минимальность прав высокая, а проверяемость низкая, следующий шаг — не очередное ужесточение наугад, а контрольный запуск, который покажет фактическое поведение. Если низка оценка управления доверием, сначала изолируйте чувствительные события и уберите у них ненужную запись.
Когда вместо аренды Mac лучше оставить текущую CI-инфраструктуру
Настройка cache-mode не требует менять вычислительную инфраструктуру и не делает аренду Mac обязательной частью защиты. Если у вас есть устойчивый собственный раннер, физический доступ к нему необходим или нагрузка постоянная и предсказуемая, собственный Mac может быть разумнее: вы управляете устройством и его окружением непосредственно. Но существующий вариант может означать отдельные расходы на обслуживание раннера, ручное обновление инструментов и ограниченную гибкость, когда для проверки нужна изолированная среда.
Если вам нужно временно проверить workflow на отдельном Apple-совместимом окружении или воспроизвести конфигурацию без покупки ещё одного устройства, аренда Mac у SSHMac может быть удобнее, чем расширение постоянного парка. Это не заменяет GitHub Actions, ревью разрешений и проверку кэша; она лишь даёт отдельную среду для работы и тестирования. Условия и доступные варианты смотрите на странице аренды Mac mini. Для постоянной тяжёлой нагрузки, специализированных физических интерфейсов или полностью локального контроля сначала оцените собственный Mac, а аренду оставьте для временных потребностей и проверок.