Skip to content

Investigation: Cancelled workflow status issue cannot be fixed at workflow level - #1254

Closed
bact with Copilot wants to merge 5 commits into
devfrom
copilot/fix-job-cancellation-status
Closed

Investigation: Cancelled workflow status issue cannot be fixed at workflow level#1254
bact with Copilot wants to merge 5 commits into
devfrom
copilot/fix-job-cancellation-status

Conversation

Copilot AI commented Feb 1, 2026

Copy link
Copy Markdown
Contributor

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: true to 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:

- name: Ensure success on cancellation
  if: always() && cancelled()
  run: |
    echo "Job was cancelled - marking as success to avoid misleading red X"
    exit 0

However, this approach does not work because when a job is cancelled by GitHub Actions:

  1. GitHub sends SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. No further steps execute, even with if: always() && cancelled()

All changes have been reverted. The issue requires one of these alternative approaches:

  1. Accept cancelled jobs as a legitimate status in branch protection
  2. Remove cancel-in-progress: true from concurrency groups (restoring duplicate runs)
  3. Configure branch protection to not require these checks for cancelled runs (not currently supported by GitHub)

Your checklist for this pull request

  • Passed code styles and structures
  • Passed code linting checks and unit test
Original prompt

Same group conditions and job cancellation added by #1250 help reduce the unnecessary runs (double run).

But the side effect is, once job got cancelled, the check status will be considered "failed" with red 'x' icon - instead of green check icon. This can be misleading.

How to deal with this?


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 3 commits February 1, 2026 23:11
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>
Copilot AI changed the title [WIP] Fix misleading job cancellation status icon Fix cancelled workflow status to prevent misleading failure indicators Feb 1, 2026
Copilot AI requested a review from bact February 1, 2026 23:17
@bact
bact requested a review from Copilot February 1, 2026 23:27
@bact
bact marked this pull request as ready for review February 1, 2026 23:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 with exit 0 to 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

Comment thread .github/workflows/pypi-publish.yml Outdated
Comment on lines +114 to +118
- name: Ensure success on cancellation
if: always() && cancelled()
run: |
echo "Job was cancelled - marking as success to avoid misleading red X"
exit 0

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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 uses AI. Check for mistakes.
Comment thread .github/workflows/pypi-publish.yml Outdated
Comment on lines +141 to +145
- name: Ensure success on cancellation
if: always() && cancelled()
run: |
echo "Job was cancelled - marking as success to avoid misleading red X"
exit 0

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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 uses AI. Check for mistakes.
Comment thread .github/workflows/unittest.yml Outdated
Comment on lines +156 to +163

# 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

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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.

Suggested change
# 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

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're correct - the approach is ineffective. Reverted in 857e1f2.

Comment thread .github/workflows/lint.yml Outdated
Comment on lines +52 to +59

# 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

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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.

Suggested change
# 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

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/codeql-analysis.yml Outdated
Comment on lines +95 to +102

# 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

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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.

Suggested change
# 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

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/pypi-publish.yml Outdated
Comment on lines +47 to +51
- name: Ensure success on cancellation
if: always() && cancelled()
run: |
echo "Job was cancelled - marking as success to avoid misleading red X"
exit 0

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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 uses AI. Check for mistakes.
Comment thread .github/workflows/pypi-publish.yml Outdated
Comment on lines +73 to +77
- name: Ensure success on cancellation
if: always() && cancelled()
run: |
echo "Job was cancelled - marking as success to avoid misleading red X"
exit 0

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

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

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:

  1. GitHub sends a SIGINT/SIGTERM to the runner
  2. After a grace period, the runner forcibly terminates all processes
  3. 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:

  1. Accepting cancelled jobs as a legitimate status
  2. Removing cancel-in-progress: true from concurrency groups
  3. 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 uses AI. Check for mistakes.
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 64.647%. remained the same
when pulling 1c9138d on copilot/fix-job-cancellation-status
into 78d3ee4 on dev.

@bact

bact commented Feb 1, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Co-authored-by: bact <128572+bact@users.noreply.github.com>

Copilot AI commented Feb 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

Reverted all cancellation handling changes in commit 857e1f2. The approach doesn't work because cancelled jobs terminate immediately without executing subsequent steps, even with if: always() && cancelled(). The issue cannot be solved at the workflow level and requires accepting cancelled status or removing cancel-in-progress: true.

@sonarqubecloud

sonarqubecloud Bot commented Feb 1, 2026

Copy link
Copy Markdown

Copilot AI changed the title Fix cancelled workflow status to prevent misleading failure indicators Investigation: Cancelled workflow status issue cannot be fixed at workflow level Feb 1, 2026
@bact bact closed this Feb 1, 2026
@bact
bact deleted the copilot/fix-job-cancellation-status branch February 2, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants