Робочі процеси CI

Робочі процеси GitHub Actions, які автоматизують перевірку PR, додавання міток та інші процеси CI/CD.

Щодо робочих процесів та (більшості) їхніх допоміжних скриптів дивіться теки workflow і scripts у .github

Мітки PR

Наступні робочі процеси працюють разом для автоматичного керування мітками для затвердження PR:

ФайлТригерПривілеї
pr-review-trigger.ymlpull_request_reviewМінімальні (no secrets)
pr-approval-labels.ymlpull_request_target, workflow_run, scheduleТокен GitHub App для редагування міток та читання на рівні org/team
blog-publish-labels.ymlschedule (daily 7 AM UTC)App token + SLACK_WEBHOOK_URL secret

Управління мітками

  • missing:docs-approval — додається, коли очікується затвердження з боку команди docs-approvers; вилучається одразу після отримання затвердження.
  • missing:sig-approval — додається, коли очікується затвердження з боку команди SIG (визначається змінами у файлах та .github/component-owners.yml); вилучається одразу після отримання затвердження від членів SIG або коли компоненти SIG не зачіпаються.
  • ready-to-be-merged — додається, коли отримані всі необхідні затвердження; в іншому випадку вилучається. Для PR, що містять мітку PUBLISH_DATE_LABELS (зараз: blog), ця мітка також обмежується датою публікації, знайденій в змінених файлах.

Дата публікації

Скрипт сканує кожен змінений файл на наявність рядка, що починається з date: (зазвичай з front matter вмісту Markdown). Якщо він знаходить дату в майбутньому, мітка ready-to-be-merged утримується до настання цієї дати (UTC). Це допомагає запобігти злиттю вмісту до запланованої дати публікації.

Перевірка застосовується до PR, що містять будь-яку мітку, зазначену у змінній середовища PUBLISH_DATE_LABELS, яка задається у кожному файлі YAML робочого процесу (наразі: blog). Додавання мітки розширює дію перевірки на інші типи PR.

Якщо PR містить кілька файлів з різними датами, мітка блокується за останньою датою — весь вміст повинен бути готовий до злиття.

Режими роботи скрипту

Скрипт pr-approval-labels.sh обробляє один PR (встановлюється через змінну середовища PR). Він викликається файлом pr-approval-labels.yml при подіях PR та файлом blog-publish-check.sh у пакетному режимі.

Скрипт blog-publish-check.sh відповідає за пакетну обробку: він перевіряє всі відкриті PR, що містять будь-яку мітку PUBLISH_DATE_LABELS, і запускає pr-approval-labels.sh для кожного з них. Використовується тригером blog-publish-labels.yml schedule (щодня о 7 ранку за UTC), тому PR, дата публікації якого настає вночі, автоматично отримує ready-to-be-merged без необхідності нового коміту.

Для чого два робочі процеси?

Подія GitHub pull_request_review немає опції _target. Це означає, що робочий процес запускається отриманням рецензування на fork PR і виконується в контексті форку і не має доступу до секретів базового репозиторію.

Щоб обійти це обмеження, система використовує workflow_run chaining pattern:

  1. pr-review-trigger виконується для кожної рецензії (затвердження чи відхилення). Відбувається збереження номеру PR у вигляді артефакту — секрети не потрібні.
  2. pr-approval-labels запускається через workflow_run (коли попередній робочий процес відпрацював). Він запускається в контексті базового репозиторію з повним доступом до GitHub App token, завантажує артефакт та оновлює міти.

У разі змін вмісту (opened, reopened, synchronize), pr-approval-labels запускається безпосередньо через pull_request_target.

sequenceDiagram
    participant R as Reviewer
    participant GH as GitHub
    participant T as pr-review-trigger
    participant L as pr-approval-labels

    R->>GH: Submits review (approve/request changes/dismiss)

    Note over GH: pull_request_review event

    GH->>T: Trigger (fork context, no secrets)
    T->>T: Save PR number as artifact
    T->>GH: Upload artifact, workflow completes

    Note over GH: workflow_run event (completed)

    GH->>L: Trigger (base repository context, with secrets)
    L->>L: Download PR number artifact
    L->>L: Run pr-approval-labels.sh
    L->>GH: Add/remove labels

Модель безпеки

  • pr-review-trigger: спеціально є мінімальним — немає секретів, прав доступу й так далі. Ігнорує коментарі review.state == "commented", оскільки коментарі на впливають на затвердження.
  • pr-approval-labels: запускається з токеном GitHub App (OTELBOT_DOCS_CLIENT_ID / OTELBOT_DOCS_PRIVATE_KEY), що має права на читання на рівні org/team та редагує мітки PR. Використання pull_request_target та workflow_run дозволяє бути впевненим, що виконання відбувається у контексті базового репозиторію.
  • blog-publish-labels: запускається за розкладом з токеном GitHub App та секретом SLACK_WEBHOOK_URL. Завжди виконується у довіреному контексті базового репозиторію (події розкладу не мають варіанту для форків).

