Skip to content

ci(#388): fail roll-up when tests are skipped on pull_request_target#400

Open
rh-hemartin wants to merge 1 commit into
mainfrom
agent/388-fix-skipped-tests-rollup
Open

ci(#388): fail roll-up when tests are skipped on pull_request_target#400
rh-hemartin wants to merge 1 commit into
mainfrom
agent/388-fix-skipped-tests-rollup

Conversation

@rh-hemartin

Copy link
Copy Markdown
Member

Summary

  • On pull_request_target, when gate is skipped or auth is denied, all downstream jobs cascade to skipped. The roll-up only checked for failure/cancelled, so it reported SUCCESS -- letting PRs satisfy branch protection without any test running.
  • Adds a check in the roll-up: on pull_request_target, if detect was skipped, fail. This covers both gate-skipped and auth-denied paths without affecting push/merge_group/workflow_dispatch.

Test plan

  • Verify existing push/merge_group runs are unaffected (gate is legitimately skipped, detect runs)
  • Verify pull_request_target with ok-to-test label still passes (gate runs, auth granted, detect runs)
  • Verify pull_request_target without authorization now fails the roll-up instead of reporting SUCCESS

Closes #388

🤖 Generated with Claude Code

@rh-hemartin
rh-hemartin requested a review from a team as a code owner July 23, 2026 13:20
@rh-hemartin rh-hemartin self-assigned this Jul 23, 2026
On pull_request_target, if detect was skipped (gate skipped or auth
denied), the roll-up now fails instead of reporting SUCCESS.

Closes #388

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Hector Martinez <hemartin@redhat.com>
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

CI: fail roll-up when pull_request_target tests are skipped

🐞 Bug fix ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Prevent branch protection from passing when pull_request_target test jobs are skipped.
• Fail the roll-up if detect is skipped on pull_request_target (gate skipped or auth denied).
• Keep push/merge_group/workflow_dispatch behavior unchanged.
Diagram

graph TD
  A["Workflow run"] --> B["Roll-up: Check results"] --> C{"on pull_request_target\nAND detect skipped?"}
  C -->|"yes"| D["Fail roll-up (exit 1)"] --> E["Branch protection blocked"]
  C -->|"no"| F["Evaluate gate/tests results"] --> G["Roll-up pass/fail"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Fail roll-up on any skipped needs (generic rule)
  • ➕ Catches future cases where other prerequisite jobs are skipped unexpectedly
  • ➕ Simplifies logic to a single policy (no event-specific branching)
  • ➖ Would likely break legitimate skip paths on push/merge_group/workflow_dispatch
  • ➖ Higher risk of introducing noisy failures and CI friction
2. Move the authorization/skip check into detect (make detect always run)
  • ➕ Keeps the roll-up purely aggregative
  • ➕ Centralizes authorization semantics in the job that owns it
  • ➖ May require reworking job conditionals/permissions to ensure detect truly runs on pull_request_target
  • ➖ Still requires a required-check strategy to ensure merges are blocked when detect can’t run
3. Make detect (or gate) the required check instead of a roll-up
  • ➕ Eliminates ambiguity where roll-up can hide skipped downstream jobs
  • ➕ Uses GitHub’s native required check semantics per job
  • ➖ May not fit existing required-check setup (single roll-up required check)
  • ➖ Could increase required-check count and complicate branch protection configuration

Recommendation: The PR’s targeted roll-up guard is the best tradeoff: it fixes the branch-protection hole specifically for pull_request_target without changing skip semantics for other events. A generic “fail on any skipped” policy is more comprehensive but too risky for workflows that intentionally skip jobs; reworking detect/gate to always run is cleaner long-term but larger in scope.

Files changed (1) +5 / -0

Bug fix (1) +5 / -0
functional-tests.ymlFail roll-up when detect is skipped on pull_request_target +5/-0

Fail roll-up when detect is skipped on pull_request_target

• Adds EVENT_NAME to the roll-up step environment and introduces an early check that fails the roll-up if the workflow is running on pull_request_target and the detect job result is skipped. This prevents unauthorized or gate-skipped pull_request_target runs from reporting SUCCESS when no tests executed.

.github/workflows/functional-tests.yml

@rh-hemartin
rh-hemartin force-pushed the agent/388-fix-skipped-tests-rollup branch from db3284f to fe6ef26 Compare July 23, 2026 13:22
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 23, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:23 PM UTC · Completed 1:34 PM UTC
Commit: fe6ef26 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 55 rules
✅ Skills: 4 invoked
  code-review
  code-implementation
  pr-review
  docs-review

Grey Divider


Action required

1. Protected workflow file modified 📜 Skill insight § Compliance
Description
This PR modifies .github/workflows/functional-tests.yml, which is a protected
governance/infrastructure path requiring explicit human review and must not be auto-approved. Ensure
the PR receives the required human approval (e.g., CODEOWNERS) before merge.
Code

.github/workflows/functional-tests.yml[R370-378]

+          EVENT_NAME: ${{ github.event_name }}
          GATE_RESULT: ${{ needs.gate.result }}
          DETECT_RESULT: ${{ needs.detect.result }}
          TESTS_RESULT: ${{ needs.functional-tests.result }}
        run: |
+          if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
+            echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
+            exit 1
+          fi
Relevance

⭐⭐⭐ High

Repo has treated .github workflow changes as governance-sensitive and asked for explicit
justification/human review before merging.

PR-#184
PR-#29

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The compliance rule requires raising a finding for any PR that modifies protected
governance/infrastructure paths (including .github/). The diff shows modifications in
.github/workflows/functional-tests.yml (added env var and a new failing condition), therefore this
must be treated as requiring human review and not auto-approved.

.github/workflows/functional-tests.yml[370-378]
Skill: pr-review

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

## Issue description
Changes under `.github/` are protected governance/infrastructure modifications and must not be auto-approved.

## Issue Context
This PR updates a GitHub Actions workflow under `.github/workflows/`, which requires explicit human review/approval per policy.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[370-378]

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


2. Label events fail rollup 🐞 Bug ≡ Correctness
Description
On pull_request_target, the roll-up now hard-fails when detect is skipped; because the workflow
triggers on any labeled event but gate is skipped unless the applied label is exactly ok-to-test,
adding any other label will skip gate/detect and fail functional-tests-complete (even for
already-authorized PRs). This can unexpectedly block merges when maintainers apply unrelated labels
after tests have passed.
Code

.github/workflows/functional-tests.yml[R375-378]

+          if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
+            echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
+            exit 1
+          fi
Relevance

⭐⭐ Medium

Plausible edge case, but no close repo precedent on pull_request_target label-trigger behavior vs
ok-to-test gating.

PR-#89
PR-#184

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The workflow is configured to run on any pull_request_target labeled event, but gate is skipped
unless the applied label is ok-to-test; detect depends on gate authorization and becomes skipped,
and the new roll-up logic fails on detect==skipped for pull_request_target. The authorization script
would authorize any labeled event when ok-to-test is present, but gate never runs on those events
today.

.github/workflows/functional-tests.yml[27-28]
.github/workflows/functional-tests.yml[46-49]
.github/workflows/functional-tests.yml[76-81]
.github/workflows/functional-tests.yml[362-378]
.github/scripts/check-e2e-authorization.sh[104-110]

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 workflow triggers on all `pull_request_target` label events, but the `gate` job is conditionally skipped unless the label being applied is `ok-to-test`. With the new roll-up rule (`pull_request_target` + `detect` skipped => fail), applying any other label causes `gate` and then `detect` to be skipped, which fails `functional-tests-complete` even when the PR is already authorized.

## Issue Context
The authorization script already supports authorizing *any* `labeled` event as long as the PR currently has `ok-to-test` (it checks the PR’s label set), but the `gate` job never runs for those events due to its `if:` filter.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[46-49]
- .github/workflows/functional-tests.yml[27-28]

### Suggested change
Adjust the `gate.if` so it runs on `pull_request_target` labeled events whenever the PR has `ok-to-test` (not only when the *newly added* label is `ok-to-test`), e.g.:
- `github.event.action != 'labeled' || contains(github.event.pull_request.labels.*.name, 'ok-to-test')`

This prevents false failures from unrelated label changes while keeping the new roll-up failure for genuinely unauthorized PRs.

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



Remediation recommended

3. Gate failure masked 🐞 Bug ◔ Observability
Description
functional-tests-complete checks for detect==skipped before checking needs.gate.result, so if the
gate job fails/cancels (causing detect to be skipped), the roll-up exits with a misleading “not
authorized” message instead of reporting the gate failure. This makes diagnosing real gate errors
harder.
Code

.github/workflows/functional-tests.yml[R375-381]

+          if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
+            echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
+            exit 1
+          fi
          if [ "$GATE_RESULT" = "failure" ] || [ "$GATE_RESULT" = "cancelled" ]; then
            echo "::error::Gate job ${GATE_RESULT}"
            exit 1
Relevance

⭐⭐⭐ High

Improving failure messaging/diagnostics in workflows is routinely accepted; check gate result first
to avoid misleading authorization error.

PR-#184
PR-#90

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The roll-up’s first branch exits on detect==skipped, so the later gate failure/cancelled branch is
unreachable in that scenario; detect is skipped whenever the authorized output is not 'true', which
includes cases where gate did not succeed.

.github/workflows/functional-tests.yml[375-382]
.github/workflows/functional-tests.yml[76-81]

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 roll-up step exits early on `DETECT_RESULT=skipped` for `pull_request_target`, before it checks `GATE_RESULT`. If `gate` fails/cancels and `detect` is skipped as a consequence, the workflow reports the wrong root cause.

## Issue Context
This doesn’t change pass/fail outcome (it still fails), but it obscures the actual failure mode and slows debugging.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[375-385]

### Suggested change
Reorder the checks so gate failure/cancellation is handled before the `detect==skipped` authorization guard, or make the `detect==skipped` guard conditional on `GATE_RESULT == success` (and optionally add `AUTHORIZED=${{ needs.gate.outputs.authorized }}` to emit a precise message).

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


Grey Divider

Qodo Logo

Comment on lines +370 to +378
EVENT_NAME: ${{ github.event_name }}
GATE_RESULT: ${{ needs.gate.result }}
DETECT_RESULT: ${{ needs.detect.result }}
TESTS_RESULT: ${{ needs.functional-tests.result }}
run: |
if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Protected workflow file modified 📜 Skill insight § Compliance

This PR modifies .github/workflows/functional-tests.yml, which is a protected
governance/infrastructure path requiring explicit human review and must not be auto-approved. Ensure
the PR receives the required human approval (e.g., CODEOWNERS) before merge.
Agent Prompt
## Issue description
Changes under `.github/` are protected governance/infrastructure modifications and must not be auto-approved.

## Issue Context
This PR updates a GitHub Actions workflow under `.github/workflows/`, which requires explicit human review/approval per policy.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[370-378]

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

Comment on lines +375 to +378
if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Label events fail rollup 🐞 Bug ≡ Correctness

On pull_request_target, the roll-up now hard-fails when detect is skipped; because the workflow
triggers on any labeled event but gate is skipped unless the applied label is exactly ok-to-test,
adding any other label will skip gate/detect and fail functional-tests-complete (even for
already-authorized PRs). This can unexpectedly block merges when maintainers apply unrelated labels
after tests have passed.
Agent Prompt
## Issue description
The workflow triggers on all `pull_request_target` label events, but the `gate` job is conditionally skipped unless the label being applied is `ok-to-test`. With the new roll-up rule (`pull_request_target` + `detect` skipped => fail), applying any other label causes `gate` and then `detect` to be skipped, which fails `functional-tests-complete` even when the PR is already authorized.

## Issue Context
The authorization script already supports authorizing *any* `labeled` event as long as the PR currently has `ok-to-test` (it checks the PR’s label set), but the `gate` job never runs for those events due to its `if:` filter.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[46-49]
- .github/workflows/functional-tests.yml[27-28]

### Suggested change
Adjust the `gate.if` so it runs on `pull_request_target` labeled events whenever the PR has `ok-to-test` (not only when the *newly added* label is `ok-to-test`), e.g.:
- `github.event.action != 'labeled' || contains(github.event.pull_request.labels.*.name, 'ok-to-test')`

This prevents false failures from unrelated label changes while keeping the new roll-up failure for genuinely unauthorized PRs.

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

Comment on lines +375 to 381
if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"
exit 1
fi
if [ "$GATE_RESULT" = "failure" ] || [ "$GATE_RESULT" = "cancelled" ]; then
echo "::error::Gate job ${GATE_RESULT}"
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Gate failure masked 🐞 Bug ◔ Observability

functional-tests-complete checks for detect==skipped before checking needs.gate.result, so if the
gate job fails/cancels (causing detect to be skipped), the roll-up exits with a misleading “not
authorized” message instead of reporting the gate failure. This makes diagnosing real gate errors
harder.
Agent Prompt
## Issue description
The roll-up step exits early on `DETECT_RESULT=skipped` for `pull_request_target`, before it checks `GATE_RESULT`. If `gate` fails/cancels and `detect` is skipped as a consequence, the workflow reports the wrong root cause.

## Issue Context
This doesn’t change pass/fail outcome (it still fails), but it obscures the actual failure mode and slows debugging.

## Fix Focus Areas
- .github/workflows/functional-tests.yml[375-385]

### Suggested change
Reorder the checks so gate failure/cancellation is handled before the `detect==skipped` authorization guard, or make the `detect==skipped` guard conditional on `GATE_RESULT == success` (and optionally add `AUTHORIZED=${{ needs.gate.outputs.authorized }}` to emit a precise message).

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

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [protected-path] .github/workflows/functional-tests.yml — PR modifies a file under the .github/ protected path. The change is authorized by issue ci(functional-tests): complete job reports SUCCESS when all tests are skipped #388 and the PR description explains the rationale (fix roll-up reporting SUCCESS when tests were skipped on pull_request_target). Human approval is always required for protected-path changes.

Low

  • [error-message-format] .github/workflows/functional-tests.yml:376 — The new error message uses a static string rather than interpolating DETECT_RESULT, unlike the existing error messages which interpolate their respective variables (e.g., ${GATE_RESULT}, ${DETECT_RESULT}, ${TESTS_RESULT}). Since this branch only executes when DETECT_RESULT is exactly "skipped", interpolation would add redundant information — the message already says "was skipped." This is a minor stylistic inconsistency, not a functional gap.
    Remediation: Optionally interpolate for visual consistency: echo "::error::Detect was skipped on pull_request_target (${DETECT_RESULT}) — tests were not authorized to run".

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

TESTS_RESULT: ${{ needs.functional-tests.result }}
run: |
if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$DETECT_RESULT" = "skipped" ]; then
echo "::error::Detect was skipped on pull_request_target — tests were not authorized to run"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] error-message-format

The new error message uses a static string rather than interpolating DETECT_RESULT, unlike the existing error messages which interpolate their respective variables. Since this branch only executes when DETECT_RESULT is exactly skipped, interpolation would add redundant information. Minor stylistic inconsistency.

Suggested fix: Optionally interpolate for visual consistency: echo ::error::Detect was skipped on pull_request_target (${DETECT_RESULT}) — tests were not authorized to run

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci(functional-tests): complete job reports SUCCESS when all tests are skipped

1 participant