Skip to content

Antalya 26.8 - Store the submodule cache in Hetzner Object Storage - #2740

Merged
strtgbb merged 4 commits into
antalya-26.8from
feature/antalya-26.8/hetzner-submodule-cache
Oct 31, 2026
Merged

strtgbb merged 4 commits into
antalya-26.8from
feature/antalya-26.8/hetzner-submodule-cache

Conversation

@strtgbb

@strtgbb strtgbb commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Reduce egress costs associated with the new submodule cache.
Sccache and LTO cache can also be moved after this PR.

Changelog category (leave one):

  • CI Fix or Improvement (changelog entry is not required)

CI/CD Options

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Unit tests
  • Performance tests
  • Aarch64 tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • CAS (content-addressed storage; Antalya only)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • OAuth (5m)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

Most runners are in Hetzner, so every job that downloads the submodule
archive from AWS S3 pays egress. Keep the archive in a Hetzner bucket
instead.

Buckets listed in `S3_EXTERNAL_BUCKETS` are served by a boto3 client with
their own endpoint and credentials. `S3.put` and `S3.head_object` use it
for those buckets, and keep using the AWS CLI for every other bucket. With
`public_read`, reads are unsigned, so community PRs can use the archive
without credentials; they never create it. A missing credential is an
error, so ambient AWS credentials are never sent to the Hetzner endpoint.

The archive is public, so `_prepare_submodule_cache` refuses to upload it
if the clone token ended up in a git config file.

The workflows export `HETZNER_S3_ACCESS_KEY` and `HETZNER_S3_SECRET_KEY`
from GitHub secrets. The bucket is `altinity-builds-cache` in hel1.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@strtgbb strtgbb added antalya cicd Improvements and fixes to the CICD process port-everywhere PRs that must be ported to every other version branch backport-ci Change that should be ported to earlier CI versions antalya-26.8 Session label (releasy session config) labels Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Workflow [PR], commit [8451c27]

strtgbb and others added 2 commits October 29, 2026 16:04
The first CI run failed with a 403 on the existence check for the
submodule archive. The bucket is public for object reads, but answers a
HEAD of a missing key with 403 to callers who cannot list it. The config
job read the bucket unsigned because the bucket is marked `public_read`,
even though it has the keys.

Reads are now unsigned only for jobs without the bucket's keys. Those
jobs treat a 403 from `head_object` as a miss; jobs with the keys use a
signed client, so a 403 is still an error for them.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The Altinity PR workflow has full-suite sanitizer jobs that use CAS storage
(`Stateless tests (amd_asan_ubsan, cas s3 storage, ...)`), which the test
rejected as unexpected full-suite jobs. It failed in every CI run, including
without other changes.

Related: https://github.com/Altinity/ClickHouse/actions/runs/41066953900

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@strtgbb strtgbb added the verified Approved for release label Oct 30, 2026
strtgbb added a commit that referenced this pull request Oct 30, 2026
Attached volumes tied the cache to whichever builder a job landed on, and
the runner scaler never reused a volume for builders made from a snapshot
image. The cache now travels as one archive per branch, build type and
debug-info flavour in the Hetzner bucket from the submodule cache:
`altinity-builds-cache/ci_ch_cache/thinlto/<branch>/<build type>-<g|g0>.tar.zst`.

Every ThinLTO build that links restores the archive before `ninja`. PR
builds use their base branch's archive. Pushes and internal PRs then
upload it again, so `-g` archives come from `MasterCI` and `-g0` ones from
PR builds; community PRs read anonymously and write nothing, like the
shared compiler cache. The cache-warmup builds only compile, so they skip
it.

The upload keeps exactly the entries the build used: restored entries get
an access time of zero, so under `relatime` the next read sets it, and the
entries still at zero are dropped before compressing with `zstd --long`.
That keeps an archive at one build's working set, about 15 GB raw for `-g`,
and lld's own pruning is off. A restore that fails leaves an empty cache
rather than a partly extracted one, and an archive over 20 GB (`-g`) or
5 GB (`-g0`) is not uploaded.

This removes the praktika `--volume-if-exists` setting, the cache mounts
and the per-target builder labels, and puts `amd_cfi` and the cache-warmup
builds back on `ARM_LARGE`.

Related: #2740

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@strtgbb
strtgbb merged commit d6fa825 into antalya-26.8 Oct 31, 2026
258 of 261 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

antalya antalya-26.8 Session label (releasy session config) backport-ci Change that should be ported to earlier CI versions cicd Improvements and fixes to the CICD process port-everywhere PRs that must be ported to every other version branch verified Approved for release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant