idea_world_labDEV JOURNAL
jeudi 25 juin 2026

Structure et historique des améliorations du workflow Qwen PR Review

Date de rédaction : 25 juin 2026

Objectif

Ce document consigne le processus de personnalisation du workflow de revue de PR basé sur qwen-code afin de l’adapter au dépôt actuel.

L’enjeu principal de ce travail n’est pas seulement que le workflow se termine avec succès, mais que les résultats de la revue générés par Qwen soient effectivement publiés en tant que commentaires sur les PR GitHub.

Contexte

Ce dépôt utilise également des bots de revue externes tels que CodeRabbit, Sourcery et Qodo. Cependant, nous importons séparément le workflow qwen-code pour l’exécuter via le chemin OpenRouter, et nous expérimentons également un flux où chaque PR reçoit une revue basée sur Qwen.

Au départ, le flux d’API de revue AI a été interrompu en raison de problèmes de coût. Par la suite, grâce à la possibilité d’utiliser openai/gpt-oss-120b:free dans le niveau gratuit d’OpenRouter, nous avons modifié le README pour tenter à nouveau cette approche.

Structure du workflow d’origine

Fichier cible :

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

Nom du workflow original :

🧐 Qwen Pull Request Review

Déclencheur principal:

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'

Le travail était configuré pour s’exécuter dans les cas suivants :

  • Exécution manuelle avec workflow_dispatch
  • Événement opened de pull_request_target lorsque l’auteur du PR est OWNER, MEMBER ou COLLABORATOR
  • Commentaire de révision de PR contenant @qwen /review
  • Corps de la révision de PR contenant @qwen /review

Les principales étapes du workflow étaient les suivantes :

  1. Checkout du code du PR
  2. Collecte du titre, du corps, des fichiers modifiés et des informations de diff du PR
  3. Exécution de QwenLM/qwen-code-action
  4. Dans le prompt, demander à Qwen de créer une revue et d’ajouter un commentaire via gh pr comment

Problème observé

Le workflow a été observé en pratique sur le PR #5.

PR :

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

La PR a été créée correctement et les bots suivants ont réagi.

  • CodeRabbit
  • Sourcery
  • Qodo

Le workflow Qwen a également été exécuté lors de l'événement pull_request_target.

Exécution observée :

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

Cependant, aucun commentaire de révision Qwen n'est resté dans la PR réelle.

En regardant le journal du workflow, on voit que Qwen, après avoir rédigé le contenu de la révision, n'exécute pas l'appel réel de l'outil et affiche en texte une instruction de style JSON sous la forme suivante.

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

Ainsi, le workflow lui‑même était un succès, mais le résultat attendu par l'utilisateur, « rédaction du commentaire PR », n’a pas été réalisé.

Résumé des causes

Le problème était la structure qui confiait la rédaction du commentaire à Qwen.

Le prompt original demandait à Qwen d’exécuter directement ce qui suit.

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

Cependant, lors de l'exécution réelle, Qwen n'a pas effectué cette tâche en appelant l'outil, mais s'est contenté d'afficher le travail à faire sous forme de texte.

Ainsi, si le modèle n'appelle pas correctement l'outil, même si le workflow réussit, aucun commentaire n'apparaît sur la PR.

Problème de structure supplémentaire identifié

La condition du job du workflow incluait l'événement issue_comment.

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

Cependant, le déclencheur on: ne comportait pas issue_comment.

En d'autres termes, même si vous laissez le commentaire @qwen /review dans la conversation PR, le workflow ne démarre pas du tout.

De plus, le déclencheur pull_request_target ne réagissait qu'à opened.

pull_request_target:
  types: ['opened']

Donc, l'événement synchronize où un nouveau commit est poussé sur la branche PR n’a pas été relancé automatiquement.

Direction d'amélioration

Au lieu de confier la rédaction des commentaires GitHub au modèle, on fait en sorte que l’étape GitHub Actions soit responsable de la rédaction des commentaires.

Après amélioration, la répartition des responsabilités est la suivante.

Qwen
  -> générer uniquement le texte Markdown de la revue

GitHub Actions
  -> enregistrer la sortie de Qwen dans un fichier
  -> publier un commentaire sur la PR avec gh pr comment

Ainsi, même si Qwen affiche l’appel d’outil sous forme de texte, il est possible de recevoir qwen_result dans l’étape du workflow et de laisser un commentaire.

Modifications

