Skip to content

Commit 5b81ee5

Browse files
jfrocheyvan-sraka
authored andcommitted
docs: document sccache CI integration
1 parent 9cb1864 commit 5b81ee5

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

nix/docs/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ learn how to play with `postgres` in the [build guide](./build-postgres.md).
4141
- **[Testing PG Upgrade Scripts](./testing-pg-upgrade-scripts.md)** - Testing PostgreSQL upgrades
4242
- **[Docker Image testing](./docker-testing.md)** - How to test the docker images against the pg_regress test suite.
4343

44+
## CI/CD
45+
46+
- **[sccache in CI](./sccache-ci.md)** - Rust compilation caching for pgrx extensions
47+
4448
## Reference
4549

4650
- **[References](./references.md)** - Useful links and resources

nix/docs/sccache-ci.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# sccache in CI
2+
3+
This document explains how sccache is integrated into the Nix CI pipeline to accelerate Rust compilation for pgrx-based PostgreSQL extensions.
4+
5+
## Overview
6+
7+
Building pgrx extensions (pg_graphql, pg_jsonschema, wrappers, etc.) involves significant Rust compilation.
8+
sccache caches compiled artifacts to speed up subsequent builds when source code hasn't changed.
9+
10+
The integration required solving several challenges around Nix's sandboxed builds and CI runner persistence.
11+
12+
## Architecture
13+
14+
Ephemeral CI runners (Blacksmith) use stickydisk for persistent storage at `/nix/var/cache/sccache`.
15+
Self-hosted Darwin runners use a local directory at the same path.
16+
17+
The cache is keyed by PostgreSQL version to avoid cross-version cache pollution:
18+
- Extension packages: `sccache-Linux-ARM64-pg17`, `sccache-Linux-ARM64-pg15`, etc.
19+
- Non-extension packages: `sccache-Linux-ARM64-shared`
20+
21+
| Platform | Runner type | sccache enabled |
22+
|----------|-------------|-----------------|
23+
| x86_64-linux | Blacksmith ephemeral | Yes (extensions only) |
24+
| aarch64-linux | Blacksmith ephemeral | Yes (extensions only) |
25+
| aarch64-linux | Self-hosted (KVM packages) | No |
26+
| aarch64-darwin | Self-hosted | Yes (extensions only) |
27+
28+
## Nix sandbox integration
29+
30+
Nix builds run in a sandbox that isolates the build environment.
31+
To allow sccache to persist across builds, the cache directory must be mounted into the sandbox via `extra-sandbox-paths`.
32+
33+
### Linux with auto-allocate-uids
34+
35+
On Linux, we use Nix's `auto-allocate-uids` feature which creates user namespaces for builds.
36+
This introduces a UID mapping challenge.
37+
38+
The base UID is 872415232 (0x34000000).
39+
Inside the sandbox, processes run as root (UID 0), but outside the sandbox this maps to UID 872415232.
40+
Files created inside the sandbox are owned by this mapped UID.
41+
42+
The workflow changes ownership to UID 872415232 before builds to ensure cache access works correctly.
43+
44+
### Darwin
45+
46+
Darwin doesn't have user namespaces.
47+
Builds run as nixbld users (members of the `nixbld` group).
48+
The cache directory is owned by the nixbld group with setgid permissions.
49+
50+
## Compromises and limitations
51+
52+
### max-jobs = 1 for extensions
53+
54+
With `auto-allocate-uids`, each parallel Nix build gets a different UID slot (872415232, 872480768, etc.).
55+
When multiple builds run in parallel, they create files with different ownership, causing EPERM errors when one build tries to update another's cache files.
56+
57+
To avoid this, extension builds use `max-jobs = 1`, serializing Nix builds so all use the same UID slot.
58+
Non-extension packages don't use sccache and can build in parallel.
59+
60+
### Blacksmith stickydisk last-writer-wins
61+
62+
Blacksmith's stickydisk has "last writer wins" semantics for concurrent writes.
63+
If multiple jobs write to the same cache key simultaneously, only the last job's writes persist.
64+
65+
We mitigate this by using per-PostgreSQL-version cache keys, reducing concurrent writes to the same cache.
66+
67+
### Extensions only
68+
69+
sccache is only enabled for extension packages (those with `postgresql_version` in the matrix).
70+
Non-extension packages (PostgreSQL itself, tooling) build without sccache to allow parallel builds.
71+
72+
## Debugging
73+
74+
To check sccache statistics, look for output at the end of extension builds:
75+
76+
```
77+
sccache stats:
78+
Compile requests 150
79+
Compile requests executed 148
80+
Cache hits 120
81+
Cache misses 28
82+
```
83+
84+
## References
85+
86+
- [Nix auto-allocate-uids](https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-auto-allocate-uids)
87+
- [sccache](https://github.com/mozilla/sccache)
88+
- [Blacksmith stickydisk](https://blacksmith.sh/docs/stickydisk)

0 commit comments

Comments
 (0)