Learn (Almost) Anything
КаталогСкачать курс

Автоматизация в GitHub

Ubuntu, Windows, macOS runners, `ubuntu-latest` и image drift, предустановленный софт, hardware classes, larger runners, networking и ограничения hosted runtime.

ruЭнциклопедия33 урока6 модулей9
GitHub actionsАвтоматизация в GitHubМодель workflowсостояние и артефактыматрицы и runtimeрелизы и environmentsПереиспользование и собственные actionsgovernance и эксплуатацияgithubactions

GitHub-hosted runners

Ubuntu, Windows, macOS runners, `ubuntu-latest` и image drift, предустановленный софт, hardware classes, larger runners, networking и ограничения hosted runtime.

GitHub-hosted runners

GitHub-hosted runner — это машина, которую GitHub поднимает для выполнения job в workflow. В обычном CI это та самая среда, где выполняются actions/checkout, setup runtime, установка зависимостей, тесты и build из CI pipeline. В Matrix strategy runner часто становится одной из осей матрицы: ubuntu-latest, windows-latest, macos-latest, конкретная версия Ubuntu или arm64-вариант.

Главная идея простая: вы не управляете этой машиной как сервером. GitHub обслуживает образ, обновляет предустановленный софт, выдаёт runner на job и после выполнения job среда исчезает. Поэтому GitHub-hosted runners удобны для большинства CI, но плохо подходят для сценариев, где нужен постоянный state, приватная сеть без дополнительных настроек или полный контроль над железом. Для этого уже смотрят в сторону Self-hosted runners или larger runners.

flowchart TD A[Workflow YAML] --> B[job.runs-on] B --> C{Label} C --> D[ubuntu-24.04 / ubuntu-latest] C --> E[windows-2025 / windows-latest] C --> F[macos-15 / macos-latest] C --> G[Larger runner label] D --> H[Fresh managed VM] E --> H F --> H G --> I[Managed VM with more CPU/RAM/disk or networking features] H --> J[Steps: checkout, setup, install, test, build] I --> J J --> K[Logs, artifacts, cache, job summary] K --> L[VM discarded after job]
flowchart TD
  A[Workflow YAML] --> B[job.runs-on]
  B --> C{Label}
  C --> D[ubuntu-24.04 / ubuntu-latest]
  C --> E[windows-2025 / windows-latest]
  C --> F[macos-15 / macos-latest]
  C --> G[Larger runner label]
  D --> H[Fresh managed VM]
  E --> H
  F --> H
  G --> I[Managed VM with more CPU/RAM/disk or networking features]
  H --> J[Steps: checkout, setup, install, test, build]
  I --> J
  J --> K[Logs, artifacts, cache, job summary]
  K --> L[VM discarded after job]
Как `runs-on` связывает job с конкретным hosted runner и почему state нужно выносить в cache или artifacts.

Что означает runs-on

runs-on выбирает тип runner для job:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm test

Для стандартных hosted runners чаще всего встречаются labels вроде ubuntu-latest, ubuntu-24.04, ubuntu-22.04, windows-latest, windows-2025, windows-2022, macos-latest, macos-15, macos-14. Есть и arm64 labels, например ubuntu-24.04-arm. Набор labels меняется со временем, поэтому в важных репозиториях лучше периодически сверяться с GitHub Docs и actions/runner-images, а не полагаться на старую заметку в README.

*-latest не значит «самая новая версия ОС, которую выпустил vendor». Это latest stable image, который GitHub сейчас считает дефолтным для Actions. Практически это означает: ubuntu-latest может перейти на новую Ubuntu не в тот день, когда Ubuntu вышла, а по расписанию GitHub. Для библиотек и production-sensitive CI часто разумнее pin на конкретный образ:

runs-on: ubuntu-24.04

Такой pin не делает среду полностью immutable, но убирает крупный класс сюрпризов: внезапную смену базовой версии OS.

Image drift: почему «вчера работало» бывает правдой

