Skip to content

Commit 4af31c1

Browse files
committed
fix(ci): pin linux glibc floor for published binaries
1 parent 40a8500 commit 4af31c1

6 files changed

Lines changed: 265 additions & 2 deletions

File tree

.github/workflows/publish.yaml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ env:
2222
R2_ENDPOINT: https://2a94c6a0ced8d35ea63cddc86c2681e7.r2.cloudflarestorage.com
2323
SIDECAR_PLATFORMS: "linux-x64-gnu linux-arm64-gnu darwin-x64 darwin-arm64"
2424
PUBLISH_INCLUDE_REGISTRY_PACKAGES: "1"
25+
LINUX_GNU_LLVM_VERSION: "22"
26+
LINUX_GNU_SYSROOT_TAG: "sysroot-20250207"
27+
LINUX_GNU_GLIBC_FLOOR_MINOR: "27"
28+
LINUX_GNU_GLIBC_REGRESSION_MINOR: "32"
2529

2630
jobs:
2731
context:
@@ -103,14 +107,16 @@ jobs:
103107
- uses: Swatinem/rust-cache@v2
104108
with:
105109
workspaces: . -> target
106-
key: ${{ matrix.target }}-${{ needs.context.outputs.trigger }}
110+
key: ${{ matrix.target }}-${{ env.LINUX_GNU_SYSROOT_TAG }}-llvm-${{ env.LINUX_GNU_LLVM_VERSION }}-${{ needs.context.outputs.trigger }}
107111
- uses: actions/cache@v4
108112
with:
109113
path: ~/.cargo/.rusty_v8
110114
key: ${{ runner.os }}-${{ matrix.target }}-rusty-v8-${{ hashFiles('Cargo.lock') }}
111115
restore-keys: |
112116
${{ runner.os }}-${{ matrix.target }}-rusty-v8-
113117
- run: pnpm install --frozen-lockfile --filter='!@agentos/website'
118+
- name: Set up Linux GNU sysroot
119+
run: scripts/ci/setup-linux-gnu-sysroot.sh
114120
- name: Build sidecar binaries
115121
id: build
116122
run: |
@@ -128,6 +134,16 @@ jobs:
128134
cp "target/${{ matrix.target }}/${profile}/agentos-sidecar" "$out/agentos-sidecar"
129135
cp "target/${{ matrix.target }}/${profile}/agentos-native-sidecar" "$out/agentos-native-sidecar"
130136
echo "dir=$out" >> "$GITHUB_OUTPUT"
137+
- name: Check glibc floor
138+
run: |
139+
scripts/ci/check-linux-glibc-floor.sh \
140+
"${{ steps.build.outputs.dir }}/agentos-sidecar" \
141+
"${{ steps.build.outputs.dir }}/agentos-native-sidecar"
142+
- name: Smoke-run in old Linux containers
143+
run: |
144+
scripts/ci/smoke-linux-artifacts.sh binary \
145+
"${{ steps.build.outputs.dir }}/agentos-sidecar" \
146+
"${{ steps.build.outputs.dir }}/agentos-native-sidecar"
131147
- uses: actions/upload-artifact@v4
132148
with:
133149
name: sidecar-${{ matrix.platform }}
@@ -162,14 +178,16 @@ jobs:
162178
- uses: Swatinem/rust-cache@v2
163179
with:
164180
workspaces: . -> target
165-
key: plugin-${{ matrix.target }}-${{ needs.context.outputs.trigger }}
181+
key: plugin-${{ matrix.target }}-${{ env.LINUX_GNU_SYSROOT_TAG }}-llvm-${{ env.LINUX_GNU_LLVM_VERSION }}-${{ needs.context.outputs.trigger }}
166182
- uses: actions/cache@v4
167183
with:
168184
path: ~/.cargo/.rusty_v8
169185
key: ${{ runner.os }}-${{ matrix.target }}-rusty-v8-${{ hashFiles('Cargo.lock') }}
170186
restore-keys: |
171187
${{ runner.os }}-${{ matrix.target }}-rusty-v8-
172188
- run: pnpm install --frozen-lockfile --filter='!@agentos/website'
189+
- name: Set up Linux GNU sysroot
190+
run: scripts/ci/setup-linux-gnu-sysroot.sh
173191
- name: Build plugin cdylib
174192
id: build
175193
run: |
@@ -186,6 +204,14 @@ jobs:
186204
cp "target/${{ matrix.target }}/${profile}/libagentos_actor_plugin.so" \
187205
"$out/libagentos_actor_plugin.so"
188206
echo "dir=$out" >> "$GITHUB_OUTPUT"
207+
- name: Check glibc floor
208+
run: |
209+
scripts/ci/check-linux-glibc-floor.sh \
210+
"${{ steps.build.outputs.dir }}/libagentos_actor_plugin.so"
211+
- name: Smoke-run in old Linux containers
212+
run: |
213+
scripts/ci/smoke-linux-artifacts.sh shared-library \
214+
"${{ steps.build.outputs.dir }}/libagentos_actor_plugin.so"
189215
- uses: actions/upload-artifact@v4
190216
with:
191217
name: plugin-${{ matrix.platform }}

