idea_world_labDEV JOURNAL
четверг, 25 июня 2026 г.

Qwen PR Review Workflow структура и запись улучшений

Дата создания: 25 июня 2026 г.

Цель

Этот документ описывает процесс взятия workflow обзора PR на основе qwen-code и его настройки под текущий репозиторий.

Суть этой задачи не просто в том, чтобы workflow завершился успешно, а в том, чтобы результаты обзора, созданные Qwen, оставались в виде реального комментария к GitHub PR.

Предыстория

Этот репозиторий также использует внешние боты для обзора, такие как CodeRabbit, Sourcery, Qodo. Однако отдельно берётся workflow qwen-code, который запускается через путь OpenRouter, и экспериментируется процесс, при котором для каждого PR оставляется обзор на основе Qwen.

Сначала из‑за проблем с затратами поток AI PR Review API был остановлен. Затем, используя бесплатный уровень OpenRouter, можно воспользоваться openai/gpt-oss-120b:free, поэтому README был изменён в сторону повторной попытки через этот путь.

Исходная структура workflow

Целевой файл:

.github/workflows/qwen-code-pr-review.yml

Исходное имя рабочего процесса:

🧐 Qwen Pull Request Review

Основной триггер:

on:
  pull_request_target:
    types: ['opened']
  pull_request_review_comment:
    types: ['created']
  pull_request_review:
    types: ['submitted']
  workflow_dispatch:
    inputs:
      pr_number:
        required: true
        type: 'number'

job условие было настроено на выполнение в следующих случаях.

  • workflow_dispatch ручной запуск
  • событие opened у pull_request_target, и автор PR является OWNER, MEMBER или COLLABORATOR
  • в комментарии обзора PR содержится @qwen /review
  • в тексте обзора PR содержится @qwen /review

Основные шаги workflow были следующими.

  1. checkout кода PR
  2. сбор заголовка PR, описания, изменённых файлов, информации diff
  3. запуск QwenLM/qwen-code-action
  4. внутри prompt заставить Qwen создать обзор и указать gh pr comment для публикации комментария

Наблюдаемая проблема

Наблюдал workflow в реальном времени на PR #5.

PR:

https://github.com/yyeongjin/idea_world/pull/5

PR успешно создан, и следующие боты отреагировали.

  • CodeRabbit
  • Sourcery
  • Qodo

Рабочий процесс Qwen также выполнился при событии pull_request_target.

Наблюдаемый запуск:

workflow: 🧐 Qwen Pull Request Review
event: pull_request_target
conclusion: success

Но в реальном PR комментарий обзора от Qwen не оставлен.

Если посмотреть журнал workflow, то Qwen после написания обзора не выполняет реальный вызов инструмента, а выводит текст с инструкцией в стиле JSON следующего вида.

{"tool":"write_file", ...}
{"tool":"run_shell_command", ...}

То есть сам workflow завершился успешно, но ожидаемый пользователем результат — «создание комментария к PR» — не был выполнен.

Сводка причин

Проблема заключалась в том, что структура делегировала написание комментариев Qwen.

Исходный запрос инструктировал Qwen выполнить следующее напрямую.

1. write_file("review.md", "<your detailed review feedback here>")
2. gh pr comment $PR_NUMBER --body-file review.md --repo $REPOSITORY

Однако при реальном выполнении Qwen не выполнил эту задачу вызовом инструмента, а вывел требуемую задачу только в виде текста.

Поэтому, если модель не вызывает инструмент правильно, даже если workflow завершится успешно, в PR не останется никаких комментариев.

Дополнительные выявленные проблемы структуры

В условиях задания workflow был включён событие issue_comment.

(github.event_name == 'issue_comment' && ... contains(github.event.comment.body, '@qwen /review') ...)

Однако в триггере on: не было issue_comment.

То есть, даже если оставить комментарий @qwen /review в обсуждении PR, workflow вообще не запускался.

Кроме того, триггер pull_request_target реагировал только на opened.

pull_request_target:
  types: ['opened']

Поэтому событие synchronize, когда в ветку PR пушится новый коммит, не запускалось автоматически.

Улучшения

Не поручать модели написание комментариев в GitHub, а сделать так, чтобы шаг GitHub Actions отвечал за написание комментариев.

После улучшения разделение ответственности выглядит следующим образом.

Qwen
  -> создать только текст Markdown‑обзора

GitHub Actions
  -> сохранить вывод Qwen в файл
  -> оставить комментарий к PR с помощью gh pr comment

Таким образом, даже если Qwen выводит вызов инструмента в виде текста, по крайней мере на этапе workflow можно получить qwen_result и оставить комментарий.

Изменения

1. trigger усиление

Существующий:

pull_request_target:
  types: ['opened']

Изменения:

pull_request_target:
  types: ['opened', 'reopened', 'synchronize']
issue_comment:
  types: ['created']