GitHub-owned runner images обновляются регулярно. В образах уже есть много инструментов: shell utilities, Git, Node, Python, Java, .NET, browsers, package managers, build tools и другое. Это удобно: простые workflow стартуют быстро. Но это же источник drift: версия Chrome, CMake, Python patch version или Android SDK может измениться между запусками.

Правильная реакция — не надеяться на предустановленную версию там, где версия важна. Используйте setup-actions и lock-файлы:

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-node@v4
    with:
      node-version-file: .nvmrc
      cache: npm

  - run: npm ci
  - run: npm test

Если сборка зависит от конкретного Chrome, Java, Ruby, Go или Xcode, фиксируйте это явно настолько, насколько позволяет экосистема. В логах workflow в секции Set up job есть информация о Runner Image и ссылка на included software именно для того runner, который выполнил job. Это первое место, куда стоит смотреть при странном падении после «ничего не меняли».

Set up job
  Current runner version: '2.327.1'
  Operating System
    Ubuntu
    24.04.2
    LTS
  Runner Image
    Image: ubuntu-24.04
    Version: 20260608.1.0
    Included Software: https://github.com/actions/runner-images/blob/ubuntu24/20260608.1/images/ubuntu/Ubuntu2404-Readme.md

Image drift не баг GitHub сам по себе. Это эксплуатационная реальность managed runtime. В Оптимизация времени CI drift обычно проявляется как внезапно замедлившийся job; в Dependency cache — как cache miss или конфликт бинарных зависимостей; в Artifacts и reports — как отличие отчётов между OS.

Ubuntu, Windows и macOS: выбирать по риску, а не по привычке

Ubuntu runners обычно самый дешёвый и быстрый дефолт для web/backend CI. Если проект деплоится в Linux-контейнер, ubuntu-24.04 почти всегда нормальная базовая среда для lint, unit tests и build. Для Docker-heavy workflow Linux также естественный выбор, а граница между runner, job container и service containers подробнее разобрана в Containers и service containers.

Windows runners нужны не «для разнообразия», а когда код реально должен работать на Windows: CLI tools, path separators, PowerShell scripts, desktop tooling, .NET/Windows SDK, архивы, line endings, filesystem semantics. Частая ошибка — гонять весь pipeline на Windows, хотя достаточно одного compatibility job на push или release branch.

macOS runners нужны для Apple tooling: Xcode, iOS/macOS builds, notarization-adjacent checks, Safari/WebKit-specific сценарии. Они дороже и обычно медленнее в очередях, поэтому их стоит держать точечно. Если Linux job уже проверяет TypeScript и unit tests, macOS job может собирать только Apple-специфичный target.

ИнтерактивКакой runner выбрать#int-1
Выберите наиболее естественный runner для каждой задачи.
Ubuntu hosted
Windows hosted
macOS hosted
Larger / self-hosted
Разложите типичные CI-задачи по средам. Это не правило навсегда, а рабочая эвристика для первого дизайна workflow.

Hardware classes и larger runners

Стандартные GitHub-hosted runners покрывают большинство CI. Но иногда job упирается не в YAML, а в ресурсы: мало RAM, мало disk, долгие code scanning runs, тяжёлый Android build, GPU-задачи, слишком много параллельных workflow. Для организаций на GitHub Team и GitHub Enterprise Cloud есть larger runners: managed VM с большим CPU/RAM/disk, autoscaling, runner groups, GPU-вариантами, а для Ubuntu/Windows — возможностью static IP и Azure private networking.

Пример выбора larger runner в workflow зависит от label, который доступен в организации:

jobs:
  heavy-build:
    runs-on: ubuntu-24.04-16core

    steps:
      - uses: actions/checkout@v4
      - run: ./gradlew build

Label здесь иллюстративный: реальное имя нужно смотреть в настройках организации или репозитория. У larger runners есть governance-слой: кто может их использовать, какие repositories имеют доступ, сколько job можно запускать одновременно. Это уже пересекается с Runner governance, потому что дорогие runners быстро становятся shared infrastructure, а не просто строкой в YAML.

