Skip to content

Commit dc8dbc3

Browse files
committed
Fix CI e2e runtime injection for amd64 guest assets
1 parent f9f5995 commit dc8dbc3

2 files changed

Lines changed: 64 additions & 7 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules/
22
dist/
33
out/
4+
.local-tests/

src/oci2gondolin/materialize/runtime-injection.ts

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ const REQUIRED_RUNTIME_FILES: RuntimeFileSpec[] = [
2828
targetRelativePath: "bin/kmod",
2929
mode: 0o755,
3030
},
31-
{
32-
sourcePathInRootfs: "/lib/ld-musl-aarch64.so.1",
33-
targetRelativePath: "lib/ld-musl-aarch64.so.1",
34-
mode: 0o755,
35-
},
3631
{
3732
sourcePathInRootfs: "/usr/lib/libcrypto.so.3",
3833
targetRelativePath: "usr/lib/libcrypto.so.3",
@@ -70,6 +65,8 @@ const REQUIRED_RUNTIME_FILES: RuntimeFileSpec[] = [
7065
},
7166
];
7267

68+
const LOADER_CANDIDATE_PATHS = ["/lib/ld-musl-aarch64.so.1", "/lib/ld-musl-x86_64.so.1"];
69+
7370
const REQUIRED_RUNTIME_DIRECTORIES: RuntimeDirectorySpec[] = [
7471
{
7572
sourcePathInRootfs: "/lib/modules",
@@ -136,6 +133,23 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
136133
const injectedFiles: string[] = [];
137134
const injectedDirectories: string[] = [];
138135

136+
const loaderSourcePath = resolveExistingPathInExt4(
137+
debugfsCmd,
138+
baseRootfsPath,
139+
LOADER_CANDIDATE_PATHS,
140+
"musl dynamic loader",
141+
);
142+
const loaderFileName = path.posix.basename(loaderSourcePath);
143+
144+
const runtimeFiles: RuntimeFileSpec[] = [
145+
...REQUIRED_RUNTIME_FILES,
146+
{
147+
sourcePathInRootfs: loaderSourcePath,
148+
targetRelativePath: `lib/${loaderFileName}`,
149+
mode: 0o755,
150+
},
151+
];
152+
139153
for (const runtimeDirectory of REQUIRED_RUNTIME_DIRECTORIES) {
140154
const finalPath = path.join(rootfsDir, runtimeDirectory.targetRelativePath);
141155
dumpDirectoryFromExt4(
@@ -148,7 +162,7 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
148162
injectedDirectories.push(finalPath);
149163
}
150164

151-
for (const runtimeFile of REQUIRED_RUNTIME_FILES) {
165+
for (const runtimeFile of runtimeFiles) {
152166
const finalPath = path.join(rootfsDir, runtimeFile.targetRelativePath);
153167
ensureParentDirectory(rootfsDir, path.dirname(finalPath));
154168

@@ -167,7 +181,12 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
167181

168182
ensureSymlink(rootfsDir, "sbin/modprobe", "../bin/kmod");
169183
ensureSymlink(rootfsDir, "sbin/insmod", "../bin/kmod");
170-
ensureSymlink(rootfsDir, "lib/libc.musl-aarch64.so.1", "ld-musl-aarch64.so.1");
184+
185+
const muslLibcSymlinkName = deriveMuslLibcSymlinkName(loaderFileName);
186+
if (muslLibcSymlinkName) {
187+
ensureSymlink(rootfsDir, `lib/${muslLibcSymlinkName}`, loaderFileName);
188+
}
189+
171190
ensureSymlink(rootfsDir, "usr/lib/liblzma.so.5", "liblzma.so.5.8.2");
172191
ensureSymlink(rootfsDir, "usr/lib/libz.so.1", "libz.so.1.3.1");
173192
ensureSymlink(rootfsDir, "usr/lib/libzstd.so.1", "libzstd.so.1.5.7");
@@ -179,6 +198,43 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
179198
};
180199
}
181200

201+
function resolveExistingPathInExt4(
202+
debugfsCmd: string,
203+
ext4Path: string,
204+
candidates: string[],
205+
label: string,
206+
): string {
207+
for (const candidate of candidates) {
208+
if (pathExistsInExt4(debugfsCmd, ext4Path, candidate)) {
209+
return candidate;
210+
}
211+
}
212+
213+
throw new CliUsageError(`Failed to locate required ${label} in base rootfs.`, [
214+
`Searched paths: ${candidates.join(", ")}`,
215+
`Base rootfs: ${ext4Path}`,
216+
"Ensure gondolin guest assets are complete for your host architecture.",
217+
]);
218+
}
219+
220+
function pathExistsInExt4(debugfsCmd: string, ext4Path: string, sourcePath: string): boolean {
221+
const result = spawnSync(debugfsCmd, ["-R", `stat ${sourcePath}`, ext4Path], {
222+
encoding: "utf8",
223+
stdio: ["ignore", "pipe", "pipe"],
224+
});
225+
226+
return result.status === 0;
227+
}
228+
229+
function deriveMuslLibcSymlinkName(loaderFileName: string): string | undefined {
230+
const match = /^ld-musl-(.+)\.so\.1$/.exec(loaderFileName);
231+
if (!match) {
232+
return undefined;
233+
}
234+
235+
return `libc.musl-${match[1]}.so.1`;
236+
}
237+
182238
function dumpDirectoryFromExt4(
183239
debugfsCmd: string,
184240
ext4Path: string,

0 commit comments

Comments
 (0)