Skip to content

fix: surface the triggering workflow's conclusion in workflow_run reviews - #2848

Merged
IsmaelMartinez merged 4 commits into
The-PR-Agent:mainfrom
afonsojanu:workflow-run-ci-conclusion
Aug 30, 2026
Merged

fix: surface the triggering workflow's conclusion in workflow_run reviews#2848
IsmaelMartinez merged 4 commits into
The-PR-Agent:mainfrom
afonsojanu:workflow-run-ci-conclusion

Conversation

@afonsojanu

Copy link
Copy Markdown
Contributor

Fixes #2841.

What

workflow_run handling in pr_agent/servers/github_action_runner.py reads event and pull_requests from the payload but never conclusion, so a review triggered after another workflow finishes reads identically whether that workflow succeeded, failed, or was cancelled — the model is never told which. conclusion is already parsed in the test fixture and otherwise unused in the codebase (aside from where PR-Agent itself creates a check run).

Change

Added _inject_ci_conclusion(conclusion), which appends a short note to the extra_instructions of the same three tools (pr_reviewer, pr_description, pr_code_suggestions) that _inject_artifact_context already targets, telling the model explicitly when the triggering workflow did not conclude with success. Called right after the existing artifact-context injection in the workflow_run branch. Purely additive — no control flow changes, no new config keys, no prompt template edits.

Also extended the restore_github_settings test fixture to snapshot/restore extra_instructions for those three tool sections. run_action now mutates that state unconditionally on every workflow_run run (previously only _inject_artifact_context did, which no-ops unless artifacts are explicitly enabled in config) — without this the existing test_workflow_run_runs_auto_tools test would leak "...concluded: success" into later tests' settings.

Tests

Two new tests in tests/unittest/test_github_action_runner_core.py:

  • test_workflow_run_injects_ci_conclusion_when_not_success — asserts the conclusion text lands in pr_reviewer.extra_instructions for a "failure" conclusion.
  • test_workflow_run_does_not_inject_ci_conclusion_when_absent — asserts nothing is appended when the payload has no conclusion key at all.

