Skip to content

Commit 39b1570

Browse files
authored
fix(ci): pin linux glibc floor for published binaries (#1647)
1 parent 5bf5901 commit 39b1570

6 files changed

Lines changed: 246 additions & 2 deletions

File tree

.github/workflows/publish.yaml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ 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"
2527

2628
jobs:
2729
context:
@@ -103,14 +105,16 @@ jobs:
103105
- uses: Swatinem/rust-cache@v2
104106
with:
105107
workspaces: . -> target
106-
key: ${{ matrix.target }}-${{ needs.context.outputs.trigger }}
108+
key: ${{ matrix.target }}-${{ env.LINUX_GNU_SYSROOT_TAG }}-llvm-${{ env.LINUX_GNU_LLVM_VERSION }}-${{ needs.context.outputs.trigger }}
107109
- uses: actions/cache@v4
108110
with:
109111
path: ~/.cargo/.rusty_v8
110112
key: ${{ runner.os }}-${{ matrix.target }}-rusty-v8-${{ hashFiles('Cargo.lock') }}
111113
restore-keys: |
112114
${{ runner.os }}-${{ matrix.target }}-rusty-v8-
113115
- run: pnpm install --frozen-lockfile --filter='!@agentos/website'
116+
- name: Set up Linux GNU sysroot
117+
run: scripts/ci/setup-linux-gnu-sysroot.sh
114118
- name: Build sidecar binaries
115119
id: build
116120
run: |
@@ -128,6 +132,16 @@ jobs:
128132
cp "target/${{ matrix.target }}/${profile}/agentos-sidecar" "$out/agentos-sidecar"
129133
cp "target/${{ matrix.target }}/${profile}/agentos-native-sidecar" "$out/agentos-native-sidecar"
130134
echo "dir=$out" >> "$GITHUB_OUTPUT"
135+
- name: Check glibc floor
136+
run: |
137+
scripts/ci/check-linux-glibc-floor.sh \
138+
"${{ steps.build.outputs.dir }}/agentos-sidecar" \
139+
"${{ steps.build.outputs.dir }}/agentos-native-sidecar"
140+
- name: Smoke-run in old Linux containers
141+
run: |
142+
scripts/ci/smoke-linux-artifacts.sh binary \
143+
"${{ steps.build.outputs.dir }}/agentos-sidecar" \
144+
"${{ steps.build.outputs.dir }}/agentos-native-sidecar"
131145
- uses: actions/upload-artifact@v4
132146
with:
133147
name: sidecar-${{ matrix.platform }}
@@ -162,14 +176,16 @@ jobs:
162176
- uses: Swatinem/rust-cache@v2
163177
with:
164178
workspaces: . -> target
165-
key: plugin-${{ matrix.target }}-${{ needs.context.outputs.trigger }}
179+
key: plugin-${{ matrix.target }}-${{ env.LINUX_GNU_SYSROOT_TAG }}-llvm-${{ env.LINUX_GNU_LLVM_VERSION }}-${{ needs.context.outputs.trigger }}
166180
- uses: actions/cache@v4
167181
with:
168182
path: ~/.cargo/.rusty_v8
169183
key: ${{ runner.os }}-${{ matrix.target }}-rusty-v8-${{ hashFiles('Cargo.lock') }}
170184
restore-keys: |
171185
${{ runner.os }}-${{ matrix.target }}-rusty-v8-
172186
- run: pnpm install --frozen-lockfile --filter='!@agentos/website'
187+
- name: Set up Linux GNU sysroot
188+
run: scripts/ci/setup-linux-gnu-sysroot.sh
173189
- name: Build plugin cdylib
174190
id: build
175191
run: |
@@ -186,6 +202,14 @@ jobs:
186202
cp "target/${{ matrix.target }}/${profile}/libagentos_actor_plugin.so" \
187203
"$out/libagentos_actor_plugin.so"
188204
echo "dir=$out" >> "$GITHUB_OUTPUT"
205+
- name: Check glibc floor
206+
run: |
207+
scripts/ci/check-linux-glibc-floor.sh \
208+
"${{ steps.build.outputs.dir }}/libagentos_actor_plugin.so"
209+
- name: Smoke-run in old Linux containers
210+
run: |
211+
scripts/ci/smoke-linux-artifacts.sh shared-library \
212+
"${{ steps.build.outputs.dir }}/libagentos_actor_plugin.so"
189213
- uses: actions/upload-artifact@v4
190214
with:
191215
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=27
5+
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: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
. /etc/os-release
11+
codename="${VERSION_CODENAME:?missing VERSION_CODENAME in /etc/os-release}"
12+
apt_list="/etc/apt/sources.list.d/llvm-toolchain-${codename}-${llvm_version}.list"
13+
14+
echo "deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${llvm_version} main" \
15+
| sudo dd "of=${apt_list}" > /dev/null
16+
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \
17+
| gpg --dearmor \
18+
| sudo dd "of=/etc/apt/trusted.gpg.d/llvm-snapshot.gpg" > /dev/null
19+
20+
sudo apt-get update
21+
sudo apt-get install -y --no-install-recommends \
22+
binutils \
23+
"clang-${llvm_version}" \
24+
"lld-${llvm_version}" \
25+
xz-utils
26+
27+
"clang-${llvm_version}" -c -o /tmp/agentos_memfd_create_shim.o \
28+
scripts/ci/deno-memfd-create-shim.c -fPIC
29+
"clang-${llvm_version}" -c -o /tmp/agentos_gettid_shim.o \
30+
scripts/ci/agentos-gettid-shim.c -fPIC
31+
32+
sysroot_arch="$(uname -m)"
33+
sysroot_url="https://github.com/denoland/deno_sysroot_build/releases/download/${sysroot_tag}/sysroot-${sysroot_arch}.tar.xz"
34+
35+
curl -fsSL "${sysroot_url}" -o /tmp/agentos-sysroot.tar.xz
36+
sudo rm -rf /sysroot
37+
cd /
38+
xzcat /tmp/agentos-sysroot.tar.xz | sudo tar -x
39+
cd "${GITHUB_WORKSPACE:?GITHUB_WORKSPACE must be set by GitHub Actions}"
40+
41+
. /sysroot/.env
42+
43+
rustflags_extra="-C linker-plugin-lto=true \
44+
-C linker=clang-${llvm_version} \
45+
-C link-arg=-fuse-ld=lld-${llvm_version} \
46+
-C link-arg=-ldl \
47+
-C link-arg=-Wl,--allow-shlib-undefined \
48+
-C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache \
49+
-C link-arg=-Wl,--thinlto-cache-policy,cache_size_bytes=700m \
50+
-C link-arg=/tmp/agentos_memfd_create_shim.o \
51+
-C link-arg=/tmp/agentos_gettid_shim.o \
52+
${RUSTFLAGS:-}"
53+
54+
{
55+
echo "CC=/usr/bin/clang-${llvm_version}"
56+
echo "CFLAGS=${CFLAGS:-}"
57+
echo "RUSTFLAGS<<__AGENTOS_SYSROOT_RUSTFLAGS"
58+
echo "${rustflags_extra}"
59+
echo "__AGENTOS_SYSROOT_RUSTFLAGS"
60+
} >> "${github_env}"
61+
62+
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)