Networking и allowlist

Обычные GitHub-hosted runners выходят в интернет из диапазонов, которыми управляет GitHub и cloud provider. Для Ubuntu и Windows это связано с Azure; macOS runners хостятся отдельно. GitHub публикует ranges через REST API, но сам GitHub не рекомендует строить firewall allowlist на огромном списке стандартных hosted IP: диапазонов много, они обновляются, а operational burden ложится на вас.

Если CI должен ходить в приватную staging-базу, внутренний package registry или закрытый Kubernetes API, есть три практичных варианта:

# 1. Оставить обычный hosted runner, но ходить только в публичные endpoint'ы
#    с короткоживущими credentials и минимальными правами.

# 2. Использовать larger runner со static IP / private networking,
#    если это доступно в вашем плане и регионе.

# 3. Перенести job на self-hosted runner внутри нужной сети.

Для cloud deploy часто лучший ответ — не «добавить IP в allowlist», а перейти на federated auth через OIDC. Тогда workflow получает короткоживущий cloud token без долгоживущего секрета в GitHub. Это отдельная тема в Cloud deploy через OIDC и OIDC и секреты облаков.

Ограничения hosted runtime

Hosted runner — свежая одноразовая среда, а не ваш build-сервер. Нельзя рассчитывать, что файл, установленный в одном job, останется в другом job. Для передачи результатов между jobs используйте artifacts или cache, в зависимости от смысла данных: отчёт и build output — в Artifacts и reports, зависимости и промежуточные build caches — в Dependency cache.

На Linux и macOS runner можно использовать passwordless sudo, Windows runner запускается с административными правами и отключённым UAC. Это удобно для установки пакетов, но не повод давать job лишние permissions. sudo apt-get install решает проблему missing package; широкие права GITHUB_TOKEN создают другую проблему, уже из области Secure use и threat model.

Ещё одно ограничение — nested virtualization. GitHub прямо отмечает, что nested VMs на hosted runners не являются официально поддерживаемым стабильным контрактом. Если workflow требует полноценную виртуализацию, специфичный hypervisor, нестандартное железо или стабильную локальную сеть, hosted runner перестаёт быть правильной абстракцией.

Практическая эвристика

Для обычного web/backend проекта начинайте с ubuntu-24.04, setup-action для runtime, lock-файла и cache. Добавляйте Windows/macOS только под реальный compatibility-риск. Используйте *-latest для некритичных workflow или когда команда осознанно принимает drift. Для стабильного CI pin конкретной OS-версии почти всегда лучше.

Если job стал тяжёлым, сначала проверьте структуру pipeline: не гоняете ли вы lint на всех OS, можно ли разделить build/test, есть ли нормальный cache, не устарели ли matrix axes. Только после этого переходите к larger runners. Больше CPU не исправит плохой dependency cache и не сделает бессмысленную матрицу полезной.

GitHub-hosted runners хороши тем, что снимают с команды обслуживание CI-инфраструктуры. Цена этой простоты — managed drift, сетевые ограничения и меньший контроль над средой. В зрелом workflow runner выбирают не по дефолту, а по контракту: какая OS нужна, какая версия образа допустима, какие ресурсы требуются и насколько job можно доверять внешней managed VM.

See also

Быстрое повторение #rc-1

Почему ubuntu-latest лучше не использовать в production-sensitive CI, если важна предсказуемость среды?

Показать ответ

*-latest — это дефолтный stable image GitHub Actions, а не неизменная версия ОС. GitHub может перевести label на новый образ по своему расписанию, поэтому для стабильного CI лучше pin вроде ubuntu-24.04.

Источники

  1. GitHub Docs: GitHub-hosted runners
  2. GitHub Docs: GitHub-hosted runners reference
  3. GitHub Docs: Larger runners
  4. GitHub Docs: Running jobs on larger runners
  5. GitHub Actions Runner Images repository