Skip to content

fix(#5339): skip disabled workflows gracefully in per-org dispatch#5340

Open
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/5339-graceful-disabled-workflow-dispatch
Open

fix(#5339): skip disabled workflows gracefully in per-org dispatch#5340
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/5339-graceful-disabled-workflow-dispatch

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

  • Per-org scaffold dispatch (dispatch.yml) now gracefully handles disabled target workflows instead of failing the entire dispatch job
  • Detects disabled workflow in gh workflow run stderr and emits ::warning:: + continues, matching the pattern already used in prioritize-scheduler.yml
  • When all matched workflows for a stage are disabled, exits cleanly with a warning instead of erroring on zero dispatches
  • Non-disabled failures (bad credentials, invalid parameters, network errors) still fail with exit 1

Fixes #5339

Changes

internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml

  • Added disabled_skipped counter to track workflows skipped due to being disabled
  • Added case-insensitive grep for disabled workflow in gh workflow run error output — on match, emit ::warning:: and continue instead of exit 1
  • Updated zero-dispatched check: if all matched workflows were disabled, emit ::warning:: instead of ::error:: + exit 1; if no workflows matched at all (genuine config problem), keep the error
  • Bumped lint-workflow-size from 500 to 510 to accommodate the additional error handling lines

Testing

  • Verify dispatch succeeds with ::warning:: annotation when target workflow is disabled (HTTP 422 Cannot trigger a 'workflow_dispatch' on a disabled workflow)
  • Verify dispatch still fails with ::error:: + exit 1 for non-disabled errors (e.g., bad credentials, network errors)
  • Verify the case where all workflows for a stage are disabled results in clean exit with ::warning:: (not exit 1)
  • Verify the case where no workflows exist for a stage still fails with ::error:: + exit 1
  • YAML is syntactically valid
  • Workflow file stays within lint-workflow-size limit (508 ≤ 510)

🤖 Generated with Claude Code


Closes #5339

Post-script verification

  • Branch is not main/master (agent/5339-graceful-disabled-workflow-dispatch)
  • Secret scan passed (gitleaks — bb253104277632085f4fb0cb434a77587dd30a0a..HEAD)
  • PR body secret scan passed (gitleaks — no-git)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

The dispatch script treated all gh workflow run failures as fatal,
including HTTP 422 when a target workflow is intentionally disabled.
Detect 'disabled workflow' in the error output and emit a warning
instead of failing, matching the pattern already used in the
prioritize-scheduler. When all matched workflows are disabled, exit
cleanly with a warning rather than erroring on zero dispatches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner July 20, 2026 06:35
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Agent PR ready for human review label Jul 20, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:36 AM UTC · Completed 6:50 AM UTC
Commit: f86e7fc · View workflow run →

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [logic-error] internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml:499 — When all stage-matched workflows are disabled (dispatched==0, disabled_skipped>0), the warning branch (line 501) does not exit or skip the final echo. Execution falls through to line 508: "Successfully dispatched 0 workflow(s) for stage $STAGE: " — a misleading success message. The control flow is also fragile: any future code appended after the success echo would execute in the all-disabled case without a guard.
    Remediation: Add exit 0 after the all-disabled warning (inside the if [[ $disabled_skipped -gt 0 ]] branch), or restructure as if/elif/else so the success message only prints when dispatched>0.

Low

  • [edge-case] internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml:483 — Disabled-workflow detection relies on grep -qi 'disabled workflow' against gh CLI stderr. This matches the current error format (Cannot trigger a 'workflow_dispatch' on a disabled workflow) but depends on an uncontrolled third-party string that could change between gh CLI versions. If the wording changes, the fallback is fail-closed (exit 1), which is safe.

  • [fail-open] internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml:499 — When all workflows for a stage are disabled, dispatch exits 0 with only a ::warning::. The stage's event is effectively dropped — upstream callers see success though no agent ran. Intentional per Per-org dispatch should gracefully skip disabled target workflows instead of failing #5339 but creates a silent-failure path. See also: [logic-error] finding at this location.

  • [injection] internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml:488 — Pre-existing (not introduced by this PR): $output (gh CLI stderr) is interpolated unsanitized into ::error:: and ::notice:: workflow commands. The new disabled-workflow code path does not interpolate $output into any new commands.

@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.

echo "Scanned $scanned workflow(s), skipped $skipped, dispatched $dispatched"
echo "Scanned $scanned workflow(s), skipped $skipped, disabled $disabled_skipped, dispatched $dispatched"

if [[ $dispatched -eq 0 ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] logic-error

When all stage-matched workflows are disabled (dispatched==0, disabled_skipped>0), the warning branch does not exit or skip the final echo. Execution falls through to 'Successfully dispatched 0 workflow(s) for stage ...' — a misleading success message. The control flow is fragile: future code appended after the success echo would execute in the all-disabled case without a guard.

Suggested fix: Add exit 0 after the all-disabled warning (inside the if [[ $disabled_skipped -gt 0 ]] branch), or restructure as if/elif/else so the success message only prints when dispatched>0.

if ! output=$(gh workflow run "$workflow_name" "${DISPATCH_ARGS[@]}" 2>&1); then
echo "::error::Failed to dispatch $workflow_name: $output"
exit 1
if echo "$output" | grep -qi 'disabled workflow'; then

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] edge-case

Disabled-workflow detection relies on grep -qi 'disabled workflow' against gh CLI stderr. This matches the current error format but depends on an uncontrolled third-party string that could change between CLI versions. If the wording changes, the fallback is fail-closed (exit 1), which is safe.

echo "Scanned $scanned workflow(s), skipped $skipped, dispatched $dispatched"
echo "Scanned $scanned workflow(s), skipped $skipped, disabled $disabled_skipped, dispatched $dispatched"

if [[ $dispatched -eq 0 ]]; then

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] fail-open

When all workflows for a stage are disabled, dispatch exits 0 with only a ::warning::. The stage's event is effectively dropped — upstream callers see success though no agent ran. Intentional per #5339 but creates a silent-failure path.

Suggested fix: Consider emitting an output variable (e.g., dispatched_count=0) so upstream callers can detect the all-disabled case.

disabled_skipped=$((disabled_skipped + 1))
continue
else
echo "::error::Failed to dispatch $workflow_name: $output"

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] injection

Pre-existing (not introduced by this PR): $output (gh CLI stderr) is interpolated unsanitized into ::error:: and ::notice:: workflow commands. The new disabled-workflow code path does not interpolate $output into any new commands.

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

Labels

ready-for-review Agent PR ready for human review requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Per-org dispatch should gracefully skip disabled target workflows instead of failing

0 participants