pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feedci: CCache churns through available space too quickly
8+ messages / 5 participants
[nested] [flat]
* ci: CCache churns through available space too quickly
@ 2026-06-05 20:09 Andres Freund <andres@anarazel.de>
0 siblings, 3 replies; 8+ messages in thread
From: Andres Freund @ 2026-06-05 20:09 UTC (permalink / raw)
To: pgsql-hackers@postgresql.org, Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>
Hi,
I noticed that a handfull of CI runs already lead to exceeding the available
cache space. One can pay for more cache space, but I think the problem is
more that what we currently do doesn't work well.
With cirrus-ci all branches shared one cache, but that's not the case with
github actions. Except for being able to read caches from the default branch
(master in our case), other branches have completely separate cache
namespaces. That's probably the right call, safety wise, but makes our ccache
approach .. not great.
We should only upload a new cache when the ccache cache hit ratio of the
existing cache entry has gotten low.
We also chose the cache key unfortunately, so that if a branch name started
with the name of the default branch, followed by a -, we'd always end up using
the main branches cache.
The attached patch fixes these, and a few other problems. See commit message
for details. With it I see a lot less cache churn and therefore also a higher
hit rate once one has more than 2-3 branches.
I'm not entirely happy with the amount of per job repetition this has. While
staying within the confines of a single .yml file, I couldn't find a better
way to deal with that. We could move a fair bit of that complexity into a
separate file, using so called "composite actions". But that's a bit of
additional github actions specific stuff that one would be exposed to, so I'm
not sure we should go that way?
It would result in having only two references to ccache in each job (one
before the build, one after). Each of those could encapsulate a bunch of steps
defined in another file.
Thoughts?
Greetings,
Andres Freund
Attachments:
[text/x-diff] v3-0001-ci-Improve-ccache-handling.patch (12.7K, ../../7eugqon2ilnaq6yimtq7prtl5wlia43mhpmwlydzlw4u4wonaz@hh2fagz5bjuu/2-v3-0001-ci-Improve-ccache-handling.patch)
download | inline diff:
From 728cd3c7ac21bdbc47f3b347a0be2cd9a3c869d7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 5 Jun 2026 11:58:39 -0400
Subject: [PATCH v3 1/2] ci: Improve ccache handling
There previously were a number of issues:
- We'd upload the cache even if we already had a high hit rate. That means we
churn through the available cache space very quickly.
For this we now check if the cache hit ratio is already high, and skip
uploading a new cache in that case.
- We'd generate per-branch caches, even if master's already would suffice,
because the branch doesn't change much
This is solved indirectly by the above.
- The cache key allowed prefix matches based on the branch,
e.g. master-pending would always use master's branch
Replace the cache key element separator of - with :, which is not a valid
part of a branch name.
- When rebasing a feature branch, we'd start with just that branch's cache,
rather than also having the newer cache of master available
This is solved by downloading by master's and the feature branch's cache,
simply overlaying both. That's possible because ccache is content addressed.
- The size of a cache would increase to the max, even though there likely will
be no benefit from old cache entries.
Address this by explicitly evicting old data and also recompressing the
cache before uploading it.
In my testing this utilizes the available cache space (10GB for personal
accounts) much more effictively than before.
The not entirely trivial determination of whether it's worth uploading a cache
entry is moved to a python script. I first had it as shell, but that gets
awkward. This way it'd also be more viable to use ccache for msvc at some
point.
The per-job redundancies are a bit annoying. There's a way around that, by
using composite actions, but I think that might be harder to understand,
without all that much of an improvement.
---
.github/workflows/pg-ci.yml | 94 ++++++++++++++++++++++------
src/tools/ci/gha_ccache_decide.py | 100 ++++++++++++++++++++++++++++++
2 files changed, 176 insertions(+), 18 deletions(-)
create mode 100644 src/tools/ci/gha_ccache_decide.py
diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8560e9389f6..86dc47de8db 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -130,6 +130,22 @@ env:
# commit-message directive parsed in the `setup` job below.
CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck"
+ ###
+ # A few variables to make expressions later on shorter
+ ###
+
+ ON_DEFAULT_BRANCH: ${{github.event.repository.default_branch == github.ref_name }}
+
+ # Note that we need to be careful to use a separator that can't be in branch
+ # names, otherwise e.g. caches for 'master' might be restored on the
+ # 'master-pending' branch.
+ CACHE_PREFIX_DEFAULT: >-
+ :${{ github.job }}:${{ github.event.repository.default_branch }}:
+ CACHE_PREFIX_BRANCH: >-
+ :${{ github.job }}:${{ github.ref_name }}:
+ CACHE_SUFFIX: >-
+ ${{ github.run_id }}:${{ github.run_attempt }}
+
jobs:
@@ -277,16 +293,30 @@ jobs:
with:
fetch-depth: ${{ env.CLONE_DEPTH }}
- - &ccache_restore_step
- name: Restore ccache
- id: ccache_restore
+ # We restore both the ccache from the default branch (typically master),
+ # and from the current branch. This will often allow feature branches to
+ # start out with a high cache hit ratio.
+ #
+ # With ccache it turns out to work to just restore two caches into the
+ # same directory, as it's basically a content addressed store. Stats
+ # could be corrupted, but we zero them out anyway.
+ - &ccache_restore_default_step
+ name: "ccache: Restore for default branch ${{github.event.repository.default_branch}}"
+ if: ${{ env.ON_DEFAULT_BRANCH == 'false' }}
uses: actions/cache/restore@v5
with:
path: ${{ env.CCACHE_DIR }}
- key: ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
- restore-keys: |
- ccache-${{ github.job }}-${{ github.ref_name }}-
- ccache-${{ github.job }}-
+ key: ccache${{env.CACHE_PREFIX_DEFAULT}}${{env.CACHE_SUFFIX}}
+ restore-keys: ccache${{env.CACHE_PREFIX_DEFAULT}}
+
+ - &ccache_restore_branch_step
+ name: "ccache: Restore for branch ${{ github.ref_name }}"
+ id: ccache-restore-branch
+ uses: actions/cache/restore@v5
+ with:
+ path: ${{ env.CCACHE_DIR }}
+ key: ccache${{env.CACHE_PREFIX_BRANCH}}${{env.CACHE_SUFFIX}}
+ restore-keys: ccache${{env.CACHE_PREFIX_BRANCH}}
- &linux_prepare_workspace_step
name: Prepare workspace
@@ -325,15 +355,30 @@ jobs:
ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}}
ninja -C build -t missingdeps
- # TODO: As long as we use per-run ccache caches, we should probably add
- # a step that checks if there is sufficient new content to warrant
- # saving the new cache.
+ # Decide if it's worth uploading a new version of the ccache cache. If
+ # we always do so unconditionally, we'd very quickly go through the
+ # allowed cache space. Instead we check if the hit rate is high enough
+ # already for that not to be worth it.
+ - &ccache_decide_save_step
+ name: "ccache: Decide if cache should be uploaded"
+ id: ccache-pre-save
+ # [Decide to] store the cache whenever the cache was set up, so that
+ # incrementally addressing compiler errors/warnings doesn't have to
+ # start from scratch.
+ if: |
+ always() &&
+ steps.ccache-restore-branch.conclusion == 'success'
+ run: python3 src/tools/ci/gha_ccache_decide.py
+
- &ccache_save_step
- name: Save ccache
+ name: "ccache: Upload cache"
uses: actions/cache/save@v5
+ if: |
+ always() &&
+ steps.ccache-pre-save.outputs.should_save == 'true'
with:
path: ${{ env.CCACHE_DIR }}
- key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
+ key: ${{ steps.ccache-restore-branch.outputs.cache-primary-key }}
# Run a minimal set of tests. The main regression tests take too long
# for this purpose. For now this is a random quick pg_regress style
@@ -448,7 +493,8 @@ jobs:
- *nix_sysinfo_step
- *checkout_step
- - *ccache_restore_step
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
@@ -467,6 +513,7 @@ jobs:
run: |
make -s -j${BUILD_JOBS} world-bin
+ - *ccache_decide_save_step
- *ccache_save_step
- name: Test world
@@ -508,7 +555,8 @@ jobs:
- *nix_sysinfo_step
- *checkout_step
- - *ccache_restore_step
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
@@ -527,6 +575,7 @@ jobs:
shell: *su_postgres_shell
run: *ninja_build_cmd
+ - *ccache_decide_save_step
- *ccache_save_step
- name: Test world
@@ -596,7 +645,8 @@ jobs:
- *nix_sysinfo_step
- *checkout_step
- - *ccache_restore_step
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
- *linux_prepare_workspace_step
- name: Configure
@@ -613,6 +663,7 @@ jobs:
shell: *su_postgres_shell
run: *ninja_build_cmd
+ - *ccache_decide_save_step
- *ccache_save_step
- name: Test world
@@ -682,7 +733,6 @@ jobs:
steps:
- *nix_sysinfo_step
- *checkout_step
- - *ccache_restore_step
- name: Setup core files
run: |
@@ -745,6 +795,9 @@ jobs:
path: ${{ env.MACPORTS_CACHE }}
key: ${{ steps.mp-key.outputs.key }}
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
+
- name: Configure
env:
PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/
@@ -762,6 +815,7 @@ jobs:
- name: Build
run: *ninja_build_cmd
+ - *ccache_decide_save_step
- *ccache_save_step
- name: Test world
@@ -1062,7 +1116,8 @@ jobs:
shell: cmd
run: mkdir ${{env.PG_REGRESS_SOCK_DIR}}
- - *ccache_restore_step
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
- name: Configure
run: |
@@ -1077,6 +1132,7 @@ jobs:
- name: Build
run: *ninja_build_cmd
+ - *ccache_decide_save_step
- *ccache_save_step
- name: Test world
@@ -1118,7 +1174,8 @@ jobs:
steps:
- *nix_sysinfo_step
- *checkout_step
- - *ccache_restore_step
+ - *ccache_restore_default_step
+ - *ccache_restore_branch_step
- name: Setup workspace
run: |
@@ -1213,5 +1270,6 @@ jobs:
headerscheck cpluspluscheck \
EXTRAFLAGS='-fmax-errors=10'
+ - *ccache_decide_save_step
- *ccache_save_step
- *upload_logs_step
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
new file mode 100644
index 00000000000..920f7bf9685
--- /dev/null
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+
+import os
+import re
+import shutil
+import subprocess
+
+def run(cmd, check=True):
+ return subprocess.run(
+ cmd,
+ check=check,
+ text=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ ).stdout
+
+def parse_ccache_stats():
+ out = run(["ccache", "--print-stats"])
+ hits = 0
+ misses = 0
+
+ for line in out.splitlines():
+ line = line.strip()
+ m = re.match(r"^local_storage_hit\s+(\d+)$", line)
+ if m:
+ hits = int(m.group(1))
+ continue
+ m = re.match(r"^local_storage_miss\s+(\d+)$", line)
+ if m:
+ misses = int(m.group(1))
+ continue
+
+ return hits, misses
+
+def append_github_output(key, value):
+ output_path = os.environ["GITHUB_OUTPUT"]
+ with open(output_path, "a", encoding="utf-8") as f:
+ f.write(f"{key}={value}\n")
+
+def main():
+ on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
+ ccache_dir = os.environ["CCACHE_DIR"]
+
+ # Decide the target hit percentage below which we decide to upload a new
+ # cache. On non-default branches a few misses aren't that bad. But, as the
+ # caches of the default branch are shared with all branches, it's worth
+ # aiming for a higher ratio there.
+ target_rate = 95 if on_default_branch else 80
+
+ # Log ccache stats, useful for more in-depth understanding. The avoid it
+ # swamping the output, collapse it in a group.
+ print("::group::ccache_stats")
+ print(run(["ccache", "-s", "-vv"]))
+ print("::endgroup::")
+
+ # compute cache hit ratio
+ hits, misses = parse_ccache_stats()
+ total = hits + misses
+ hit_pct = int(( hits / total) * 100) if total > 0 else 100
+
+ print(f"hits: {hits}, misses: {misses}, hit_pct: {hit_pct}, target rate: {target_rate}")
+
+ # If there were either barely any misses, or the cache hit ratio was high,
+ # there no point in generating a new cache entry. We have limited cache
+ # space.
+ should_save = misses > 10 and hit_pct < target_rate
+
+ append_github_output("should_save", str(should_save).lower())
+
+ if not should_save:
+ print(f"hit rate {hit_pct} is above target of {target_rate}, skip creating new cache entry")
+ return 0
+
+ print(f"hit rate {hit_pct} is below target of {target_rate}, create new cache entry")
+
+ # It's not worth persisting old cache entries (e.g. from before a
+ # change to a central header, or from the default branch if this
+ # branch differs a lot). Therefore evict ccache entries that are a
+ # bit older. The cutoff here is fairly arbitrary, it could
+ # probably be improved.
+ print("::group::ccache_shrink")
+ print(run(["ccache", "--evict-older-than", f"{45*60}s"]))
+ print(run(["ccache", "-X", "10"]))
+
+ # Don't store ccache stats , otherwise we'd need to reset the cache access
+ # data after restoring the cache in the next run, to be able to get the
+ # hit ratio of the CI run.
+ print(run(["ccache", "-z"]))
+ print("::endgroup::")
+
+ # Before continuing, try to kill all ccache instances, otherwise
+ # it's possible that on cancellations there is still running
+ # ccaches that cause the upload to fail.
+ if shutil.which("killall"):
+ print(run(["killall", "ccache"], check=False))
+
+ return 0
+
+if __name__ == "__main__":
+ exit(main())
--
2.54.0.380.gc69baaf57b
[text/x-diff] v3-0002-ci-fewer-tests.patch (1.1K, ../../7eugqon2ilnaq6yimtq7prtl5wlia43mhpmwlydzlw4u4wonaz@hh2fagz5bjuu/3-v3-0002-ci-fewer-tests.patch)
download | inline diff:
From 64067cebec777f41883f6d86649336415e5e713d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 5 Jun 2026 14:52:27 -0400
Subject: [PATCH v3 2/2] ci: fewer tests
---
.github/workflows/pg-ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 86dc47de8db..f81b738e27e 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -53,7 +53,7 @@ env:
# Check target for the autoconf builds. Can be set to e.g. check to only
# test the main regression tests.
- CHECK: check-world PROVE_FLAGS=--timer
+ CHECK: check PROVE_FLAGS=--timer
CHECKFLAGS: -Otarget
# Build test dependencies as part of the build step, to see compiler
@@ -63,7 +63,7 @@ env:
# Can be set to a non-empty value to run a limited set of tests
# (e.g. --suite regress to only run the main regression tests).
- MTEST_TARGET:
+ MTEST_TARGET: --suite test_misc --suite regress
PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf
--
2.54.0.380.gc69baaf57b
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-08 10:30 Nazir Bilal Yavuz <byavuz81@gmail.com>
parent: Andres Freund <andres@anarazel.de>
2 siblings, 1 reply; 8+ messages in thread
From: Nazir Bilal Yavuz @ 2026-06-08 10:30 UTC (permalink / raw)
To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers@postgresql.org, Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>
Hi,
Thank you for working on this!
On Fri, 5 Jun 2026 at 23:09, Andres Freund <andres@anarazel.de> wrote:
>
> I noticed that a handfull of CI runs already lead to exceeding the available
> cache space. One can pay for more cache space, but I think the problem is
> more that what we currently do doesn't work well.
>
> With cirrus-ci all branches shared one cache, but that's not the case with
> github actions. Except for being able to read caches from the default branch
> (master in our case), other branches have completely separate cache
> namespaces. That's probably the right call, safety wise, but makes our ccache
> approach .. not great.
>
> We should only upload a new cache when the ccache cache hit ratio of the
> existing cache entry has gotten low.
This makes sense.
> We also chose the cache key unfortunately, so that if a branch name started
> with the name of the default branch, followed by a -, we'd always end up using
> the main branches cache.
>
>
> The attached patch fixes these, and a few other problems. See commit message
> for details. With it I see a lot less cache churn and therefore also a higher
> hit rate once one has more than 2-3 branches.
>
>
> I'm not entirely happy with the amount of per job repetition this has. While
> staying within the confines of a single .yml file, I couldn't find a better
> way to deal with that. We could move a fair bit of that complexity into a
> separate file, using so called "composite actions". But that's a bit of
> additional github actions specific stuff that one would be exposed to, so I'm
> not sure we should go that way?
I think it looks okay, no need to use composite actions for this.
--------------------
I tested the patch and I confirm that it works as mentioned. Here is my review:
All the points you explained in the commit message are nice improvements!
Typo in commit message:
+ In my testing this utilizes the available cache space (10GB for personal
+ accounts) much more effictively than before.
Typo at 'effictively' in the commit message.
diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 8560e9389f6..86dc47de8db 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
+ - &ccache_decide_save_step
+ name: "ccache: Decide if cache should be uploaded"
+ id: ccache-pre-save
+ # [Decide to] store the cache whenever the cache was set up, so that
+ # incrementally addressing compiler errors/warnings doesn't have to
+ # start from scratch.
+ if: |
+ always() &&
+ steps.ccache-restore-branch.conclusion == 'success'
+ run: python3 src/tools/ci/gha_ccache_decide.py
Isn't the conclusion always true unless GitHub has some self errors?
Also, we are directly running this script with the 'python3' command
but it might not be available on the PATH. I had some problems with
this on BSD images when we were using Cirrus. I am not sure we would
have such problems with GitHub Actions but I just wanted to mention
it.
diff --git a/src/tools/ci/gha_ccache_decide.py
b/src/tools/ci/gha_ccache_decide.py
new file mode 100644
index 00000000000..920f7bf9685
--- /dev/null
+++ b/src/tools/ci/gha_ccache_decide.py
+def main():
+ on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
+ ccache_dir = os.environ["CCACHE_DIR"]
ccache_dir isn't used.
+ # compute cache hit ratio
+ hits, misses = parse_ccache_stats()
+ total = hits + misses
+ hit_pct = int(( hits / total) * 100) if total > 0 else 100
Extra space in '( hits'.
+ # If there were either barely any misses, or the cache hit ratio was high,
+ # there no point in generating a new cache entry. We have limited cache
+ # space.
+ should_save = misses > 10 and hit_pct < target_rate
We consider misses here but we don't mention it, we only mention hit
rate and target rate. I think this is not very important since we
can't possibly have a case that misses < 10 and hit_pct < target_rate.
If that is not the case, then I think we can remove misses from the
should_save calculation.
+ # Don't store ccache stats , otherwise we'd need to reset the cache access
Extra space before comma.
--
Regards,
Nazir Bilal Yavuz
Microsoft
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-08 14:59 Andres Freund <andres@anarazel.de>
parent: Nazir Bilal Yavuz <byavuz81@gmail.com>
0 siblings, 1 reply; 8+ messages in thread
From: Andres Freund @ 2026-06-08 14:59 UTC (permalink / raw)
To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: pgsql-hackers@postgresql.org, Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>
Hi,
On 2026-06-08 13:30:03 +0300, Nazir Bilal Yavuz wrote:
> I think it looks okay, no need to use composite actions for this.
Cool.
> I tested the patch and I confirm that it works as mentioned. Here is my review:
>
> All the points you explained in the commit message are nice improvements!
>
> Typo in commit message:
>
> + In my testing this utilizes the available cache space (10GB for personal
> + accounts) much more effictively than before.
>
> Typo at 'effictively' in the commit message.
Oops.
> diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
> index 8560e9389f6..86dc47de8db 100644
> --- a/.github/workflows/pg-ci.yml
> +++ b/.github/workflows/pg-ci.yml
>
> + - &ccache_decide_save_step
> + name: "ccache: Decide if cache should be uploaded"
> + id: ccache-pre-save
> + # [Decide to] store the cache whenever the cache was set up, so that
> + # incrementally addressing compiler errors/warnings doesn't have to
> + # start from scratch.
> + if: |
> + always() &&
> + steps.ccache-restore-branch.conclusion == 'success'
> + run: python3 src/tools/ci/gha_ccache_decide.py
>
> Isn't the conclusion always true unless GitHub has some self errors?
I mean, the cache restoration *could* fail? Or another earlier step could We
don't want to upload a new cache entry if we never got to building...
> Also, we are directly running this script with the 'python3' command
> but it might not be available on the PATH. I had some problems with
> this on BSD images when we were using Cirrus. I am not sure we would
> have such problems with GitHub Actions but I just wanted to mention
> it.
I think we'll just have to address it if/when it becomes a problem. I don't
really see the alternative...
> diff --git a/src/tools/ci/gha_ccache_decide.py
> b/src/tools/ci/gha_ccache_decide.py
> new file mode 100644
> index 00000000000..920f7bf9685
> --- /dev/null
> +++ b/src/tools/ci/gha_ccache_decide.py
>
> +def main():
> + on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
> + ccache_dir = os.environ["CCACHE_DIR"]
>
> ccache_dir isn't used.
Ah, yea. It was earlier, but I removed that part (computed the cache size,
when this was a shell script, by using du. But that seemed too awkward in
python, so I removed it).
> + # If there were either barely any misses, or the cache hit ratio was high,
> + # there no point in generating a new cache entry. We have limited cache
> + # space.
> + should_save = misses > 10 and hit_pct < target_rate
>
> We consider misses here but we don't mention it
I was trying to mention it, via "If there were either barely any misses".
> , we only mention hit rate and target rate. I think this is not very
> important since we can't possibly have a case that misses < 10 and hit_pct <
> target_rate.
Why could we not have such a case? If we start building with some changes
that trigger cache misses, but there's a compiler error a few seconds in, that
seems like it'd precisely hit that case?
Greetings,
Andres Freund
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-08 16:10 Nazir Bilal Yavuz <byavuz81@gmail.com>
parent: Andres Freund <andres@anarazel.de>
0 siblings, 1 reply; 8+ messages in thread
From: Nazir Bilal Yavuz @ 2026-06-08 16:10 UTC (permalink / raw)
To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers@postgresql.org, Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>
Hi,
On Mon, 8 Jun 2026 at 17:59, Andres Freund <andres@anarazel.de> wrote:
>
> > diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
> > index 8560e9389f6..86dc47de8db 100644
> > --- a/.github/workflows/pg-ci.yml
> > +++ b/.github/workflows/pg-ci.yml
> >
> > + - &ccache_decide_save_step
> > + name: "ccache: Decide if cache should be uploaded"
> > + id: ccache-pre-save
> > + # [Decide to] store the cache whenever the cache was set up, so that
> > + # incrementally addressing compiler errors/warnings doesn't have to
> > + # start from scratch.
> > + if: |
> > + always() &&
> > + steps.ccache-restore-branch.conclusion == 'success'
> > + run: python3 src/tools/ci/gha_ccache_decide.py
> >
> > Isn't the conclusion always true unless GitHub has some self errors?
>
> I mean, the cache restoration *could* fail? Or another earlier step could We
> don't want to upload a new cache entry if we never got to building...
I see, yes these points make sense.
> > Also, we are directly running this script with the 'python3' command
> > but it might not be available on the PATH. I had some problems with
> > this on BSD images when we were using Cirrus. I am not sure we would
> > have such problems with GitHub Actions but I just wanted to mention
> > it.
>
> I think we'll just have to address it if/when it becomes a problem. I don't
> really see the alternative...
Sounds good.
> > diff --git a/src/tools/ci/gha_ccache_decide.py
> > b/src/tools/ci/gha_ccache_decide.py
> > new file mode 100644
> > index 00000000000..920f7bf9685
> > --- /dev/null
> > +++ b/src/tools/ci/gha_ccache_decide.py
>
> > + # If there were either barely any misses, or the cache hit ratio was high,
> > + # there no point in generating a new cache entry. We have limited cache
> > + # space.
> > + should_save = misses > 10 and hit_pct < target_rate
> >
> > We consider misses here but we don't mention it
>
> I was trying to mention it, via "If there were either barely any misses".
Sorry, what I meant was we don't mention in the logs, which is:
+ if not should_save:
+ print(f"hit rate {hit_pct} is above target of {target_rate},
skip creating new cache entry")
+ return 0
> > , we only mention hit rate and target rate. I think this is not very
> > important since we can't possibly have a case that misses < 10 and hit_pct <
> > target_rate.
>
> Why could we not have such a case? If we start building with some changes
> that trigger cache misses, but there's a compiler error a few seconds in, that
> seems like it'd precisely hit that case?
Yes, you are right. I hadn't thought of the failure case. Then, it
would be good to mention that case in the log I mentioned above.
Otherwise, we will be printing the incorrect reason.
--
Regards,
Nazir Bilal Yavuz
Microsoft
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-08 19:28 Andres Freund <andres@anarazel.de>
parent: Nazir Bilal Yavuz <byavuz81@gmail.com>
0 siblings, 0 replies; 8+ messages in thread
From: Andres Freund @ 2026-06-08 19:28 UTC (permalink / raw)
To: Nazir Bilal Yavuz <byavuz81@gmail.com>; +Cc: pgsql-hackers@postgresql.org, Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>
Hi,
On 2026-06-08 19:10:46 +0300, Nazir Bilal Yavuz wrote:
> On Mon, 8 Jun 2026 at 17:59, Andres Freund <andres@anarazel.de> wrote:
> > > diff --git a/src/tools/ci/gha_ccache_decide.py
> > > b/src/tools/ci/gha_ccache_decide.py
> > > new file mode 100644
> > > index 00000000000..920f7bf9685
> > > --- /dev/null
> > > +++ b/src/tools/ci/gha_ccache_decide.py
> >
> > > + # If there were either barely any misses, or the cache hit ratio was high,
> > > + # there no point in generating a new cache entry. We have limited cache
> > > + # space.
> > > + should_save = misses > 10 and hit_pct < target_rate
> > >
> > > We consider misses here but we don't mention it
> >
> > I was trying to mention it, via "If there were either barely any misses".
>
> Sorry, what I meant was we don't mention in the logs, which is:
>
> + if not should_save:
> + print(f"hit rate {hit_pct} is above target of {target_rate},
> skip creating new cache entry")
> + return 0
Ah, makes sense.
I updated that, and after doing some minor polishing, pushed it.
Thanks for the quick review!
Greetings,
Andres
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-17 22:02 Tristan Partin <tristan@partin.io>
parent: Andres Freund <andres@anarazel.de>
2 siblings, 1 reply; 8+ messages in thread
From: Tristan Partin @ 2026-06-17 22:02 UTC (permalink / raw)
To: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>; Thomas Munro <thomas.munro@gmail.com>; +Cc: pgsql-hackers
On Fri Jun 5, 2026 at 8:09 PM UTC, Andres Freund wrote:
> Hi,
>
> I noticed that a handfull of CI runs already lead to exceeding the available
> cache space. One can pay for more cache space, but I think the problem is
> more that what we currently do doesn't work well.
>
> With cirrus-ci all branches shared one cache, but that's not the case with
> github actions. Except for being able to read caches from the default branch
> (master in our case), other branches have completely separate cache
> namespaces. That's probably the right call, safety wise, but makes our ccache
> approach .. not great.
>
> We should only upload a new cache when the ccache cache hit ratio of the
> existing cache entry has gotten low.
I had started reviewing this patch the day it was originally sent, but
due to circumstances I couldn't finish the review before it was
committed. I had some thoughts with regard to improving the Python
script itself. Attached are some improvements that make the code
a little more pythonic as well as more easily usable locally for testing
purposes. Some of the patches may be more valuable than others.
--
Tristan Partin
PostgreSQL Contributors Team
AWS (https://aws.amazon.com)
Attachments:
[text/x-patch] v1-0001-Use-long-options-for-ccache-commands.patch (1.6K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/2-v1-0001-Use-long-options-for-ccache-commands.patch)
download | inline diff:
From 650f97c15d0bd9e8c5d725afe53d4bb2eab92770 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:05:43 +0000
Subject: [PATCH v1 1/7] Use long options for ccache commands
-s, -X, and -z don't mean much to someone reading this script unless
they are very familiar with the ccache CLI.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index a8e32310d0..ea9fbe9452 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -49,7 +49,7 @@ def main():
# Log ccache stats, useful for more in-depth understanding. To avoid
# swamping the output, collapse it in a group.
print("::group::ccache_stats")
- print(run(["ccache", "-s", "-vv"]))
+ print(run(["ccache", "--show-stats", "-vv"]))
print("::endgroup::")
# compute cache hit ratio
@@ -84,12 +84,12 @@ def main():
# probably be improved.
print("::group::ccache_shrink")
print(run(["ccache", "--evict-older-than", f"{45*60}s"]))
- print(run(["ccache", "-X", "10"]))
+ print(run(["ccache", "--recompress", "10"]))
# Don't store ccache stats, otherwise we'd need to reset the cache access
# data after restoring the cache in the next run, to be able to get the
# hit ratio of the CI run.
- print(run(["ccache", "-z"]))
+ print(run(["ccache", "--zero-stats"]))
print("::endgroup::")
# Before continuing, try to kill all ccache instances, otherwise
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0002-Use-json-to-parse-ccache-statistics.patch (1.9K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/3-v1-0002-Use-json-to-parse-ccache-statistics.patch)
download | inline diff:
From 86bf2412ecd471dd901dbee5271e5a84fde243fd Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:06:42 +0000
Subject: [PATCH v1 2/7] Use json to parse ccache statistics
Instead of relying on regex to parse ccache CLI output, we can ask
ccache to output its statistics in JSON, which Python natively supports.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 24 ++++--------------------
1 file changed, 4 insertions(+), 20 deletions(-)
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index ea9fbe9452..b4874517fb 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
+import json
import os
-import re
import shutil
import subprocess
@@ -14,24 +14,6 @@ def run(cmd, check=True):
stderr=subprocess.STDOUT,
).stdout
-def parse_ccache_stats():
- out = run(["ccache", "--print-stats"])
- hits = 0
- misses = 0
-
- for line in out.splitlines():
- line = line.strip()
- m = re.match(r"^local_storage_hit\s+(\d+)$", line)
- if m:
- hits = int(m.group(1))
- continue
- m = re.match(r"^local_storage_miss\s+(\d+)$", line)
- if m:
- misses = int(m.group(1))
- continue
-
- return hits, misses
-
def append_github_output(key, value):
output_path = os.environ["GITHUB_OUTPUT"]
with open(output_path, "a", encoding="utf-8") as f:
@@ -53,7 +35,9 @@ def main():
print("::endgroup::")
# compute cache hit ratio
- hits, misses = parse_ccache_stats()
+ ccache_stats = json.loads(run(["ccache", "--print-stats", "--format", "json"]))
+ hits = ccache_stats["local_storage_hit"]
+ misses = ccache_stats["local_storage_miss"]
total = hits + misses
hit_pct = int((hits / total) * 100) if total > 0 else 100
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0003-Remove-the-shutil.which-call.patch (1.4K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/4-v1-0003-Remove-the-shutil.which-call.patch)
download | inline diff:
From 25881caa9baca7980dda530e27b6025bcf4e8c4a Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:09:29 +0000
Subject: [PATCH v1 3/7] Remove the shutil.which() call
This call is pointless. We were resolving `killall` to a filesystem
path, and immediately discarding it just to re-resolve it again in the
subsequent run() call. This is not a pythonic was to write this code.
Instead, we can wrap the function call with a try/except block and just
ignore any exception that may arise.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index b4874517fb..4b322b8087 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -2,7 +2,6 @@
import json
import os
-import shutil
import subprocess
def run(cmd, check=True):
@@ -79,8 +78,10 @@ def main():
# Before continuing, try to kill all ccache instances, otherwise
# it's possible that on cancellations there is still running
# ccaches that cause the upload to fail.
- if shutil.which("killall"):
+ try:
print(run(["killall", "ccache"], check=False))
+ except FileNotFoundError:
+ pass
return 0
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0004-Use-a-context-manager-to-write-grouped-CI-output.patch (2.9K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/5-v1-0004-Use-a-context-manager-to-write-grouped-CI-output.patch)
download | inline diff:
From de4cf351d9ce083c3666c7ffc0f1f900eacfa441 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:20:47 +0000
Subject: [PATCH v1 4/7] Use a context manager to write grouped CI output
With a context manager, we can take responsibility from the caller to
write proper GitHub Action output syntax, and instead let the caller
focus on logging relevant output.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index 4b322b8087..58b1d14c96 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -3,6 +3,7 @@
import json
import os
import subprocess
+from contextlib import contextmanager
def run(cmd, check=True):
return subprocess.run(
@@ -18,6 +19,14 @@ def append_github_output(key, value):
with open(output_path, "a", encoding="utf-8") as f:
f.write(f"{key}={value}\n")
+@contextmanager
+def group(name):
+ print(f"::group::{name}")
+ try:
+ yield
+ finally:
+ print("::endgroup::")
+
def main():
on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
@@ -29,9 +38,8 @@ def main():
# Log ccache stats, useful for more in-depth understanding. To avoid
# swamping the output, collapse it in a group.
- print("::group::ccache_stats")
- print(run(["ccache", "--show-stats", "-vv"]))
- print("::endgroup::")
+ with group("ccache_stats"):
+ print(run(["ccache", "--show-stats", "-vv"]))
# compute cache hit ratio
ccache_stats = json.loads(run(["ccache", "--print-stats", "--format", "json"]))
@@ -65,15 +73,14 @@ def main():
# branch differs a lot). Therefore evict ccache entries that are a
# bit older. The cutoff here is fairly arbitrary, it could
# probably be improved.
- print("::group::ccache_shrink")
- print(run(["ccache", "--evict-older-than", f"{45*60}s"]))
- print(run(["ccache", "--recompress", "10"]))
+ with group("ccache_shrink"):
+ print(run(["ccache", "--evict-older-than", f"{45*60}s"]))
+ print(run(["ccache", "--recompress", "10"]))
- # Don't store ccache stats, otherwise we'd need to reset the cache access
- # data after restoring the cache in the next run, to be able to get the
- # hit ratio of the CI run.
- print(run(["ccache", "--zero-stats"]))
- print("::endgroup::")
+ # Don't store ccache stats, otherwise we'd need to reset the cache
+ # access data after restoring the cache in the next run, to be able to
+ # get the hit ratio of the CI run.
+ print(run(["ccache", "--zero-stats"]))
# Before continuing, try to kill all ccache instances, otherwise
# it's possible that on cancellations there is still running
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0005-Provide-ccache-target-rate-as-an-input-to-the-scr.patch (4.1K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/6-v1-0005-Provide-ccache-target-rate-as-an-input-to-the-scr.patch)
download | inline diff:
From 5961484cb19125c87d91ace9df9b250471cd94f5 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:38:08 +0000
Subject: [PATCH v1 5/7] Provide ccache target rate as an input to the script
This makes it much easier to test locally. Now, we don't depend on an
ON_DEFAULT_BRANCH environment variable within the script. We pull the
decision making up to the CI step itself to tell the script what rate to
target.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
.github/workflows/pg-ci.yml | 8 +++++++-
src/tools/ci/gha_ccache_decide.py | 29 +++++++++++++++--------------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index 5bc5292d2a..6ccd8c2475 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -368,7 +368,13 @@ jobs:
if: |
always() &&
steps.ccache-restore-branch.conclusion == 'success'
- run: python3 src/tools/ci/gha_ccache_decide.py
+ run: |
+ # Decide the target hit percentage below which we decide to upload a
+ # new cache. On non-default branches a few misses aren't that bad.
+ # But, as the caches of the default branch are shared with all
+ # branches, it's worth aiming for a higher ratio there.
+ python3 src/tools/ci/gha_ccache_decide.py \
+ --target-rate $([ "$ON_DEFAULT_BRANCH" = "true" ] && echo 95 || echo 80)
- &ccache_save_step
name: "ccache: Upload cache"
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index 58b1d14c96..fe9db62891 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
+import argparse
import json
import os
import subprocess
@@ -27,15 +28,7 @@ def group(name):
finally:
print("::endgroup::")
-def main():
- on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
-
- # Decide the target hit percentage below which we decide to upload a new
- # cache. On non-default branches a few misses aren't that bad. But, as the
- # caches of the default branch are shared with all branches, it's worth
- # aiming for a higher ratio there.
- target_rate = 95 if on_default_branch else 80
-
+def main(args):
# Log ccache stats, useful for more in-depth understanding. To avoid
# swamping the output, collapse it in a group.
with group("ccache_stats"):
@@ -48,19 +41,19 @@ def main():
total = hits + misses
hit_pct = int((hits / total) * 100) if total > 0 else 100
- print(f"hits: {hits}, misses: {misses}, hit_pct: {hit_pct}, target rate: {target_rate}")
+ print(f"hits: {hits}, misses: {misses}, hit_pct: {hit_pct}, target rate: {args.target_rate}")
# If the cache hit ratio was high, or the absolute number of misses
# (e.g. in case of a failed build) was low, there is no point in
# generating a new cache entry. We have limited cache space.
- if hit_pct >= target_rate:
- print(f"hit rate {hit_pct} is above target of {target_rate}, skip creating new cache entry")
+ if hit_pct >= args.target_rate:
+ print(f"hit rate {hit_pct} is above target of {args.target_rate}, skip creating new cache entry")
should_save = False
elif misses <= 10:
print(f"only {misses} misses, skip creating new cache entry")
should_save = False
else:
- print(f"hit rate {hit_pct} is below target of {target_rate}, create new cache entry")
+ print(f"hit rate {hit_pct} is below target of {args.target_rate}, create new cache entry")
should_save = True
append_github_output("should_save", str(should_save).lower())
@@ -93,4 +86,12 @@ def main():
return 0
if __name__ == "__main__":
- exit(main())
+ parser = argparse.ArgumentParser(description="Decide whether to save cache")
+ parser.add_argument(
+ "--target-rate",
+ type=int,
+ default=80,
+ help="target hit rate below which to save cache",
+ )
+
+ exit(main(parser.parse_args()))
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0006-Check-that-GITHUB_OUTPUT-exists-before-trying-to-.patch (1.4K, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/7-v1-0006-Check-that-GITHUB_OUTPUT-exists-before-trying-to-.patch)
download | inline diff:
From 53ef4d0e88fe08f3c9dfa305cbe1cff4ecb521ac Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 19:48:02 +0000
Subject: [PATCH v1 6/7] Check that GITHUB_OUTPUT exists before trying to
append to it
Without defining GITHUB_OUTPUT as an environment variable before testing
the script, it would error out with an undefined variable. This will
improve local development a bit.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
index fe9db62891..1b58990939 100644
--- a/src/tools/ci/gha_ccache_decide.py
+++ b/src/tools/ci/gha_ccache_decide.py
@@ -6,6 +6,8 @@
import subprocess
from contextlib import contextmanager
+GITHUB_OUTPUT = os.environ.get("GITHUB_OUTPUT")
+
def run(cmd, check=True):
return subprocess.run(
cmd,
@@ -16,9 +18,9 @@ def run(cmd, check=True):
).stdout
def append_github_output(key, value):
- output_path = os.environ["GITHUB_OUTPUT"]
- with open(output_path, "a", encoding="utf-8") as f:
- f.write(f"{key}={value}\n")
+ if GITHUB_OUTPUT:
+ with open(GITHUB_OUTPUT, "a", encoding="utf-8") as f:
+ f.write(f"{key}={value}\n")
@contextmanager
def group(name):
--
Tristan Partin
https://tristan.partin.io
[text/x-patch] v1-0007-Make-gha_ccache_decide.py-executable.patch (675B, ../../DJBNW7DKLMV1.2WHERLY9NSEJX@partin.io/8-v1-0007-Make-gha_ccache_decide.py-executable.patch)
download | inline diff:
From 16b12c125ca98909456f467f7b801edd2e598b19 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 17 Jun 2026 22:00:01 +0000
Subject: [PATCH v1 7/7] Make gha_ccache_decide.py executable
The script already had a shebang line, so it seems intended for this
script to be executable.
Signed-off-by: Tristan Partin <tristan@partin.io>
---
src/tools/ci/gha_ccache_decide.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 src/tools/ci/gha_ccache_decide.py
diff --git a/src/tools/ci/gha_ccache_decide.py b/src/tools/ci/gha_ccache_decide.py
old mode 100644
new mode 100755
--
Tristan Partin
https://tristan.partin.io
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-18 04:50 Thomas Munro <thomas.munro@gmail.com>
parent: Andres Freund <andres@anarazel.de>
2 siblings, 0 replies; 8+ messages in thread
From: Thomas Munro @ 2026-06-18 04:50 UTC (permalink / raw)
To: Andres Freund <andres@anarazel.de>; +Cc: pgsql-hackers@postgresql.org, Nazir Bilal Yavuz <byavuz81@gmail.com>; Jacob Champion <jacob.champion@enterprisedb.com>
On Sat, Jun 6, 2026 at 8:09 AM Andres Freund <andres@anarazel.de> wrote:
> With cirrus-ci all branches shared one cache, but that's not the case with
> github actions. Except for being able to read caches from the default branch
> (master in our case), other branches have completely separate cache
> namespaces. That's probably the right call, safety wise, but makes our ccache
> approach .. not great.
For the record: based on what Andres explained about how GHA cache
sharing works, I taught cfbot to mirror the master branch in its
postgresql-cfbot/postgresql account, and use the latest successful CI
run from there to select the base commit for the cf/XXX branches it
maintains. IIUC that should work well for this cache sharing policy,
since master's cache should be uploaded and ready to reuse at that
point. Perhaps we'll also get some data on how successful these new
heuristics are?
https://github.com/postgresql-cfbot/postgresql/commits/master/
I also taught cfbot to delete old cf/XXX branches with no builds in
over 90 days (we went from over 9000 to 376...). That matches
Github's own retention period for logs, artefacts etc, so stale
branches are not very interesting and it seemed like a good idea not
to waste resources or clutter the UI with junk.
^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: ci: CCache churns through available space too quickly
@ 2026-06-19 18:30 Jacob Champion <jacob.champion@enterprisedb.com>
parent: Tristan Partin <tristan@partin.io>
0 siblings, 0 replies; 8+ messages in thread
From: Jacob Champion @ 2026-06-19 18:30 UTC (permalink / raw)
To: Tristan Partin <tristan@partin.io>; +Cc: Andres Freund <andres@anarazel.de>; Nazir Bilal Yavuz <byavuz81@gmail.com>; Thomas Munro <thomas.munro@gmail.com>; pgsql-hackers
On Wed, Jun 17, 2026 at 3:02 PM Tristan Partin <tristan@partin.io> wrote:
> I had started reviewing this patch the day it was originally sent, but
> due to circumstances I couldn't finish the review before it was
> committed. I had some thoughts with regard to improving the Python
> script itself. Attached are some improvements that make the code
> a little more pythonic as well as more easily usable locally for testing
> purposes. Some of the patches may be more valuable than others.
The code in 0001-3 looks good to me (haven't reviewed the commit
messages, but I assume they'd be squashed up anyway).
I'm lukewarm on the remaining pieces.
--Jacob
^ permalink raw reply [nested|flat] 8+ messages in thread
end of thread, other threads:[~2026-06-19 18:30 UTC | newest]
Thread overview: 8+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-05 20:09 ci: CCache churns through available space too quickly Andres Freund <andres@anarazel.de>
2026-06-08 10:30 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-08 14:59 ` Andres Freund <andres@anarazel.de>
2026-06-08 16:10 ` Nazir Bilal Yavuz <byavuz81@gmail.com>
2026-06-08 19:28 ` Andres Freund <andres@anarazel.de>
2026-06-17 22:02 ` Tristan Partin <tristan@partin.io>
2026-06-19 18:30 ` Jacob Champion <jacob.champion@enterprisedb.com>
2026-06-18 04:50 ` Thomas Munro <thomas.munro@gmail.com>
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox