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

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

Environment files `GITHUB_ENV`, `GITHUB_OUTPUT`, `GITHUB_PATH`, `GITHUB_STEP_SUMMARY`, группировка логов, warnings/errors, masking и удобные Markdown-отчеты в run summary.

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

Workflow commands и summaries

Environment files `GITHUB_ENV`, `GITHUB_OUTPUT`, `GITHUB_PATH`, `GITHUB_STEP_SUMMARY`, группировка логов, warnings/errors, masking и удобные Markdown-отчеты в run summary.

Workflow commands и summaries

Workflow commands — это канал связи между вашим run-скриптом и GitHub Actions runner. Обычный echo пишет строку в лог, а специально отформатированный echo или запись в environment file меняет состояние job: добавляет env-переменную, задаёт output, расширяет PATH, создаёт annotation или пишет Markdown в summary.

Их удобно считать тонким слоем «служебного протокола» поверх shell. Для данных между steps чаще используются environment files: GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH, GITHUB_STEP_SUMMARY. Для читаемости логов — команды ::group::, ::warning::, ::error::, ::add-mask:: и ::stop-commands::.

Environment files: запись сейчас, эффект позже

Каждая из переменных GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH и GITHUB_STEP_SUMMARY содержит путь к временному файлу на runner. Вы не редактируете YAML во время выполнения; вы дописываете строки в этот файл, а runner считывает их после завершения step.

Самая важная практическая деталь: step, который пишет в GITHUB_ENV или GITHUB_PATH, сам ещё не видит новое значение. Его увидят последующие steps в том же job.

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Compute build metadata
        run: |
          echo "BUILD_SHA=${GITHUB_SHA::7}" >> "$GITHUB_ENV"
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"
          echo "Inside same step: BUILD_SHA=$BUILD_SHA"

      - name: Use build metadata
        run: |
          echo "Later step: BUILD_SHA=$BUILD_SHA"
          command -v my-tool || true

В первом step BUILD_SHA ещё пустой, если он не был задан раньше. Во втором step он уже доступен как обычная env-переменная. Это отличается от Variables, env и secrets, где env: задаётся декларативно в YAML, и от Contexts и expressions, которые вычисляются в выражениях ${{ ... }} до или во время планирования частей workflow.

Есть ограничения. Нельзя перезаписывать стандартные переменные GITHUB_* и RUNNER_*; GITHUB_ENV также нельзя использовать для установки NODE_OPTIONS. Если нужно передать значение в другой job, GITHUB_ENV не подходит: job изолирован. Для этого нужны Step outputs и job outputs, artifacts или внешний storage.

GITHUB_OUTPUT: когда значение должно стать API step

GITHUB_OUTPUT задаёт outputs текущего step. Чтобы потом сослаться на них, у step должен быть id.

- name: Detect package manager
  id: pkg
  run: |
    if [ -f pnpm-lock.yaml ]; then
      echo "manager=pnpm" >> "$GITHUB_OUTPUT"
    elif [ -f package-lock.json ]; then
      echo "manager=npm" >> "$GITHUB_OUTPUT"
    else
      echo "manager=unknown" >> "$GITHUB_OUTPUT"
    fi

- name: Install
  if: ${{ steps.pkg.outputs.manager != 'unknown' }}
  run: echo "Will install with ${{ steps.pkg.outputs.manager }}"

Такой output хорош для короткого структурного значения: версия, путь, флаг, имя окружения, результат detection step. Для файлов он плох: кладите coverage, screenshots, bundles и test reports в Artifacts и reports. Для ускорения зависимостей используйте Dependency cache, а не outputs.

Многострочные значения записываются через delimiter-синтаксис:

{
  echo 'REPORT<<EOF'
  npm test -- --reporter=dot || true
  echo 'EOF'
} >> "$GITHUB_OUTPUT"

Delimiter не должен встретиться отдельной строкой внутри значения. Если содержимое произвольное, безопаснее записать его в файл и загрузить как artifact.

GITHUB_STEP_SUMMARY: важное отдельно от шумных логов

Логи нужны для диагностики, но читать их после каждого CI run неудобно. GITHUB_STEP_SUMMARY позволяет добавить Markdown в summary страницы workflow run. Это место для короткого результата: что проверялось, сколько тестов прошло, куда задеплоено, какой artifact скачать.

- name: Test and summarize
  run: |
    echo "## CI summary" >> "$GITHUB_STEP_SUMMARY"
    echo "" >> "$GITHUB_STEP_SUMMARY"
    echo "| Check | Result |" >> "$GITHUB_STEP_SUMMARY"
    echo "| --- | --- |" >> "$GITHUB_STEP_SUMMARY"

    if npm test; then
      echo "| Tests | Passed |" >> "$GITHUB_STEP_SUMMARY"
    else
      echo "| Tests | Failed |" >> "$GITHUB_STEP_SUMMARY"
      exit 1
    fi

