From 1c0a09ba8645b40c467a62a511a997d9a5e4f51a Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 27 Aug 2026 12:49:07 +0800 Subject: [PATCH 1/6] ci: only cancel the Delta Spark UT run for a real /delta-test comment --- .github/workflows/delta_spark_ut.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/delta_spark_ut.yml b/.github/workflows/delta_spark_ut.yml index e7525f5be7..ac7aeb3573 100644 --- a/.github/workflows/delta_spark_ut.yml +++ b/.github/workflows/delta_spark_ut.yml @@ -151,7 +151,19 @@ env: # Cancel older `pull_request` and `/delta-test` runs for the same PR. concurrency: group: ${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number || github.head_ref || github.sha }}-${{ github.workflow }} - cancel-in-progress: true + # `issue_comment` fires on every comment, and for such an event + # `github.event.issue.number` puts the run in the same group as that PR's + # `pull_request` run. Cancelling unconditionally therefore lets any unrelated + # comment kill an in-flight suite, which the comment run then does not replace + # because `delta-test-requested` below skips it. Only a real `/delta-test` + # command should cancel, so this repeats that job's `if` verbatim. + cancel-in-progress: >- + ${{ github.event_name != 'issue_comment' || + (github.event.issue.pull_request && + (github.event.comment.body == '/delta-test' || + startsWith(github.event.comment.body, '/delta-test ') || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\r"'))) || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\n"'))))) }} jobs: delta-test-requested: From af5e68b4029c2e68300e855a1daec6115db97ef3 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 27 Aug 2026 13:45:53 +0800 Subject: [PATCH 2/6] ci: give a non-command comment run its own concurrency group Conditioning cancel-in-progress instead would leave the run pending until the in-flight suite ends, up to timeout-minutes: 350, showing as an unresolved check the whole time. Taking it out of the group keeps today's behaviour for the two cases the group exists for and removes only the collateral cancellation. --- .github/workflows/delta_spark_ut.yml | 34 ++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/workflows/delta_spark_ut.yml b/.github/workflows/delta_spark_ut.yml index ac7aeb3573..1fa922aca7 100644 --- a/.github/workflows/delta_spark_ut.yml +++ b/.github/workflows/delta_spark_ut.yml @@ -149,21 +149,27 @@ env: DELTA_NUM_SHARDS: '8' # Cancel older `pull_request` and `/delta-test` runs for the same PR. +# +# `issue_comment` fires for every comment, and for that event +# `github.event.issue.number` is the PR number, so without the trailing +# discriminator such a run joins the PR's group and `cancel-in-progress` kills an +# in-flight suite. Leaving it in the group but not cancelling is no better: the +# run would sit `pending` until the suite ends, up to the shards' +# `timeout-minutes: 350`. All a non-command comment run ever does is skip in +# `delta-test-requested`, so give it a group to itself. The condition repeats +# that job's `if` verbatim, so `pull_request` runs and real `/delta-test` runs +# keep sharing one group per PR exactly as before. concurrency: - group: ${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number || github.head_ref || github.sha }}-${{ github.workflow }} - # `issue_comment` fires on every comment, and for such an event - # `github.event.issue.number` puts the run in the same group as that PR's - # `pull_request` run. Cancelling unconditionally therefore lets any unrelated - # comment kill an in-flight suite, which the comment run then does not replace - # because `delta-test-requested` below skips it. Only a real `/delta-test` - # command should cancel, so this repeats that job's `if` verbatim. - cancel-in-progress: >- - ${{ github.event_name != 'issue_comment' || - (github.event.issue.pull_request && - (github.event.comment.body == '/delta-test' || - startsWith(github.event.comment.body, '/delta-test ') || - startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\r"'))) || - startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\n"'))))) }} + group: >- + ${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number || github.head_ref || github.sha }}-${{ github.workflow }}-${{ + (github.event_name != 'issue_comment' || + (github.event.issue.pull_request && + (github.event.comment.body == '/delta-test' || + startsWith(github.event.comment.body, '/delta-test ') || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\r"'))) || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\n"')))))) + && 'shared' || github.run_id }} + cancel-in-progress: true jobs: delta-test-requested: From 0c1cb09b5305ffae8f9585ecfc2bb70b944c0792 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 27 Aug 2026 14:00:18 +0800 Subject: [PATCH 3/6] ci: append the discriminator only for a non-command comment run Keeps the group name byte-identical to main for every other trigger, so PRs open at merge time do not land in a window where a push run and a /delta-test run sit in different groups and stop superseding each other. --- .github/workflows/delta_spark_ut.yml | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/.github/workflows/delta_spark_ut.yml b/.github/workflows/delta_spark_ut.yml index 1fa922aca7..c7b2d535b6 100644 --- a/.github/workflows/delta_spark_ut.yml +++ b/.github/workflows/delta_spark_ut.yml @@ -150,25 +150,23 @@ env: # Cancel older `pull_request` and `/delta-test` runs for the same PR. # -# `issue_comment` fires for every comment, and for that event -# `github.event.issue.number` is the PR number, so without the trailing -# discriminator such a run joins the PR's group and `cancel-in-progress` kills an -# in-flight suite. Leaving it in the group but not cancelling is no better: the -# run would sit `pending` until the suite ends, up to the shards' -# `timeout-minutes: 350`. All a non-command comment run ever does is skip in -# `delta-test-requested`, so give it a group to itself. The condition repeats -# that job's `if` verbatim, so `pull_request` runs and real `/delta-test` runs -# keep sharing one group per PR exactly as before. +# `issue_comment` fires on every comment created in the repo, and +# `github.event.issue.number` is that issue's number, which for a comment on a +# PR is the PR's own number. Such a run would therefore join the PR's group and +# cancel an in-flight suite while `delta-test-requested` below skips it, losing +# the suite and replacing it with nothing. Give only that case a group of its +# own, so every other trigger keeps the exact group name it has today. The +# negated condition is that job's `if` verbatim. concurrency: group: >- - ${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number || github.head_ref || github.sha }}-${{ github.workflow }}-${{ - (github.event_name != 'issue_comment' || - (github.event.issue.pull_request && - (github.event.comment.body == '/delta-test' || - startsWith(github.event.comment.body, '/delta-test ') || - startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\r"'))) || - startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\n"')))))) - && 'shared' || github.run_id }} + ${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number || github.head_ref || github.sha }}-${{ github.workflow }}${{ + !(github.event_name != 'issue_comment' || + (github.event.issue.pull_request && + (github.event.comment.body == '/delta-test' || + startsWith(github.event.comment.body, '/delta-test ') || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\r"'))) || + startsWith(github.event.comment.body, format('/delta-test{0}', fromJSON('"\n"')))))) + && format('-comment-{0}', github.run_id) || '' }} cancel-in-progress: true jobs: From 74d189a9ae0919105d75856d7ab09b59ed5debac Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 27 Aug 2026 14:09:16 +0800 Subject: [PATCH 4/6] ci: say issue or PR comment, since review and commit comments use other events --- .github/workflows/delta_spark_ut.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delta_spark_ut.yml b/.github/workflows/delta_spark_ut.yml index c7b2d535b6..b1d37e64d3 100644 --- a/.github/workflows/delta_spark_ut.yml +++ b/.github/workflows/delta_spark_ut.yml @@ -150,7 +150,7 @@ env: # Cancel older `pull_request` and `/delta-test` runs for the same PR. # -# `issue_comment` fires on every comment created in the repo, and +# `issue_comment` fires on every comment posted on an issue or a PR, and # `github.event.issue.number` is that issue's number, which for a comment on a # PR is the PR's own number. Such a run would therefore join the PR's group and # cancel an in-flight suite while `delta-test-requested` below skips it, losing From 80c86608f00e35dae11314861fe26d4bca5b3388 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 27 Aug 2026 16:42:01 +0800 Subject: [PATCH 5/6] ci: apply the same group discriminator to velox_backend_ansi.yml Same shape as delta_spark_ut.yml: any comment on a PR joined the ANSI group and cancelled an in-flight /ansi-test or /ansi-analyze run, then skipped in check-comment. Fixes the case reported in #12908. --- .github/workflows/velox_backend_ansi.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/velox_backend_ansi.yml b/.github/workflows/velox_backend_ansi.yml index 2ed44123ce..64c158f96d 100644 --- a/.github/workflows/velox_backend_ansi.yml +++ b/.github/workflows/velox_backend_ansi.yml @@ -40,8 +40,20 @@ env: CCACHE_DIR: "${{ github.workspace }}/.ccache" SPARK_ANSI_SQL_MODE: true +# `issue_comment` fires on every comment posted on an issue or a PR, and +# `github.event.issue.number` puts such a run in the same group as an in-flight +# ANSI run for that PR, so `cancel-in-progress` kills it while `check-comment` +# below skips the newcomer, leaving no replacement. Give only that case a group +# of its own, so every other trigger keeps the exact group name it has today. +# The negated condition is that job's `if` verbatim. concurrency: - group: ${{ github.repository }}-ansi-${{ github.event.issue.number || inputs.pr_number }} + group: >- + ${{ github.repository }}-ansi-${{ github.event.issue.number || inputs.pr_number }}${{ + !((github.event_name == 'workflow_dispatch') || + (github.event.issue.pull_request && + (contains(github.event.comment.body, '/ansi-test') || + contains(github.event.comment.body, '/ansi-analyze')))) + && format('-comment-{0}', github.run_id) || '' }} cancel-in-progress: true jobs: From c6a6777d2b7ff0d8a1428336765137f2be4d7c6c Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Fri, 28 Aug 2026 12:24:47 +0800 Subject: [PATCH 6/6] ci: drop 32 now-passing entries from the Delta known-failures baseline Two complete eight-shard runs on this branch report the same 32 now-passing tests, byte-identical lists, with Stale and Skipped both zero. Deleted by hand rather than committing the regenerated artifact, which also replaces the hand-written header with an auto-generated stub. --- .../util/delta-spark-ut/known-failures.txt | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/.github/workflows/util/delta-spark-ut/known-failures.txt b/.github/workflows/util/delta-spark-ut/known-failures.txt index 14dfbfc22d..ba9f191a56 100644 --- a/.github/workflows/util/delta-spark-ut/known-failures.txt +++ b/.github/workflows/util/delta-spark-ut/known-failures.txt @@ -66,11 +66,6 @@ org.apache.spark.sql.delta.ConvertToDeltaScalaSuite#external tables use correct org.apache.spark.sql.delta.DeleteMetricsSuite#delete-metrics: delete one row per file - Partitioned = false, cdfEnabled = false org.apache.spark.sql.delta.DeleteMetricsSuite#delete-metrics: delete one row per file - Partitioned = false, cdfEnabled = true org.apache.spark.sql.delta.DeltaAllFilesInCrcSuite#test all-files-in-crc verification failure also triggers and logs incremental-commit verification result -org.apache.spark.sql.delta.DeltaAlterTableByNameIdColumnMappingSuite#CHANGE COLUMN - case insensitive - column mapping id mode -org.apache.spark.sql.delta.DeltaAlterTableByNameIdColumnMappingSuite#CHANGE COLUMN - move to first (nested) - column mapping id mode -org.apache.spark.sql.delta.DeltaAlterTableByNameNameColumnMappingSuite#CHANGE COLUMN - case insensitive - column mapping name mode -org.apache.spark.sql.delta.DeltaAlterTableByNameNameColumnMappingSuite#CHANGE COLUMN - move to first (nested) - column mapping name mode -org.apache.spark.sql.delta.DeltaArbitraryColumnNameSuite#create table org.apache.spark.sql.delta.DeltaCDCIdColumnMappingSuite#filters with special characters in name should be pushed down - column mapping id mode org.apache.spark.sql.delta.DeltaCDCNameColumnMappingSuite#filters with special characters in name should be pushed down - column mapping name mode org.apache.spark.sql.delta.DeltaCDCSQLIdColumnMappingSuite#filters with special characters in name should be pushed down - column mapping id mode @@ -89,11 +84,8 @@ org.apache.spark.sql.delta.DeltaCDCStreamSuite#cdc streams with noop merge org.apache.spark.sql.delta.DeltaCDCStreamWithCatalogManagedBatch100Suite#cdc streams with noop merge org.apache.spark.sql.delta.DeltaCDCStreamWithCatalogManagedBatch1Suite#cdc streams with noop merge org.apache.spark.sql.delta.DeltaCDCStreamWithCatalogManagedBatch2Suite#cdc streams with noop merge -org.apache.spark.sql.delta.DeltaColumnMappingSuite#add nested column in schema on new protocol -org.apache.spark.sql.delta.DeltaColumnMappingSuite#alter column order in schema on new protocol org.apache.spark.sql.delta.DeltaColumnMappingSuite#explicit id matching org.apache.spark.sql.delta.DeltaColumnMappingSuite#id and name mode should write field_id in parquet schema -org.apache.spark.sql.delta.DeltaColumnMappingSuite#try modifying restricted max id property should fail org.apache.spark.sql.delta.DeltaDataFrameHadoopOptionsSuite#SC-86916: Delta log cache should respect options org.apache.spark.sql.delta.DeltaDataFrameHadoopOptionsSuite#SC-86916: checkpoint should pick up Hadoop file system options org.apache.spark.sql.delta.DeltaDataFrameHadoopOptionsSuite#SC-86916: invalidateCache should invalidate all DeltaLogs of the given path @@ -645,30 +637,8 @@ org.apache.spark.sql.delta.stats.DataSkippingDeltaV1JsonCheckpointV2Suite#data s org.apache.spark.sql.delta.stats.DataSkippingDeltaV1JsonCheckpointV2Suite#data skipping on TIMESTAMP_NTZ with Long.MaxValue - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1JsonCheckpointV2Suite#data skipping stats before and after optimize org.apache.spark.sql.delta.stats.DataSkippingDeltaV1JsonCheckpointV2Suite#data skipping stats before and after optimize - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - double nested, single 1 - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - double nested, single 1 - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - backtick escapes work as expected - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - backtick escapes work as expected - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - index only a subset of leaf columns - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - index only a subset of leaf columns - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - naming a nested column allows nested complex types - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - naming a nested column allows nested complex types - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - naming a nested column indexes all leaf fields of that column - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - indexed column names - naming a nested column indexes all leaf fields of that column - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 3 - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 3 - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 6 - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 6 - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 9 - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested schema - # indexed column = 9 - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested, single 1 - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - nested, single 1 - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - starts with, nested - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping by stats - starts with, nested - column mapping name mode - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping flags - column mapping name mode org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping flags - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP - column mapping name mode - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP_NTZ - column mapping name mode org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP_NTZ - column mapping name mode - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP_NTZ near Long.MaxValue - column mapping name mode @@ -677,8 +647,6 @@ org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping on TIMESTAMP_NTZ with Long.MaxValue - column mapping name mode - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping stats before and after optimize - column mapping name mode org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping stats before and after optimize - column mapping name mode - old behavior with DataFrame schema -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping with a different DataFrame schema order and nested columns - column mapping name mode -org.apache.spark.sql.delta.stats.DataSkippingDeltaV1NameColumnMappingSuite#data skipping with missing columns in DataFrame - column mapping name mode org.apache.spark.sql.delta.stats.DataSkippingDeltaV1ParquetCheckpointV2Suite#Data skipping handles aliasing for _metadata fields org.apache.spark.sql.delta.stats.DataSkippingDeltaV1ParquetCheckpointV2Suite#Data skipping handles aliasing for _metadata fields - old behavior with DataFrame schema org.apache.spark.sql.delta.stats.DataSkippingDeltaV1ParquetCheckpointV2Suite#data skipping flags