Цель:

  • Выполнять при открытии нового PR
  • Выполнять при повторном открытии PR
  • Выполнять при появлении нового коммита в ветке PR
  • Выполнять, когда в обсуждении PR оставляют @qwen /review

Дополнительные наблюдения:

Только усиление триггера on: было недостаточно. На самом деле, когда в ветку PR был запушен новый коммит, запуск pull_request_target был создан, но условие задачи всё ещё разрешало только github.event.action == 'opened', поэтому запуск завершился со статусом skipped.

Следовательно, условие задачи также нужно изменить, как показано ниже.

(github.event.action == 'opened' ||
 github.event.action == 'reopened' ||
 github.event.action == 'synchronize')

2. Назначение id шагу Qwen

Изменения:

- name: 'Run Qwen PR Review'
  id: 'qwen_review'

Цель:

Для того, чтобы в последующем шаге прочитать следующий вывод.

steps.qwen_review.outputs.qwen_result

3. изменение ответственности prompt

Исходный запрос напрямую указывал Qwen создавать файлы и писать комментарии к PR.

После изменения запрос инструктирует Qwen возвращать только текст обзора в формате Markdown в качестве окончательного ответа.

Return the review markdown text as your final answer.
Do not call write_file.
Do not call gh pr comment.
Do not output JSON tool-call instructions.
A later GitHub Actions step will post your final answer as a PR comment.

Намерение:

  • Сократить количество проблем, когда Qwen выводит JSON вызова инструмента.
  • Перенести ответственность за написание комментариев с модели на шаг рабочего процесса.

4. Добавление шага публикации вывода Qwen в виде комментария PR

Добавленный шаг:

- name: 'Post Qwen PR Review'
  if: |-
    ${{ always() && steps.qwen_review.outputs.summary != '' }}
  env:
    GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
    PR_NUMBER: '${{ steps.get_pr.outputs.pr_number || steps.get_pr_comment.outputs.pr_number }}'
    REPOSITORY: '${{ github.repository }}'
    QWEN_RESULT: '${{ steps.qwen_review.outputs.summary }}'
  run: |-
    {
      echo "## Qwen PR Review"
      echo
      printf '%s\n' "$QWEN_RESULT"
    } > qwen-review.md
    gh pr comment "$PR_NUMBER" --body-file qwen-review.md --repo "$REPOSITORY"

Намерение:

  • Если вывод Qwen не пустой, обязательно оставлять комментарий к PR.
  • За написание комментария отвечает детерминированный шаг, использующий GITHUB_TOKEN и gh pr comment.

Дополнительные наблюдения:

Сначала я неправильно считал имя вывода как steps.qwen_review.outputs.qwen_result. На самом деле, проверив action.yml в QwenLM/qwen-code-action, обнаружилось, что внутри composite‑шаг создаёт qwen_result, но имя вывода, публикуемое наружу из действия, — summary.

outputs:
  summary:
    value: ${{ steps.qwen_run.outputs.qwen_result }}

Так что последующий шаг комментария должен читать steps.qwen_review.outputs.summary. Если читать qwen_result, то даже если Qwen корректно создал тело обзора, шаг post будет пропущен.

Важные замечания

Рабочий процесс pull_request_target запускается не на основе файла workflow из ветки PR, а на основе файла workflow из базовой ветки.

Поэтому просто внесение изменений в workflow в ветке PR не изменит поведение pull_request_target текущего PR.

Чтобы действительно применить изменения, необходимо одно из следующего.

  1. Сначала применить изменение workflow в main.
  2. Затем в следующем PR оставить @qwen /review или выполнить новый commit и push, чтобы запустить изменённый workflow.

В этой задаче изменение workflow сначала будет применено в main, а затем в PR #5 будет повторно запущен Qwen review, чтобы проверить, будет ли действительно создан комментарий.

Требования к безопасности

В документации workflow не следует записывать такие чувствительные данные, как API‑ключ, URL конечной точки, базовый URL провайдера.

В журналах GitHub Actions следующие значения также должны быть замаскированы как секреты.

OPENAI_API_KEY
OPENAI_BASE_URL
OPENAI_MODEL
GITHUB_TOKEN

В документе оставляются только факт изменения модели и структура workflow, а реальные значения secret не записываются.

Текущее заключение

Следующее было подтверждено в этом наблюдении.

  • Создание PR работало нормально.
  • CodeRabbit, Sourcery и Qodo корректно реагировали на PR.
  • Qwen workflow также завершился успешно в pull_request_target.
  • Однако в прежней структуре Qwen мог выводить указания вызова инструмента в виде текста, не оставляя реального комментария.
  • Поэтому «успех workflow» и «успех написания комментария к PR» следует рассматривать отдельно.
  • Безопаснее изменить процесс так, чтобы последующий шаг GitHub Actions публиковал вывод Qwen непосредственно в виде комментария.