Summary поддерживает GitHub Flavored Markdown. Файл GITHUB_STEP_SUMMARY уникален для каждого step; когда job заканчивается, summaries steps группируются в job summary. Если summaries пишут несколько jobs, на странице workflow они упорядочиваются по времени завершения jobs, а не по порядку объявления в YAML.

Практический стиль: summary должен отвечать на вопрос «что мне делать дальше?». Например: «tests failed, смотри artifact playwright-report», «deploy в staging прошёл, URL такой-то», «cache miss, job занял 6m 12s». Не дублируйте туда весь лог. У summary есть лимиты: максимум 1 MiB на step и до 20 step summaries, показываемых на job. Если upload summary не удался из-за размера, GitHub создаст error annotation, но сам job от этого не станет failed.

Логи: groups, annotations и debug

Для длинных install/build steps используйте группы. Это не меняет выполнение, но резко улучшает чтение лога.

- name: Build
  run: |
    echo "::group::Install dependencies"
    npm ci
    echo "::endgroup::"

    echo "::group::Run tests"
    npm test
    echo "::endgroup::"

::notice::, ::warning:: и ::error:: создают annotations. Их можно привязать к файлу и строке:

echo "::warning file=src/config.ts,line=12,title=Deprecated config::USE_LEGACY_API still enabled"
echo "::error file=src/app.test.ts,line=44,title=Flaky test::Expected status 200, got 500"

Annotation полезна, когда скрипт сам нашёл проблему и может указать на конкретное место. Но ::error:: — это ещё не exit 1. Если step должен упасть, завершайте команду ненулевым кодом.

::debug:: виден только при включённом debug logging через secret ACTIONS_STEP_DEBUG=true. Это хорошее место для дополнительной диагностики, которую не хочется показывать в обычном run.

Masking и stop-commands

::add-mask::{value} просит runner редактировать это значение в последующих логах. Ключевое слово — «последующих»: маску надо зарегистрировать до того, как значение напечатано или использовано в другой workflow command.

- name: Generate temporary token
  run: |
    token="temp-token-from-script"
    echo "::add-mask::$token"
    echo "Token generated and masked"

Не полагайтесь на masking как на полноценную модель безопасности. Не печатайте secrets намеренно, не кладите их в cache или artifacts, не выводите целиком contexts вроде github. Это та же логика, что и в Secure use и threat model: masking снижает ущерб от случайного вывода, но не делает опасный workflow безопасным.

::stop-commands::{token} временно отключает распознавание workflow commands в stdout. Это нужно, когда вы печатаете произвольный скрипт, JSON или лог внешнего инструмента, где случайно может встретиться строка вида ::warning::....

marker=$(uuidgen)
echo "::stop-commands::$marker"
cat generated-script.sh
echo "::$marker::"

Marker должен быть уникальным для run. Иначе кто-то может раньше времени снова включить команды в выводе.

Рабочая эвристика

Используйте GITHUB_ENV, когда значение нужно как env-переменная в следующих steps того же job. Используйте GITHUB_OUTPUT, когда значение является контрактом step и должно читаться через steps.<id>.outputs или подниматься в job outputs. Используйте GITHUB_PATH, когда step установил CLI в нестандартную директорию. Используйте GITHUB_STEP_SUMMARY, когда результат важнее подробного лога.

А для человека, который открывает failed run утром, оставляйте короткий summary, аккуратные groups и точные annotations. Это не косметика: это эксплуатационная часть нормального CI pipeline.

See also

  • Variables, env и secrets — где проходит граница между env, vars, secrets и contexts.
  • Step outputs и job outputs — как поднимать outputs из step в job и передавать их через needs.
  • Artifacts и reports — когда результатом является файл или отчёт, а не короткая строка.
  • Dependency cache — почему cache не является handoff-механизмом между steps или jobs.
  • CI pipeline — где summaries и annotations помогают быстро понять статус проверки.
  • Secure use и threat model — почему masking не заменяет least privilege и аккуратную работу с secrets.
  • pull_request_target и untrusted PR — где случайный вывод и untrusted scripts становятся security-проблемой.
Быстрое повторение #rc-1

Что меняется, когда run-скрипт пишет строку в environment file вроде GITHUB_ENV, а не просто делает обычный echo в лог?

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

Runner считывает этот временный файл после завершения step и меняет состояние job: env-переменные, outputs, PATH или summary. Обычный echo без такого файла только пишет строку в лог.

Источники

  1. Workflow commands for GitHub Actions - GitHub Docs
  2. Variables reference - GitHub Docs