scripts/ci/agentos-gettid-shim.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#define _GNU_SOURCE
2+
#include <sys/syscall.h>
3+
#include <sys/types.h>
4+
#include <unistd.h>
5+
6+
#ifndef SYS_gettid
7+
# if defined(__x86_64__)
8+
# define SYS_gettid 186
9+
# elif defined(__aarch64__)
10+
# define SYS_gettid 178
11+
# elif defined(__arm__)
12+
# define SYS_gettid 224
13+
# elif defined(__i386__)
14+
# define SYS_gettid 224
15+
# elif defined(__powerpc64__)
16+
# define SYS_gettid 207
17+
# else
18+
# error "gettid syscall number unknown for this architecture"
19+
# endif
20+
#endif
21+
22+
pid_t gettid(void) {
23+
return (pid_t)syscall(SYS_gettid);
24+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
floor_minor="${LINUX_GNU_GLIBC_FLOOR_MINOR:-27}"
5+
regression_minor="${LINUX_GNU_GLIBC_REGRESSION_MINOR:-32}"
6+
7+
if [ "$#" -eq 0 ]; then
8+
echo "usage: $0 <elf>..." >&2
9+
exit 2
10+
fi
11+
12+
for artifact in "$@"; do
13+
echo "Checking glibc symbol floor for ${artifact}"
14+
versions="$(objdump -T "${artifact}" | grep -oE 'GLIBC_2\.[0-9]+' | sort -Vu || true)"
15+
16+
if [ -z "${versions}" ]; then
17+
echo "No GLIBC_2.x symbols found in ${artifact}."
18+
continue
19+
fi
20+
21+
echo "${versions}"
22+
23+
while IFS= read -r version; do
24+
minor="${version#GLIBC_2.}"
25+
if [ "${minor}" -ge "${regression_minor}" ]; then
26+
echo "${artifact} references ${version}; this is at or above the hard regression tripwire GLIBC_2.${regression_minor}." >&2
27+
exit 1
28+
fi
29+
if [ "${minor}" -gt "${floor_minor}" ]; then
30+
echo "${artifact} references ${version}; expected GLIBC_2.${floor_minor} or older." >&2
31+
exit 1
32+
fi
33+
done <<< "${versions}"
34+
done
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2018-2026 the Deno authors. MIT license.
2+
3+
#define _GNU_SOURCE
4+
#include <fcntl.h>
5+
#include <sys/syscall.h>
6+
#include <unistd.h>
7+
8+
#ifndef SYS_memfd_create
9+
# if defined(__x86_64__)
10+
# define SYS_memfd_create 319
11+
# elif defined(__aarch64__)
12+
# define SYS_memfd_create 279
13+
# elif defined(__arm__)
14+
# define SYS_memfd_create 385
15+
# elif defined(__i386__)
16+
# define SYS_memfd_create 356
17+
# elif defined(__powerpc64__)
18+
# define SYS_memfd_create 360
19+
# else
20+
# error "memfd_create syscall number unknown for this architecture"
21+
# endif
22+
#endif
23+
24+
int memfd_create(const char *name, unsigned int flags) {
25+
return syscall(SYS_memfd_create, name, flags);
26+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
llvm_version="${LINUX_GNU_LLVM_VERSION:-22}"
5+
sysroot_tag="${LINUX_GNU_SYSROOT_TAG:-sysroot-20250207}"
6+
github_env="${GITHUB_ENV:?GITHUB_ENV must be set by GitHub Actions}"
7+
8+
export DEBIAN_FRONTEND=noninteractive
9+
10+
# Match Deno's sysroot-link setup closely enough that Rust, C/C++, and lld all
11+
# resolve against the bionic sysroot instead of the runner's host glibc.
12+
sudo apt-get -qq remove --purge -y man-db > /dev/null 2> /dev/null || true
13+
sudo apt-get -qq remove \
14+
'clang-12*' 'clang-13*' 'clang-14*' 'clang-15*' 'clang-16*' \
15+
'clang-17*' 'clang-18*' 'clang-19*' 'clang-20*' 'clang-21*' \
16+
'llvm-12*' 'llvm-13*' 'llvm-14*' 'llvm-15*' 'llvm-16*' \
17+
'llvm-17*' 'llvm-18*' 'llvm-19*' 'llvm-20*' 'llvm-21*' \
18+
'lld-12*' 'lld-13*' 'lld-14*' 'lld-15*' 'lld-16*' \
19+
'lld-17*' 'lld-18*' 'lld-19*' 'lld-20*' 'lld-21*' \
20+
> /dev/null 2> /dev/null || true
21+
22+
. /etc/os-release
23+
codename="${VERSION_CODENAME:?missing VERSION_CODENAME in /etc/os-release}"
24+
apt_list="/etc/apt/sources.list.d/llvm-toolchain-${codename}-${llvm_version}.list"
25+
26+
echo "deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${llvm_version} main" \
27+
| sudo dd "of=${apt_list}" > /dev/null
28+
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \
29+
| gpg --dearmor \
30+
| sudo dd "of=/etc/apt/trusted.gpg.d/llvm-snapshot.gpg" > /dev/null
31+
32+
sudo apt-get update
33+
sudo apt-get install -y --no-install-recommends \
34+
binutils \
35+
"clang-${llvm_version}" \
36+
"lld-${llvm_version}" \
37+
xz-utils
38+
39+
"clang-${llvm_version}" -c -o /tmp/agentos_memfd_create_shim.o \
40+
scripts/ci/deno-memfd-create-shim.c -fPIC
41+
"clang-${llvm_version}" -c -o /tmp/agentos_gettid_shim.o \
42+
scripts/ci/agentos-gettid-shim.c -fPIC
43+
44+
sysroot_arch="$(uname -m)"
45+
sysroot_url="https://github.com/denoland/deno_sysroot_build/releases/download/${sysroot_tag}/sysroot-${sysroot_arch}.tar.xz"
46+
47+
curl -fsSL "${sysroot_url}" -o /tmp/agentos-sysroot.tar.xz
48+
sudo rm -rf /sysroot
49+
cd /
50+
xzcat /tmp/agentos-sysroot.tar.xz | sudo tar -x
51+
cd "${GITHUB_WORKSPACE:?GITHUB_WORKSPACE must be set by GitHub Actions}"
52+
53+
. /sysroot/.env
54+
55+
rustflags_extra="-C linker-plugin-lto=true \
56+
-C linker=clang-${llvm_version} \
57+
-C link-arg=-fuse-ld=lld-${llvm_version} \
58+
-C link-arg=-ldl \
59+
-C link-arg=-Wl,--allow-shlib-undefined \
60+
-C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache \
61+
-C link-arg=-Wl,--thinlto-cache-policy,cache_size_bytes=700m \
62+
-C link-arg=/tmp/agentos_memfd_create_shim.o \
63+
-C link-arg=/tmp/agentos_gettid_shim.o \
64+
${RUSTFLAGS:-}"
65+
66+
{
67+
echo "CARGO_PROFILE_BENCH_INCREMENTAL=false"
68+
echo "CARGO_PROFILE_RELEASE_INCREMENTAL=false"
69+
echo "CC=/usr/bin/clang-${llvm_version}"
70+
echo "CFLAGS=${CFLAGS:-}"
71+
echo "RUSTFLAGS<<__AGENTOS_SYSROOT_RUSTFLAGS"
72+
echo "${rustflags_extra}"
73+
echo "__AGENTOS_SYSROOT_RUSTFLAGS"
74+
echo "RUSTDOCFLAGS<<__AGENTOS_SYSROOT_RUSTDOCFLAGS"
75+
echo "${rustflags_extra}"
76+
echo "__AGENTOS_SYSROOT_RUSTDOCFLAGS"
77+
} >> "${github_env}"
78+
79+
echo "Configured ${sysroot_tag} (${sysroot_arch}) with LLVM ${llvm_version}."
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
kind="${1:-}"
5+
shift || true
6+
7+
if [ -z "${kind}" ] || [ "$#" -eq 0 ]; then
8+
echo "usage: $0 <binary|shared-library> <artifact>..." >&2
9+
exit 2
10+
fi
11+
12+
case "${kind}" in
13+
binary | shared-library) ;;
14+
*)
15+
echo "unsupported artifact kind: ${kind}" >&2
16+
exit 2
17+
;;
18+
esac
19+
20+
tmpdir="$(mktemp -d)"
21+
trap 'rm -rf "${tmpdir}"' EXIT
22+
23+
if command -v docker >/dev/null 2>&1; then
24+
container_runtime=docker
25+
elif command -v podman >/dev/null 2>&1; then
26+
container_runtime=podman
27+
else
28+
if command -v sudo >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then
29+
sudo apt-get update
30+
sudo apt-get install -y podman
31+
fi
32+
33+
if command -v podman >/dev/null 2>&1; then
34+
container_runtime=podman
35+
else
36+
echo "docker or podman is required for Linux compatibility smoke tests" >&2
37+
exit 127
38+
fi
39+
fi
40+
41+
run_container() {
42+
"${container_runtime}" run --rm -v "${tmpdir}:/artifacts:ro" "$@"
43+
}
44+
45+
for artifact in "$@"; do
46+
cp "${artifact}" "${tmpdir}/$(basename "${artifact}")"
47+
chmod +x "${tmpdir}/$(basename "${artifact}")"
48+
done
49+
50+
for image in docker.io/library/debian:11 docker.io/library/ubuntu:20.04; do
51+
for artifact in "$@"; do
52+
name="$(basename "${artifact}")"
53+
echo "Smoke-checking ${name} in ${image}"
54+
if [ "${kind}" = "binary" ]; then
55+
run_container "${image}" /bin/sh -ceu '
56+
status=0
57+
timeout 5s "/artifacts/$1" --version > /tmp/agentos-smoke.out 2> /tmp/agentos-smoke.err || status=$?
58+
cat /tmp/agentos-smoke.out
59+
cat /tmp/agentos-smoke.err >&2
60+
if grep -E "GLIBC_2\\.[0-9]+.*not found|version .*GLIBC_2\\.[0-9]+" /tmp/agentos-smoke.err >&2; then
61+
exit 1
62+
fi
63+
if [ "${status}" -eq 126 ] || [ "${status}" -eq 127 ]; then
64+
exit "${status}"
65+
fi
66+
exit 0
67+
' sh "${name}"
68+
else
69+
run_container "${image}" /bin/sh -ceu '
70+
ldd "/artifacts/$1"
71+
' sh "${name}"
72+
fi
73+
done
74+
done

0 commit comments

Comments
 (0)