Environments и protection rules
`production`, `staging`, approvals, wait timers, deployment branch/tag restrictions, custom protection rules, environment secrets/vars и связь с deployment history.
Environments и protection rules
Environment в GitHub Actions — это именованная цель деплоя: staging, production, preview, demo-eu, customer-a и так далее. В отличие от обычной переменной окружения, environment — это не строка для shell, а объект GitHub: у него есть protection rules, secrets, variables и история deployments. Когда job указывает environment, GitHub может остановить его перед выполнением деплойных steps, запросить approval, подождать wait timer, проверить branch/tag policy или спросить внешний GitHub App.
name: deploy
on:
push:
branches: [main]
jobs:
deploy-production:
runs-on: ubuntu-24.04
environment:
name: production
url: https://example.com
permissions:
contents: read
deployments: write
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
API_BASE_URL: ${{ vars.API_BASE_URL }}Здесь production связывает job с настройками environment. url попадёт в deployment history и, для PR-сценариев, может появиться как ссылка «View deployment». Секрет DEPLOY_TOKEN и variable API_BASE_URL берутся именно из environment, если они там заведены. Это продолжение темы Variables, env и secrets, но с важным отличием: environment secrets становятся доступны job только после прохождения protection rules.
flowchart TD
A[Workflow run дошёл до deploy job] --> B{Job ссылается на environment?}
B -- нет --> C[Job выполняется как обычный job]
B -- да --> D[GitHub создаёт deployment object]
D --> E{Branch/tag разрешён?}
E -- нет --> X[Deployment rejected / job не проходит gate]
E -- да --> F{Есть wait timer?}
F -- да --> G[Ожидание без billable runner time]
F -- нет --> H{Нужен reviewer?}
G --> H
H -- да --> I[Pending: approve или reject]
H -- нет --> J{Custom protection rule?}
I -- approved --> J
I -- rejected --> X
J -- да --> K[GitHub App approve/reject]
J -- нет --> L[Job получает environment secrets/vars]
K -- approved --> L
K -- rejected --> X
L --> M[Deploy steps выполняются]
M --> N[Deployment status и history обновляются]Что именно защищает environment
Protection rules работают до того, как job, ссылающийся на environment, продолжит выполнение. Это не то же самое, что if: из Jobs, dependencies и conditions: if: решает, запускать job или step по данным workflow, а environment gate — это отдельная проверка GitHub на границе деплоя.
Основные встроенные rules:
- Required reviewers — один из указанных пользователей или teams должен approve job. Можно запретить self-review, чтобы автор запуска не мог сам пропустить production.
- Wait timer — задержка перед продолжением job. Диапазон в GitHub Docs: от 1 минуты до 43 200 минут, то есть 30 дней; это время не считается как billable runner time.
- Deployment branches and tags — allowlist refs, которым разрешено деплоить в environment. Например,
mainдляproduction,release/*для release branches или отдельные tag patterns. - Admin bypass policy — по умолчанию админы могут bypass protection rules, но для строгого production это можно запретить.
- Custom deployment protection rules — GitHub App получает событие и approve/reject деплой на основании внешней системы: change management, observability, incident status, security gate.
Практичная модель такая: staging обычно защищают слабее, production — сильнее. Например, staging может принимать push из main без approval, но production требует reviewer, запрещает self-review, разрешает только tags v* или branch main, а ещё использует concurrency, чтобы два production-деплоя не шли одновременно. Последняя часть уже относится к Deployment workflows, но environment — место, где этот workflow получает организационный контроль.
Environment secrets и variables
Environment secrets удобны для credentials, которые отличаются по целям деплоя: STAGING_SSH_KEY, PRODUCTION_SSH_KEY, cloud role, webhook token, kubeconfig replacement. Но лучше не плодить имена вида PROD_TOKEN, STAGING_TOKEN на уровне repository secrets, если можно хранить один и тот же DEPLOY_TOKEN в разных environments. Workflow остаётся одинаковым, меняется только target.
jobs:
deploy:
runs-on: ubuntu-24.04
environment: ${{ inputs.target }}
steps:
- run: ./deploy --target "$TARGET"
env:
TARGET: ${{ inputs.target }}
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
PUBLIC_ORIGIN: ${{ vars.PUBLIC_ORIGIN }}Environment variables читаются через vars, а не через env. Это хорошо подходит для несекретной конфигурации: PUBLIC_ORIGIN, REGION, SERVICE_NAME, SENTRY_ENVIRONMENT. Для секретов остаётся secrets. Правило безопасности из Permissions и GITHUB_TOKEN сохраняется: даже если environment gate настроен хорошо, permissions у job всё равно должны быть минимальными.
Важная тонкость: если workflow ссылается на environment, которого ещё нет, GitHub может создать environment с этим именем автоматически, но без настроенных protection rules и secrets. Для production лучше создать environment вручную в Settings → Environments или через API и заранее настроить политики. Имена environments не чувствительны к регистру, но в репозитории должны быть уникальны.
Branch/tag restrictions: не путать с event filters
Фильтры из Events и filters решают, запустится ли workflow вообще. Deployment branch/tag rule решает, может ли уже запущенный workflow деплоить в конкретный environment. Обычно нужны оба слоя.
on:
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
target:
type: choice
options: [staging, production]
jobs:
deploy:
runs-on: ubuntu-24.04
environment: ${{ github.ref_type == 'tag' && 'production' || 'staging' }}
steps:
- run: ./deploy.shЕсли production environment разрешает только tags v*, случайный ручной запуск с feature branch не пройдёт production gate даже при ошибке в YAML. Это полезная страховка от человеческих и конфигурационных ошибок.
Deployments и история
Когда job ссылается на environment, GitHub создаёт deployment object и deployment status objects: environment name, состояние job, URL, связанный commit, PR/branch, workflow logs. Это превращает Actions из «набора логов» в историю доставок: что сейчас активно в production, какой commit был выкачен, откуда он пришёл и где смотреть логи.
Если job нужен только для доступа к environment secrets/vars, но не является настоящим деплоем, можно указать deployment: false:
jobs:
smoke-with-prod-config:
runs-on: ubuntu-24.04
environment:
name: production
deployment: false
steps:
- run: ./scripts/smoke.sh
env:
API_TOKEN: ${{ secrets.READONLY_PROD_TOKEN }}Это не создаёт deployment object, но job всё равно получает environment secrets и variables после прохождения правил. Ограничение: custom deployment protection rules не совместимы с deployment: false, потому что им нужен deployment flow, который они approve или reject.
jobs:
deploy:
runs-on: ubuntu-24.04
environment: productionCustom rules: когда approval должен быть машинным
Manual approval хорошо работает для маленькой команды, но плохо масштабируется, если production можно выпускать десятки раз в день. Custom deployment protection rule — это GitHub App, который подписывается на deployment protection rule event, получает payload, проверяет внешнее условие и отправляет approval или rejection обратно в GitHub.
Типичные внешние gates: нет активного инцидента в ServiceNow, error rate в Datadog ниже порога, canary в Honeycomb выглядит нормально, Sentry release health не просел, change request уже одобрен. Это не замена тестам из CI pipeline, а последний контекстный gate перед средой. Тесты отвечают «артефакт собран и проверен?», protection rule отвечает «сейчас можно катить именно сюда?».
Частые ошибки
Первая ошибка — считать environment просто способом хранить secrets. Тогда production secrets становятся доступны любому workflow, который умеет сослаться на production. Нужны reviewers, branch/tag restrictions и аккуратные permissions.
Вторая — требовать approval на каждом staging-деплое. В итоге команда начинает bypass rules или отключает gates. Для staging лучше автоматизировать, а ручную проверку оставить на production, regulated environments или опасные операции.
Третья — смешивать promotion и rebuild. Если production job заново собирает код после staging, история deployments говорит «в production ушёл commit X», но не гарантирует, что это тот же artifact. Обычно надёжнее собрать artifact в CI, проверить его, а потом передавать дальше через Artifacts и reports и deploy jobs.
See also
- Deployment workflows — паттерны deploy after CI, manual
workflow_dispatch, promotion, rollback и productionconcurrency. - Variables, env и secrets — разница между
env,vars,secretsи областью видимости. - Permissions и GITHUB_TOKEN — least privilege для job, который деплоит.
- Events и filters — запуск workflow по branches, tags, manual и schedule.
- Artifacts и reports — как передавать проверенный build output в deploy job.
- Cloud deploy через OIDC — деплой в облака без долгоживущих cloud secrets.
- Monitoring и troubleshooting — где искать run logs, deployment statuses и причины pending/rejected jobs.
Внешние справки: GitHub Docs по deployment environments, managing environments, deploying to an environment, deployments and environments reference, reviewing deployments, custom protection rules, secure use и deployment history.
Источники
- Managing environments for deployment - GitHub Docs
- Deployments and environments - GitHub Docs
- Reviewing deployments - GitHub Docs
- Deploying to a specific environment - GitHub Docs
- Secure use reference - GitHub Docs
- Creating custom deployment protection rules - GitHub Docs
- Viewing deployment history - GitHub Docs
