Investigation: Cancelled workflow status issue cannot be fixed at workflow level#1254
Conversation
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR attempts to address the issue where cancelled workflow jobs (from PR #1250's concurrency groups) appear as "failed" with red X icons in branch protection and status checks. The proposed solution adds a final step to each workflow job that runs on cancellation and exits successfully.
Changes:
- Added cancellation handler steps to 4 workflow files (unittest.yml, lint.yml, codeql-analysis.yml, pypi-publish.yml)
- Each handler uses
if: always() && cancelled()condition withexit 0to mark as success - Total of 7 jobs modified across the workflows
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| .github/workflows/unittest.yml | Added cancellation handler to unittest job |
| .github/workflows/lint.yml | Added cancellation handler to ruff job |
| .github/workflows/codeql-analysis.yml | Added cancellation handler to analyze job |
| .github/workflows/pypi-publish.yml | Added cancellation handlers to echo_github_env, check_build_trigger, build, and publish_pypi jobs |
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
|
|
||
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | ||
| # When job is cancelled by concurrency, this step ensures success status | ||
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | |
| # When job is cancelled by concurrency, this step ensures success status | |
| - name: Ensure success on cancellation | |
| if: always() && cancelled() | |
| run: | | |
| echo "Job was cancelled - marking as success to avoid misleading red X" | |
| exit 0 |
There was a problem hiding this comment.
You're correct - the approach is ineffective. Reverted in 857e1f2.
|
|
||
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | ||
| # When job is cancelled by concurrency, this step ensures success status | ||
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | |
| # When job is cancelled by concurrency, this step ensures success status | |
| - name: Ensure success on cancellation | |
| if: always() && cancelled() | |
| run: | | |
| echo "Job was cancelled - marking as success to avoid misleading red X" | |
| exit 0 |
|
|
||
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | ||
| # When job is cancelled by concurrency, this step ensures success status | ||
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
| # Ensure cancelled jobs don't show as failed (red X) in PR checks | |
| # When job is cancelled by concurrency, this step ensures success status | |
| - name: Ensure success on cancellation | |
| if: always() && cancelled() | |
| run: | | |
| echo "Job was cancelled - marking as success to avoid misleading red X" | |
| exit 0 |
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
| - name: Ensure success on cancellation | ||
| if: always() && cancelled() | ||
| run: | | ||
| echo "Job was cancelled - marking as success to avoid misleading red X" | ||
| exit 0 |
There was a problem hiding this comment.
This approach does not achieve the intended goal. When a workflow job is cancelled by GitHub Actions (via concurrency groups), the entire job is cancelled immediately and no subsequent steps run - including steps with if: always() && cancelled(). The job conclusion remains "cancelled" regardless of this step.
According to GitHub Actions documentation, when a job is cancelled:
- GitHub sends a SIGINT/SIGTERM to the runner
- After a grace period, the runner forcibly terminates all processes
- No further steps execute, even with
if: always()
The fundamental issue is that branch protection rules and status checks treat "cancelled" jobs as failed (red X). However, this cannot be worked around at the workflow level - it requires either:
- Accepting cancelled jobs as a legitimate status
- Removing
cancel-in-progress: truefrom concurrency groups - Configuring branch protection to not require these checks for cancelled runs (not currently supported by GitHub)
This step will never execute when the job is actually cancelled, making it ineffective.
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Reverted all cancellation handling changes in commit 857e1f2. The approach doesn't work because cancelled jobs terminate immediately without executing subsequent steps, even with |
|



What do these changes do
This PR investigated approaches to prevent cancelled GitHub Actions jobs from appearing as "failed" with red X icons in branch protection and status checks.
What was wrong
PR #1250 added
cancel-in-progress: trueto deduplicate concurrent workflow runs. When jobs are cancelled, they appear as "failed" with red X icons in some contexts (branch protection, status checks), misleading users about actual failures.How this fixes it
Investigation Result: After implementation and code review, it was determined that this issue cannot be solved at the workflow level.
The attempted solution was to add a final step to each workflow job:
However, this approach does not work because when a job is cancelled by GitHub Actions:
if: always() && cancelled()All changes have been reverted. The issue requires one of these alternative approaches:
cancel-in-progress: truefrom concurrency groups (restoring duplicate runs)Your checklist for this pull request
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.