Мітки публікацій у блозі

Робочий процес blog-publish-labels.yml запускається щодня о 7:00 за UTC. Він виконує скрипт blog-publish-check.sh, який перебирає всі відкриті PR із міткою blog і для кожного з них викликає скрипт pr-approval-labels.sh. Коли до будь-якого з них застосовується новий статус ready-to-be-merged, надсилається сповіщення у Slack. Ви також можете запустити його вручну за допомогою workflow_dispatch із вхідним параметром force_notify, щоб надіслати тестове сповіщення у Slack. Коли force_notify має значення true, крок позначення міткою повністю пропускається («сухий запуск») — надсилається лише тестовий вміст повідомлення у Slack.

Файл робочого процесуТригерНеобхідні секрети
blog-publish-labels.ymlschedule (щодня о 7:00 за UTC), workflow_dispatch (ручне тестування через force_notify)OTELBOT_DOCS_PRIVATE_KEY, SLACK_WEBHOOK_URL

Сповіщення в Slack надсилається лише тоді, коли мітка переходить з відсутньої до присутньої під час цього запуску — повторні щоденні запуски для вже промаркованого PR не надсилають повторні сповіщення. При ручному запуску робочого процесу встановіть force_notify у true, щоб надіслати одноразове тестове сповіщення (мітки не застосовуються), щоб ви могли перевірити форматування Slack.

Налаштування вебхука Slack

Робочий процес використовує Slack Workflow Builder webhook trigger, що дозволяє не інженерам керувати форматом повідомлення без зміни коду робочого процесу.

Створення вебхука:

  1. У Slack: Інструменти → Workflow Builder → Новий робочий процес → Почати з нуля

  2. Виберіть тригер: Webhook

  3. Оголосіть одну змінну — назва: pr_list, тип: Текст

  4. Додайте крок: Надіслати повідомлення до потрібного каналу, з тілом:

    :newspaper: *Blog posts ready to publish*
    
    The following PRs have reached their publish date and all required
    approvals — they are ready to be merged:
    
    {{pr_list}}
    
    Have a great day! :sunny:
    

    Далі натисніть Додати кнопку і налаштуйте:

    • Назва: Review and merge
    • Колір: Primary (зелений)
    • Дія: Відкрити посилання
    • URL: https://github.com/open-telemetry/opentelemetry.io/issues?q=is%3Apr+state%3Aopen+label%3Ablog+label%3Aready-to-be-merged
  5. Опублікуйте робочий процес і скопіюйте URL вебхука

  6. Додайте його до репозиторію: Налаштування → Секрети та змінні → Дії → Новий секрет репозиторію, назва: SLACK_WEBHOOK_URL

Payload, що надсилається робочим процесом:

{
  "pr_list": "• #123: Add blog post: OTel 1.0 — https://github.com/.../pull/123\n• #456: Announce: new SIG — https://github.com/.../pull/456"
}

Кожен PR є пунктом списку з його заголовком та URL. Slack автоматично створює посилання для простих URL. Кілька PR, позначених в один день, обʼєднуються в одне повідомлення — один виклик вебхука незалежно від кількості готових PR.

sequenceDiagram
    participant GH as GitHub
    participant W as blog-publish-labels
    participant B as blog-publish-check.sh
    participant L as pr-approval-labels.sh
    participant S as Slack

    Note over GH: schedule event (daily, 7 AM UTC)

    GH->>W: Trigger (base repository context, with secrets)
    W->>B: Run blog-publish-check.sh
    B->>GH: Query open PRs with PUBLISH_DATE_LABELS labels
    GH-->>B: List of PRs
    loop Each PR
        B->>L: Run pr-approval-labels.sh (PR=number)
        L->>GH: Add/remove labels
    end
    alt Any PR newly labeled ready-to-be-merged
        W->>S: POST Slack notification with PR links
    end

Директиви виправлення PR