Verified both against the pre-fix code (via git stash on just the implementation file): the first fails as expected (assert 'concluded: failure' in ''), the second still passes (there's nothing to guard against there). Full tests/unittest/test_github_action_runner_core.py: 19 passed.

PYTHONPATH=. pytest -q tests/unittest/test_github_action_runner_core.py

…iews

The workflow_run handler read event and pull_requests from the payload
but never conclusion, so a post-CI review reads identically whether the
triggering workflow succeeded, failed, or was cancelled. conclusion is
already parsed and unused elsewhere in the codebase.

_inject_ci_conclusion appends a labelled note to the same
extra_instructions fields _inject_artifact_context already targets, so
the reviewer is told plainly when CI did not pass instead of implying
a clean run by omission.

Also extends the restore_github_settings test fixture to snapshot and
restore the three tools' extra_instructions, since run_action now
mutates that state unconditionally on every workflow_run test, not
just ones that opt into artifact injection.
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Surface workflow_run CI conclusions in automated reviews

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Propagates workflow_run conclusions into automated prompts so failed CI is explicitly surfaced.
• Leaves missing conclusions untouched and avoids duplicating identical CI status instructions.
• Adds regression coverage and restores mutated prompt settings between tests.
Diagram

sequenceDiagram
    actor GH as GitHub Actions
    participant Runner as Action Runner
    participant Settings as Tool Settings
    participant Desc as PR Description
    participant Review as PR Reviewer
    participant Suggest as Code Suggestions
    GH->>Runner: workflow_run payload
    Runner->>Settings: Append CI conclusion
    Settings-->>Desc: Prompt context
    Settings-->>Review: Prompt context
    Settings-->>Suggest: Prompt context
    Runner->>Desc: Run description
    Runner->>Review: Run review
    Runner->>Suggest: Run suggestions
Loading
High-Level Assessment

Appending the conclusion through the existing extra_instructions mechanism is the best fit for this targeted fix because it reuses established artifact-context wiring and avoids new configuration or prompt-template contracts. A dedicated structured CI-status prompt variable was considered but would create broader cross-tool changes without improving this payload-level behavior.

Files changed (2) +86 / -9

Bug fix (1) +33 / -0
github_action_runner.pyInject triggering workflow conclusions into automated tool prompts +33/-0

Inject triggering workflow conclusions into automated tool prompts

• Adds CI conclusion context after repository settings and artifact context are applied for 'workflow_run' events. The helper safely ignores absent conclusions, targets the reviewer, description, and suggestion tools, and prevents duplicate text.

pr_agent/servers/github_action_runner.py

Tests (1) +53 / -9
test_github_action_runner_core.pyCover CI conclusion injection and isolate prompt settings +53/-9

Cover CI conclusion injection and isolate prompt settings

• Extends workflow event fixtures to vary or omit conclusions and adds regression tests for failure and missing values. The settings restoration fixture now snapshots each auto-run tool's 'extra_instructions' to prevent cross-test leakage.

tests/unittest/test_github_action_runner_core.py

@qodo-code-review

qodo-code-review Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Target-selection branches lack tests 📘 Rule violation ▣ Testability ⭐ New
Description
The new string-normalization and invalid-type fallback branches for ARTIFACTS.TARGET_TOOLS have no
corresponding test coverage. Regressions in custom target configuration could therefore prevent CI
conclusions from reaching the intended tools unnoticed.
Code

pr_agent/servers/github_action_runner.py[R367-370]

+    if isinstance(target_tools, str):
+        target_tools = [t.strip() for t in target_tools.split(",") if t.strip()]
+    elif not isinstance(target_tools, (list, set, tuple)):
+        target_tools = default_target_tools
Relevance

●●● Strong

Recent accepted precedents favor regression tests for invalid configuration types and newly
introduced behavior branches.

PR-#2528
PR-#2387

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 2694678 requires tests for newly introduced production behavior and branches. The
changed code adds separate handling for string and unsupported target configurations, while the
PR-branch tests at tests/unittest/test_github_action_runner_core.py[475-510] only exercise the
default configured list and the absent-conclusion return path.

Rule 2694678: Require tests to change when production code behavior changes
pr_agent/servers/github_action_runner.py[367-370]
tests/unittest/test_github_action_runner_core.py[475-510]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The newly introduced `ARTIFACTS.TARGET_TOOLS` normalization and fallback branches are not exercised by tests.

## Issue Context
Add focused tests for a comma-separated string and an unsupported value type, asserting which tools receive the CI-conclusion instruction while preserving settings isolation.

## Fix Focus Areas
- pr_agent/servers/github_action_runner.py[365-375]
- tests/unittest/test_github_action_runner_core.py[475-510]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. default_target_tools duplicates configuration 📘 Rule violation ⚙ Maintainability ⭐ New
Description
The new fallback repeats the configured artifacts.target_tools list in business logic even though
the same default already exists in pr_agent/settings/configuration.toml. This creates a second
source of truth that can drift from the centrally loaded configuration.
Code

pr_agent/servers/github_action_runner.py[R365-366]

+    default_target_tools = ["pr_reviewer", "pr_description", "pr_code_suggestions"]
+    target_tools = get_settings().get("ARTIFACTS.TARGET_TOOLS", default_target_tools)
Relevance

●●● Strong

Recent accepted precedents explicitly require removing duplicated runtime defaults and using
centrally configured settings.

PR-#2528
PR-#2598

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 2694652 forbids duplicating runtime configuration literals when a settings loader is
available. The changed code defines the three tool names as an inline fallback, while
pr_agent/settings/configuration.toml[480-490] already defines the identical
artifacts.target_tools configuration.

Rule 2694652: Do not hard-code configuration; load it from .pr_agent.toml or pr_agent/settings
pr_agent/servers/github_action_runner.py[365-366]
pr_agent/settings/configuration.toml[480-490]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`_inject_ci_conclusion` duplicates the centrally configured `artifacts.target_tools` default in Python business logic.

## Issue Context
The canonical list already exists in `pr_agent/settings/configuration.toml`; configuration should be loaded through `get_settings()` without repeating the same deployment-adjustable value inline.

## Fix Focus Areas
- pr_agent/servers/github_action_runner.py[365-370]
- pr_agent/settings/configuration.toml[480-490]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Artifact targets suppress CI status 🐞 Bug ≡ Correctness ⭐ New
Description
_inject_ci_conclusion uses ARTIFACTS.TARGET_TOOLS to select recipients, so customizing artifact
delivery to one tool silently withholds the triggering workflow's conclusion from other enabled
workflow-run tools. Those tools can then still imply a clean change after failed or cancelled CI,
defeating this fix for a supported configuration.
Code

pr_agent/servers/github_action_runner.py[366]

+    target_tools = get_settings().get("ARTIFACTS.TARGET_TOOLS", default_target_tools)
Relevance

●● Moderate

The concern is semantically plausible, but no close precedent confirms separating artifact targets
from CI-conclusion recipients.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The artifact helper and configuration explicitly define ARTIFACTS.TARGET_TOOLS as controlling
artifact context, while the workflow-run branch independently runs all three tools. The new lookup
therefore creates an unrelated configuration dependency that can omit CI context from tools that
still execute.

pr_agent/servers/github_action_runner.py[50-71]
pr_agent/settings/configuration.toml[480-490]
pr_agent/servers/github_action_runner.py[321-343]
pr_agent/servers/github_action_runner.py[365-375]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`_inject_ci_conclusion` currently derives its recipients from `ARTIFACTS.TARGET_TOOLS`. That setting controls artifact context only, so repositories that restrict artifacts to a subset of tools also unintentionally suppress CI-conclusion context for other workflow-run tools.

## Issue Context
The workflow-run path independently enables and runs `pr_description`, `pr_reviewer`, and `pr_code_suggestions`. Artifact injection is optional and its target setting is documented specifically as selecting tools that receive artifact context; it must not control whether enabled tools learn that the triggering workflow failed or was cancelled.

## Fix Focus Areas
- pr_agent/servers/github_action_runner.py[365-375]
- pr_agent/servers/github_action_runner.py[321-343]
- pr_agent/settings/configuration.toml[480-490]

Use an independent fixed CI recipient list (or a dedicated CI-specific configuration if intended), and add a test proving that a restricted `ARTIFACTS.TARGET_TOOLS` value does not suppress CI status from the other workflow-run tools.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (2)
4. Fixture docstring is declarative ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
Three modified or newly added docstrings begin with declarative or noun phrases—`run_action
mutates, A failing/cancelled triggering workflow must be surfaced, and No conclusion in the
payload`—rather than imperative verbs. They therefore violate the required imperative docstring
style.
Code

tests/unittest/test_github_action_runner_core.py[R110-112]

+    """run_action mutates global GITHUB/GITHUB_ACTION_CONFIG/GITHUB_APP settings, plus the
+    extra_instructions of the three auto-run tools (artifact/CI-conclusion injection);
+    snapshot and restore them so these tests don't leak state into others."""
Relevance

●● Moderate

Imperative-docstring enforcement has recent accepted precedents, but similar test-docstring findings
were rejected; team behavior is mixed.

PR-#2807
PR-#2703
PR-#2661

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2694688 requires new or modified docstrings to use imperative phrasing. The cited fixture
docstring starts with the declarative statement run_action mutates before discussing snapshotting
and restoration, while the two added test docstrings begin with declarative statements about
surfacing a failing or cancelled workflow and handling a payload with no conclusion; none begins
with an imperative verb.

Rule 2694688: Docstrings and comments must use imperative phrasing
tests/unittest/test_github_action_runner_core.py[110-112]
tests/unittest/test_github_action_runner_core.py[474-475]
tests/unittest/test_github_action_runner_core.py[491-492]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rewrite the modified fixture docstring and the new failure-case and absent-conclusion test docstrings so their first sentences begin with imperative verbs while preserving each docstring’s intent.

## Issue Context
The checklist requires newly added or modified docstrings to describe behavior using imperative phrasing. Suitable openings include `Restore` or `Snapshot` for the fixture, `Verify that a failing or cancelled workflow is surfaced to the model` for the failure-case test, and `Verify that an absent conclusion does not append a concluded-None instruction` for the absent-conclusion test.

## Fix Focus Areas
- tests/unittest/test_github_action_runner_core.py[110-112]
- tests/unittest/test_github_action_runner_core.py[474-475]
- tests/unittest/test_github_action_runner_core.py[491-492]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Tool names use single quotes ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new tool-name literals use single-quote delimiters even though double quotes require no
additional escaping. This violates the repository’s required Python string style.
Code

pr_agent/servers/github_action_runner.py[R368-369]

+            if key.lower() in ('pr_reviewer', 'pr_description', 'pr_code_suggestions'):
+                if hasattr(setting, 'extra_instructions'):
Relevance

●● Moderate

Recent quote-style precedents conflict: exact double-quote fixes were accepted, but comparable
single-quote findings were also rejected.

PR-#2836
PR-#2774
PR-#2598

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2694657 requires double-quoted Python string literals. The changed lines delimit pr_reviewer,
pr_description, pr_code_suggestions, and extra_instructions with single quotes without an
escaping justification.

Rule 2694657: Use double quotes for all Python string literals
pr_agent/servers/github_action_runner.py[368-369]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace the newly added single-quoted Python string literals with double-quoted literals.

## Issue Context
The compliance checklist requires double quotes for Python strings unless doing so would add escaping; these literals need no escaping.

## Fix Focus Areas
- pr_agent/servers/github_action_runner.py[368-369]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


  • Author self-review: I have reviewed the code review findings, and addressed the relevant ones.

Grey Divider

Context sources
✅ Compliance rules (platform): 34 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit be60e78

Results up to commit f6b661b ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 📜 Skill insights (0)


Remediation recommended
1. Fixture docstring is declarative ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
Three modified or newly added docstrings begin with declarative or noun phrases—`run_action
mutates, A failing/cancelled triggering workflow must be surfaced, and No conclusion in the
payload`—rather than imperative verbs. They therefore violate the required imperative docstring
style.
Code

tests/unittest/test_github_action_runner_core.py[R110-112]

+    """run_action mutates global GITHUB/GITHUB_ACTION_CONFIG/GITHUB_APP settings, plus the
+    extra_instructions of the three auto-run tools (artifact/CI-conclusion injection);
+    snapshot and restore them so these tests don't leak state into others."""
Relevance

●● Moderate

Imperative-docstring enforcement has recent accepted precedents, but similar test-docstring findings
were rejected; team behavior is mixed.

PR-#2807
PR-#2703
PR-#2661

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2694688 requires new or modified docstrings to use imperative phrasing. The cited fixture
docstring starts with the declarative statement run_action mutates before discussing snapshotting
and restoration, while the two added test docstrings begin with declarative statements about
surfacing a failing or cancelled workflow and handling a payload with no conclusion; none begins
with an imperative verb.

Rule 2694688: Docstrings and comments must use imperative phrasing
tests/unittest/test_github_action_runner_core.py[110-112]
tests/unittest/test_github_action_runner_core.py[474-475]
tests/unittest/test_github_action_runner_core.py[491-492]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rewrite the modified fixture docstring and the new failure-case and absent-conclusion test docstrings so their first sentences begin with imperative verbs while preserving each docstring’s intent.

## Issue Context
The checklist requires newly added or modified docstrings to describe behavior using imperative phrasing. Suitable openings include `Restore` or `Snapshot` for the fixture, `Verify that a failing or cancelled workflow is surfaced to the model` for the failure-case test, and `Verify that an absent conclusion does not append a concluded-None instruction` for the absent-conclusion test.

## Fix Focus Areas
- tests/unittest/test_github_action_runner_core.py[110-112]
- tests/unittest/test_github_action_runner_core.py[474-475]
- tests/unittest/test_github_action_runner_core.py[491-492]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Tool names use single quotes ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new tool-name literals use single-quote delimiters even though double quotes require no
additional escaping. This violates the repository’s required Python string style.
Code

pr_agent/servers/github_action_runner.py[R368-369]

+            if key.lower() in ('pr_reviewer', 'pr_description', 'pr_code_suggestions'):
+                if hasattr(setting, 'extra_instructions'):
Relevance

●● Moderate

Recent quote-style precedents conflict: exact double-quote fixes were accepted, but comparable
single-quote findings were also rejected.

PR-#2836
PR-#2774
PR-#2598

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2694657 requires double-quoted Python string literals. The changed lines delimit pr_reviewer,
pr_description, pr_code_suggestions, and extra_instructions with single quotes without an
escaping justification.

Rule 2694657: Use double quotes for all Python string literals
pr_agent/servers/github_action_runner.py[368-369]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace the newly added single-quoted Python string literals with double-quoted literals.

## Issue Context
The compliance checklist requires double quotes for Python strings unless doing so would add escaping; these literals need no escaping.

## Fix Focus Areas
- pr_agent/servers/github_action_runner.py[368-369]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Addresses automated review feedback on the two style rules this repo
enforces: double-quoted string literals, and imperative-phrased
docstrings for new/modified code.
@afonsojanu

Copy link
Copy Markdown
Contributor Author

Addressed both findings: double-quoted the new string literals, and reworded the three modified/new docstrings to imperative mood. Tests still 19 passed.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit da64da4

@IsmaelMartinez IsmaelMartinez left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking this one of the three, and crediting all three. It is the only one that leaves _inject_artifact_context alone, and that turns out to be the whole difference: both alternatives refactor it and both pick up problems doing so.

Notes on the other two, since the comparison is what decided it. #2843 by @lb1192176991-lab arrived first and follows the issue most literally, and its ARTIFACTS.TARGET_TOOLS handling is the one thing this PR is missing, which is the inline below. #2847 by @vaishaldsouza wrote the best single test of the three, a regression test for a malformed target_tools value. When I merge I will add you both as co-authors.

One inline before that. Thanks also for extending restore_github_settings unprompted: yours is the only one of the three that does not leak CI text into global settings between tests.

Comment thread pr_agent/servers/github_action_runner.py Outdated
The CI-status injection was checking against a fixed tuple of three
tool names, so a repo that narrows ARTIFACTS.TARGET_TOOLS to fewer
tools still got the CI context injected into all three anyway.

Reads the configured target tools now, falling back to the same three
tools when nothing is set, with a guard so a string, a malformed
value, or nothing at all can't raise.

Based on the approach from The-PR-Agent#2843, applied here per review feedback.
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 2d05fb8

@qodo-code-review

qodo-code-review Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

Grey Divider

Sorry, something went wrong

We weren't able to complete the code review on our side. Please try again manually by commenting /agentic_review on this PR.

Grey Divider

Qodo Logo

@IsmaelMartinez IsmaelMartinez left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patience here, and for taking the ARTIFACTS.TARGET_TOOLS suggestion verbatim.

Approving and merging, with one change I pushed to your branch first as be60e784. The closing sentence asserted "the change has not passed CI", which is untrue for action_required, and that is the most common non-success conclusion on this repo: 18 of the last 300 runs against 12 outright failures. It now reports the conclusion rather than asserting failure. That wording was mine from #2841, not yours.

The coverage holds. Reverting the runner while keeping your tests puts test_workflow_run_injects_ci_conclusion_when_not_success red, and the fixture extension is load-bearing rather than padding: without it the success text leaks into the next test.

#2843 and #2847 are credited as co-authors on the squash.

@IsmaelMartinez
IsmaelMartinez merged commit ceae34b into The-PR-Agent:main Aug 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The workflow_run trigger ignores the workflow's conclusion

2 participants