1. Renforcement du déclencheur

Ancien :

pull_request_target:
  types: ['opened']

Modification:

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

Intention :

  • S'exécuter lorsqu'une PR est ouverte pour la première fois
  • S'exécuter lorsqu'une PR est rouverte
  • S'exécuter lorsqu'un nouveau commit est ajouté à la branche de la PR
  • S'exécuter lorsqu'un commentaire @qwen /review est laissé dans la conversation de la PR

Observations supplémentaires :

Renforcer uniquement le déclencheur on: n'était pas suffisant. En fait, lorsqu'un nouveau commit était poussé sur la branche de la PR, le run pull_request_target était créé, mais la condition du job n'autorisait encore que github.event.action == 'opened', ce qui faisait que le run se terminait par skipped.

Par conséquent, la condition du job doit également être modifiée comme suit.

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

2. Attribution d'ID à l'étape Qwen

Modification:

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

Intention :

Ceci est destiné à lire la sortie suivante dans l'étape suivante.

steps.qwen_review.outputs.qwen_result

3. Changement de responsabilité du prompt

Le prompt original demandait directement à Qwen de rédiger le fichier et le commentaire de PR.

Après modification, le prompt indique à Qwen de ne renvoyer que le texte Markdown de la revue comme réponse finale.

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.

Intention :

  • Réduire le problème où Qwen génère du JSON d’appel d’outil.
  • Transférer la responsabilité de la rédaction des commentaires du modèle au step du workflow.

4. Ajouter une étape pour publier la sortie de Qwen en commentaire PR

Étape ajoutée :

- 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"

Intention :

  • Si la sortie de Qwen n'est pas vide, on la laisse toujours en commentaire de PR.
  • La rédaction du commentaire est prise en charge par une étape déterministe qui utilise GITHUB_TOKEN et gh pr comment.

Observations supplémentaires :

Au début, j'ai mal lu le nom de la sortie comme steps.qwen_review.outputs.qwen_result. En vérifiant le action.yml de QwenLM/qwen-code-action, il s'avère que l'étape interne du composite crée qwen_result, mais le nom de la sortie exposée à l'extérieur de l'action est summary.

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

Donc l’étape de commentaire suivante doit lire steps.qwen_review.outputs.summary. Si vous lisez qwen_result, même si Qwen génère correctement le corps de la revue, l’étape de publication sera ignorée.

Points d’attention

Le workflow pull_request_target s’exécute en se basant sur le fichier de workflow de la branche de base, et non sur celui de la branche PR.

Par conséquent, simplement pousser une modification du workflow dans la branche PR ne changera pas le comportement actuel de pull_request_target pour cette PR.

Pour que cela prenne effet, l’une des options suivantes est nécessaire :

  1. Appliquer d’abord la modification du workflow dans main.
  2. Puis, dans la PR, laisser un commentaire @qwen /review ou pousser un nouveau commit afin d’exécuter le workflow mis à jour.

Dans ce travail, la modification du workflow sera d’abord intégrée dans main, puis le Qwen review sera déclenché à nouveau sur la PR #5 afin de vérifier si le commentaire est réellement créé.

Critères de sécurité

Le fichier du workflow ne doit pas contenir de valeurs sensibles telles que la clé API, l’URL du point de terminaison ou l’URL de base du fournisseur.

Dans les journaux de GitHub Actions, ces valeurs doivent également être masquées en tant que secrets.

OPENAI_API_KEY
OPENAI_BASE_URL
OPENAI_MODEL
GITHUB_TOKEN

Le document ne conserve que le fait du changement de modèle et la structure du workflow, sans enregistrer les valeurs réelles des secrets.

Conclusion actuelle

Ce qui a été confirmé par cette observation est le suivant :

  • La création de la PR s’est déroulée normalement.
  • CodeRabbit, Sourcery et Qodo ont réagi correctement à la PR.
  • Le workflow Qwen s’est également terminé avec succès dans pull_request_target.
  • Cependant, dans la structure précédente, Qwen pouvait se contenter d’afficher une instruction d’appel d’outil sous forme de texte sans réellement publier de commentaire.
  • Ainsi, le « succès du workflow » et le « succès de la publication du commentaire de la PR » doivent être considérés séparément.
  • Il est plus sûr de modifier le workflow afin que la valeur de sortie de Qwen soit directement publiée comme commentaire par l’étape suivante de GitHub Actions.