Файл pr-actions.yml дозволяє учасникам запускати певні fix скрипти шляхом додавання коментарів до PR:

  • /fix запускає npm run fix.
  • /fix:<name> запускає npm run fix:<name> (наприклад, /fix:format).
  • /fix:all переадресує на /fix оскільки семантика команд була змінена (#9291).
  • /fix:ALL переадресує на fix:all, тож супровідники можуть запускати fix:all.

Директива повинна бути першим рядком коментаря; будь-які наступні рядки ігноруються, тож ви можете додати пояснення після неї. Сам робочий процес запускається на будь-який коментар, тіло якого починається з /fix (наприклад, /fixup потрапляє в конвеєр і отримує зворотний звʼязок про недійсну директиву, тоді як коментар, що починається з пробілу, або з /fix лише на пізнішому рядку, не запускає робочий процес взагалі).

Вони запускаються у чотириступеневому конвеєрі:

  1. ack (надійний): як тільки отримує вказівку, відповідає коментарем 🔄 «у процесі виконання», що містить посилання на коментар із вказівкою та на сам запуск.
  2. generate-patch (ненадійний): перевіряє гілку PR, запускає команду виправлення, очищає кеш посилань і завантажує артефакт латки (site.patch), до 1024 КБ.
  3. apply-patch (надійний): викликає робочий процес reusable-apply-patch.yml — отримується з основної гілки, ніколи не з PR, який застосовує латку за допомогою токена GitHub App і додає коміт у гілку PR. Пропускається, якщо команда не внесла змін.
  4. report (надійний): замінює підтвердження на остаточний результат, коли це можливо, або публікує новий коментар з результатом, коли підтвердження не існує, наприклад, для закритих PR. Кожна директива зазвичай відповідає одному коментарю, який посилається на директиву та на запуск, який її створив. Це охоплює всі директиви, які запускають робочий процес, включаючи недійсні директиви (такі як /fixup або /fix please), бездіяльні запуски та помилки, що виникають до створення будь-якого латки.

Директиви виконуються лише для відкритих PR (включаючи чернетки PR): у закритому або обʼєднаному PR команда виправлення ніколи не запускається, а завдання звіту пояснює причину. Стан PR береться з корисного навантаження тригера, тому жоден виконавець не витрачається на саме виправлення.

Конвеєр працює лише в канонічному репозиторії open-telemetry, де існують облікові дані бота. Fork PR працюють нормально, події issue_comment спрацьовують у базовому репозиторії, але робочий процес пропускає себе всередині форків.

Директиви дотримуються семантики «останнього переможного варіанту»: новий коментар /fix у PR скасовує поточний запуск цього PR (який все одно видає результат ⚠️), оскільки паралельні запуски виправлення на одній гілці не мають сенсу — другий push все одно завершиться невдачею, щойно гілка буде переміщена.

Парсер директив знаходиться у scripts/gh/pr-fix/, генерування латок — у дії npm-script-patch, а коментарі з визнанням та результатами створюються за допомогою scripts/gh/patch-report/; всі вони проходять модульне тестування за допомогою команди npm run test:local-tools.

Прибирання

Робочий процес housekeeping.yml запускається для затверджених команд виправлення — зазвичай fix-and-test:all, або скрипт npm, що запускається вручну (лише для супровідників) — щодня о 21:37 за UTC, приблизно через 12 годин після виконання інших щоденних автоматизованих завдань, і публікує всі отримані зміни у вигляді PR. Це другий виклик дій з повторного використання латок, а також потік планового обслуговування, що став поштовхом для створення #6592.

Він запускає триступеневий конвеєр:

  1. generate-patch: запускає команди прибирання через дію npm-script-patch і завантажує зміни як артефакт латки. На відміну від конвеєра /fix, весь запуск є надійним: тригери розкладу та виклику завжди виконують код зі стандартної гілки. Невдала команда призводить до невдачі завдання, але будь-які виправлення, які вона створила, все одно публікуються з попередженням про часткові результати в тілі PR.
  2. publish-patch: викликає робочий процес reusable-patch-pr.yml, аналог reusable-apply-patch.yml для процесів виклику без контексту PR, який примусово робить push латки в стабільну гілку otelbot/housekeeping, відтворювану з main на кожному запуску, і відкриває для неї PR, якщо він ще не відкритий. Таким чином, одночасно існує не більше одного PR для прибирання, завжди містить останні результати. Будь-які коміти, направлені в гілку, вручну або через /fix, будуть перезаписані наступним запуском, тому зливайте PR негайно, якщо ви робити push комітів в нього. Пропускається, коли команда не створила змін, залишаючи будь-який відкритий PR для прибирання без змін. Автоматичне злиття безпечне для PR прибирання за умови, що застарілі схвалення скасовуються при push комітів: необхідні огляди залишаються контролем над контентом, отриманим від машини та інтернету, навіть при примусових pushes.
  3. report-failure: створює тікет відстеження у разі невдачі через звітність про невдачі робочого процесу; коли виправлення були опубліковані, тікет посилається на PR для прибирання.

Автоматичне злиття локалізацій

Робочий процес locale-auto-merge.yml дозволяє кураторам локалі вмикати функцію GitHub auto-merge для PR, що стосуються виключно локалі, за допомогою директиви /auto-merge (або /auto-merge:enable / /auto-merge:disable) в коментарі до PR —правила розміщення дивіться у допоміжному файлі README. Він працює як бот DOCS, який має привілеї, необхідні для перемикання опції «обʼєднати, коли буде готово» в умовах захисту гілки; CODEOWNERS та необхідні перевірки залишаються жорстким барʼєром для обʼєднання.

Тонкий робочий процес делегує завдання помічнику в scripts/gh/locale-auto-merge/, який перед дією застосовує два обмеження: кожен змінений файл повинен належати локалі, а коментатор повинен бути членом команди docs-<loc>-maintainers для кожної локалі, якої торкається PR. Правила придатності та авторизації помічника (і як їх перевірити локально) знаходяться в його README; його модульні та інтеграційні тести виконуються за допомогою npm run test:local-tools. Використання для учасників описано в посібнику з локалізації.

Гілки інтеграції специфікацій

Запланований робочий процес specs-integration.yml керує циклом оновлення сайту для вихідних репозиторіїв специфікацій (які auto-update-versions.yml тому виключає). Він виконує одне матричне завдання для кожного вихідного репозиторію: між випусками кожне завдання відстежує невипущені зміни з вихідного репозиторію через чернетковий PR («гілку інтеграції»); щойно вихідний репозиторій випускає нову версію, воно фіналізує цю гілку та PR у PR випуску.

Матричне завданняВихідний репозиторійSlag гілки
otelopentelemetry-specificationspec
semconvsemantic-conventionssemconv

Кожне завдання делегує крок «вибір режиму, версії та гілки» спільному помічнику scripts/gh/specs/pick-branch.mjs. Помічник:

  • Обирає MODE запуску: dev, поки версія, зафіксована в main, є останнім випуском upstream, та release, коли існує новіший випуск.
  • Записує MODE, VERSION та BRANCH у $GITHUB_ENV для наступних кроків.
  • Відкриває відстежувальне питання (мітка <slug>-integration-warning, дедуплікація) при виявленні проблем, таких як кілька застарілих інтеграційних гілок.

Останній крок scripts/gh/specs/create-or-finalize-pr.mjs створює або фіналізує PR відповідно до MODE: у режимі dev він відкриває чернетковий інтеграційний PR, якщо його не існує; у режимі release він створює або фіналізує PR випуску. Він перезаписує лише текст PR, який створила автоматизація: заголовок або тіло, відредаговані супровідником, залишаються без змін.

Режими запуску

Обидва помічники автоматично обирають між режимом dry-run та write і виводять банер [mode], пояснюючи свій вибір:

КонтекстСтандартна поведінкаПеревизначення
GitHub Actionswritepass --dry-run
Local (anywhere else)dry-runpass --no-dry-run

Локально, dry-run все ще виконує всі команди git/gh лише для читання (щоб перевірка дедуплікації питань виконувалася), але пропускає записи. З --no-dry-run помічники використовують ваші локальні облікові дані gh; якщо GITHUB_ENV не встановлено, pick-branch виводить лише MODE/VERSION/BRANCH в stdout — експортуйте їх для передачі в локальний запуск create-or-finalize-pr. Спробуйте:

scripts/gh/specs/pick-branch.mjs --spec otel
scripts/gh/specs/pick-branch.mjs --spec semconv --no-dry-run
scripts/gh/specs/create-or-finalize-pr.mjs --help

Чиста логіка знаходиться в index.mjs кожного помічника і покривається файлами *.test.mjs у тій же теці (npm run test:local-tools для їх запуску).

Повідомлення про помилки робочого процесу

reusable-report-failure.yml відкриває (або коментує) відстежувану проблему, коли робочий процес, що викликає, не вдається. Як його підключити, необовʼязкові вхідні дані та поведінка контексту процесу, що викликає, документуються в заголовку файлу робочого процесу; логіка проблеми знаходиться в scripts/gh/report-failure/ (npm run test:local-tools).

Інші робочі процеси

Репозиторій також містить кілька інших робочих процесів:

Робочий процесПризначення
check-links.ymlПеревірка посилань за допомогою htmltest, а також пілотний проєкт Lychee без блокування
check-text.ymlПеревірка термінології Textlint
check-i18n.ymlПеревірка локалізації front matter
check-spelling.ymlПеревірка орфографії
test.ymlЗапуск тестів (виключає test:base)
auto-update-registry.ymlАвтоматичне оновлення версій пакетів реєстру
auto-update-versions.ymlАвтоматичне оновлення версій компонентів OTel (крім репозиторіїв специфікацій)
build-dev.ymlЗбірка для розробки та попередній перегляд
lint-scripts.ymlПеревірка скриптів за допомогою ShellCheck
label-manager.ymlКерування мітками PR (мітки компонентів та процес затвердження)
component-owners.ymlПризначення рецензентів на основі власності на компоненти
Востаннє змінено July 12, 2026: [uk] Ukrainian documentation for OpenTelemetry (0301c8f3)