diff --git a/.claude/tools/fetch_ci_report.js b/.claude/tools/fetch_ci_report.js index 09b4cab3d82d4..4803a71b7c7b8 100755 --- a/.claude/tools/fetch_ci_report.js +++ b/.claude/tools/fetch_ci_report.js @@ -574,14 +574,16 @@ async function getCIReportsFromPR(prUrl) { console.log(`Fetching CI reports for PR #${prNumber}...\n`); - // Fetch PR comments to find CI bot comment. + // Report URLs are the signal — do not filter by bot login. + // Altinity posts via github-actions[bot] with the virtual-hosted S3 URL; + // older comments used clickhouse-gh[bot] and path-style S3. // Drop GH_CONFIG_DIR before spawning gh: some agent/runner checkouts set it to a poisoned // config dir (no/expired auth) that makes `gh api` fail, while the default config is fine. // Other repo tooling (patch-release-check) does the same via `env -u GH_CONFIG_DIR gh`. const ghEnv = { ...process.env }; delete ghEnv.GH_CONFIG_DIR; try { - const commentsJson = execSync(`gh api repos/Altinity/ClickHouse/issues/${prNumber}/comments --paginate --jq '.[] | select(.user.login == "clickhouse-gh[bot]") | {body, created_at}'`, { + const commentsJson = execSync(`gh api repos/Altinity/ClickHouse/issues/${prNumber}/comments --paginate --jq '.[] | {body, created_at}'`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], env: ghEnv @@ -589,15 +591,12 @@ async function getCIReportsFromPR(prUrl) { const comments = commentsJson.trim().split('\n').filter(l => l.trim()).map(l => JSON.parse(l)); comments.sort((a, b) => (b.created_at || '').localeCompare(a.created_at || '')); - if (!comments || comments.length === 0) { - throw new Error('No CI bot comment found'); - } - // Search through all bot comments for CI report URLs (not just the latest). Exclude backtick and + // Search through all comments for CI report URLs (not just the latest). Exclude backtick and // quote chars so a URL quoted in markdown (e.g. inside the AI-review text) is not captured with // trailing junk, strip trailing punctuation, and dedupe -- otherwise the same report is fetched - // twice and the summary is doubled. - const reportUrlPattern = /https:\/\/s3\.amazonaws\.com\/altinity-build-artifacts\/json\.html\?[^\s)`'"]+/g; + // twice and the summary is doubled. Match both path-style and virtual-hosted S3 URLs. + const reportUrlPattern = /https:\/\/(?:s3\.amazonaws\.com\/altinity-build-artifacts|altinity-build-artifacts\.s3\.amazonaws\.com)\/json\.html\?[^\s)`'"]+/g; for (const comment of comments) { if (!comment.body) continue; let urls = comment.body.match(reportUrlPattern); @@ -607,9 +606,9 @@ async function getCIReportsFromPR(prUrl) { } } - throw new Error('No CI report URLs found in bot comments'); + throw new Error('No CI report URLs found in PR comments'); } catch (error) { - if (error.message.includes('No CI bot comment found') || error.message.includes('No CI report URLs found')) { + if (error.message.includes('No CI report URLs found')) { throw error; } throw new Error(`Failed to fetch PR comments: ${error.message}`); diff --git a/.github/actions/create_workflow_report/create_workflow_report.py b/.github/actions/create_workflow_report/create_workflow_report.py index 4cad8779a9140..dde3813ea7dd1 100755 --- a/.github/actions/create_workflow_report/create_workflow_report.py +++ b/.github/actions/create_workflow_report/create_workflow_report.py @@ -192,6 +192,9 @@ def _enrich_prs_in_release_merge_prs(df: pd.DataFrame, repo: str) -> pd.DataFram f"https://api.github.com/repos/{repo}/pulls/{pr_number}", headers=headers, ) + if response.status_code == 404: + # NOTE (strtgbb): not in this repo — upstream PR merged from a fork + continue if response.status_code != 200: raise Exception( f"Failed to fetch pull request info: {response.status_code} {response.text}" @@ -207,6 +210,8 @@ def _enrich_prs_in_release_merge_prs(df: pd.DataFrame, repo: str) -> pd.DataFram "pr_labels": html.escape(", ".join(sorted(label_names)), quote=True), } ) + if not rows: + return pd.DataFrame(columns=["pr_number", "pr_name", "pr_labels"]) return pd.DataFrame(rows) diff --git a/ci/jobs/integration_test_job.py b/ci/jobs/integration_test_job.py index df0a298ed7753..4ccac05dc242e 100644 --- a/ci/jobs/integration_test_job.py +++ b/ci/jobs/integration_test_job.py @@ -1329,7 +1329,7 @@ def main(): # hard subprocess backstop). Used below to keep an empty flaky/targeted result a # best-effort SKIPPED only when a timeout actually exhausted the budget. timed_out = False - session_timeout_parallel = 3600 * 2 + session_timeout_parallel = 3600 * 2.5 session_timeout_sequential = 3600 if is_llvm_coverage: diff --git a/ci/jobs/scripts/stress/stress.py b/ci/jobs/scripts/stress/stress.py index b4e8b47141fd0..793e71d1d8d70 100755 --- a/ci/jobs/scripts/stress/stress.py +++ b/ci/jobs/scripts/stress/stress.py @@ -400,7 +400,13 @@ def install_thread_pool_fault_injection() -> None: logging.info("Installing thread-pool fault-injection config: %s -> %s", src, dst) subprocess.run(["ln", "-sf", src, dst], check=True) - if not call_with_retry(make_query_command("SYSTEM RELOAD CONFIG"), timeout=30, retry_count=5): + # NOTE (strtgbb): ARM debug + ThreadFuzzer config reload is ~18-23s; the + # default 15s receive_timeout loses the race and fails the job. + if not call_with_retry( + make_query_command("SYSTEM RELOAD CONFIG", receive_timeout=60), + timeout=90, + retry_count=5, + ): # Fail-close before the verify query: a stale non-zero probability left # over from an earlier reload would otherwise mask the reload failure. raise RuntimeError( @@ -655,9 +661,9 @@ def execute_bash(full_command, timeout=120): raise -def make_query_command(query: str) -> str: +def make_query_command(query: str, receive_timeout: int = 15) -> str: return ( - f'clickhouse client -q "{query}" --receive_timeout=15 --max_untracked_memory=1Gi ' + f'clickhouse client -q "{query}" --receive_timeout={receive_timeout} --max_untracked_memory=1Gi ' "--memory_profiler_step=1Gi --max_memory_usage_for_user=0 --max_memory_usage_in_client=1000000000 " "--enable-progress-table-toggle=0 " "--ast_fuzzer_runs=0", diff --git a/ci/praktika/native_jobs.py b/ci/praktika/native_jobs.py index 804b2805a9041..e6c9a673f43cd 100644 --- a/ci/praktika/native_jobs.py +++ b/ci/praktika/native_jobs.py @@ -292,6 +292,8 @@ def _prepare_submodule_cache(workflow, workflow_config: RunConfig) -> Result: no_strict=True, ) Shell.check(f"rm -f {archive_path}") + if not created and not S3.head_object(s3_path): + raise RuntimeError(f"failed to upload submodule cache {s3_path}") info = ( f"cache miss, created: {cache_hash}" if created @@ -302,10 +304,12 @@ def _prepare_submodule_cache(workflow, workflow_config: RunConfig) -> Result: workflow_config.dump() status = Result.Status.OK except Exception as e: - print(f"WARNING: Submodule cache failed: {e}") + print(f"ERROR: Submodule cache failed: {e}") traceback.print_exc() info = f"{e}\n{traceback.format_exc()}" - status = Result.Status.OK # non-fatal, jobs fall back to GitHub clone + # Do not continue with an empty submodule_cache_hash. Builds would + # skip the restore and clone the same pins themselves. + status = Result.Status.FAIL return Result.create_from( name="Submodule Cache", diff --git a/ci/settings/altinity_overrides.py b/ci/settings/altinity_overrides.py index 4221ccf17b87b..9e965980b8ef5 100644 --- a/ci/settings/altinity_overrides.py +++ b/ci/settings/altinity_overrides.py @@ -59,6 +59,10 @@ class RunnerLabels: INSTALL_PYTHON_REQS_FOR_NATIVE_JOBS = "" +# NOTE (strtgbb): anonymous submodule fetches of non-tip pins get refused +# after the burst of ~150 clones; send the ambient gh token instead. +ENABLE_SUBMODULE_CLONE_AUTH = True + DISABLED_WORKFLOWS = [ "backport_branches.py", "custom_build_praktika.py", diff --git a/cmake/autogenerated_versions.txt b/cmake/autogenerated_versions.txt index 581fe1859c695..8820579f055f9 100644 --- a/cmake/autogenerated_versions.txt +++ b/cmake/autogenerated_versions.txt @@ -7,10 +7,9 @@ SET(VERSION_MAJOR 26) SET(VERSION_MINOR 8) SET(VERSION_PATCH 6) SET(VERSION_GITHASH ec5605431dacfc812affc406cc81ca398ca68174) -SET(VERSION_DESCRIBE v26.8.6.10001.altinitytest) -SET(VERSION_STRING 26.8.6.10001.altinitytest) +SET(VERSION_DESCRIBE v26.8.6.20001.altinityantalya) +SET(VERSION_STRING 26.8.6.20001.altinityantalya) # end of autochange -SET(VERSION_TWEAK 10001) -SET(VERSION_FLAVOUR altinitytest) - +SET(VERSION_TWEAK 20001) +SET(VERSION_FLAVOUR altinityantalya) diff --git a/tests/docker_scripts/stress_runner.sh b/tests/docker_scripts/stress_runner.sh index 1fdaee27310e2..0d013452f68a7 100755 --- a/tests/docker_scripts/stress_runner.sh +++ b/tests/docker_scripts/stress_runner.sh @@ -97,7 +97,9 @@ if [ "$cache_policy" = "SLRU" ]; then sed -i.tmp "s|LRU|SLRU|" /etc/clickhouse-server/config.d/storage_conf*.xml fi -start_server || { echo "Failed to start server"; exit 1; } +# Preload writes system logs the restart must load before port 9000 opens. +# The default wait (~70s) expires first on some ARM runners. +start_server 10 || { echo "Failed to start server"; exit 1; } clickhouse-client --query "SYSTEM STOP THREAD FUZZER" @@ -302,7 +304,9 @@ fi # hang the server under sanitizers and trip the hung check. cp -av --dereference /repo/ci/jobs/scripts/fuzzer/limit-recursion-settings.xml /etc/clickhouse-server/users.d/ -start_server || { echo "Failed to start server"; exit 1; } +# Same wait as the other restarts: ARM sanitizer + S3 + async_load_databases=false +# can miss the default ~70s window before port 9000 opens. +start_server 10 || { echo "Failed to start server"; exit 1; } # clickhouse-test must know which storage backend the server actually uses, or its storage skip # tags are inert and incompatible tests run on an unsupported backend. Both variables are already diff --git a/tests/integration/test_s3_cluster/test.py b/tests/integration/test_s3_cluster/test.py index 00978fb7231c9..cb18b7a643072 100644 --- a/tests/integration/test_s3_cluster/test.py +++ b/tests/integration/test_s3_cluster/test.py @@ -1729,8 +1729,9 @@ def query_cycle(): node_to_shutdown.query("SYSTEM STOP SWARM MODE") - # enough time to complete processing of objects, started before "SYSTEM STOP SWARM MODE" - time.sleep(3) + # Drain in-flight objects started before STOP SWARM. Query time is 3-4s + # normally; TSan is several times slower, so 3s is not enough. + time.sleep(15) node_to_shutdown.stop_clickhouse(kill=True) diff --git a/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.reference b/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.reference index e307b0ef6ae99..0bf9c660e01aa 100644 --- a/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.reference +++ b/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.reference @@ -2,32 +2,32 @@ Create tables with Array(Float32) and Array(BFloat16) column Column: Array(Float32) -- Search vector: Array(Float64) 5 0 -6 0.09375 -7 0.203125 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 -- Search vector: Array(Float32) 5 0 -6 0.09375 -7 0.203125 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 -- Search vector: Array(BFloat16) 5 0 -6 0.09375 -7 0.203125 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 Column: Array(BFloat16) -- Search vector: Array(Float64) 5 0 -6 0.09375 -7 0.1875 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 -- Search vector: Array(Float32) 5 0 -6 0.09375 -7 0.1875 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 -- Search vector: Array(BFloat16) 5 0 -6 0.09375 -7 0.1875 -8 0.296875 +6 0.1 +7 0.2 +8 0.3 diff --git a/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.sql b/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.sql index c4aa1debd8651..d7797d8113534 100644 --- a/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.sql +++ b/tests/queries/0_stateless/02354_vector_search_rescoring_distance_in_select_list.sql @@ -60,26 +60,28 @@ INSERT INTO tab_bf16 VALUES (0, [1.0, 0.0]), (9, [0.0, 2.4]); -- The nearest neighbours to [0.0, 0.2] are 5,6,7,8 +-- Round distances: ARM sanitizer builds disable SimSIMD and scalar USearch +-- differs in the 3rd decimal (0.203125 vs 0.1875). Neighbor order is unchanged. SELECT 'Column: Array(Float32)'; SELECT '-- Search vector: Array(Float64)'; WITH CAST([0.0, 2.0] AS Array(Float64)) AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_f32 ORDER BY L2Distance(vec, reference_vec) LIMIT 4; SELECT '-- Search vector: Array(Float32)'; WITH CAST([0.0, 2.0] AS Array(BFloat16)) AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_f32 ORDER BY L2Distance(vec, reference_vec) LIMIT 4; SELECT '-- Search vector: Array(BFloat16)'; WITH CAST([0.0, 2.0] AS Array(BFloat16)) AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_f32 ORDER BY L2Distance(vec, reference_vec) LIMIT 4; @@ -88,21 +90,21 @@ SELECT 'Column: Array(BFloat16)'; SELECT '-- Search vector: Array(Float64)'; WITH [0.0, 2.0] AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_bf16 ORDER BY L2Distance(vec, reference_vec) LIMIT 4; SELECT '-- Search vector: Array(Float32)'; WITH CAST([0.0, 2.0] AS Array(BFloat16)) AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_bf16 ORDER BY L2Distance(vec, reference_vec) LIMIT 4; SELECT '-- Search vector: Array(BFloat16)'; WITH CAST([0.0, 2.0] AS Array(Float32)) AS reference_vec -SELECT id, L2Distance(vec, reference_vec) +SELECT id, round(L2Distance(vec, reference_vec), 1) FROM tab_bf16 ORDER BY L2Distance(vec, reference_vec) LIMIT 4;