diff --git a/index.ts b/index.ts index 7581e6e..5a8a01a 100644 --- a/index.ts +++ b/index.ts @@ -4,17 +4,23 @@ import { copyFile, mkdir, opendir, + readdir, rm, symlink, writeFile, } from "node:fs/promises"; +import { tmpdir } from "node:os"; import { basename, join } from "node:path"; import { promisify } from "node:util"; const execFile = promisify(execFileCallback); +// TODO: configurar runsc +// TODO: cache de apk (robar de define-alpine-the-sequel) + const currRootPath = await setupRootfsDir(); await setupBasicApkEnvironment(currRootPath); +const packages = ["alpine-base", "fish", "docker", "linux-virt"]; await execFile("doas", [ "apk", "--initdb", @@ -22,9 +28,25 @@ await execFile("doas", [ "--root", currRootPath, "add", - ...["alpine-baselayout", "busybox", "libc-utils", "alpine-keys"], - "fish", + ...packages, ]); +await chroot(currRootPath, ["rc-update", "add", "docker", "default"]); + +await chroot(currRootPath, ["rc-update", "add", "localmount", "boot"]); +await writeFstab(currRootPath); + +// make VM disk image +const ext4Path = "raw.ext4"; +await execFile("qemu-img", ["create", "-f", "raw", ext4Path, "50G"]); +await execFile("mkfs.ext4", [ext4Path]); + +const mntdir = join(tmpdir(), "woodpecker-in-a-vm-" + nanoid()); +await mkdir(mntdir); +await execFile("doas", ["mount", ext4Path, mntdir]); +for (const path of await readdir(currRootPath)) + await execFile("doas", ["cp", "-r", join(currRootPath, path), mntdir]); +await execFile("doas", ["umount", mntdir]); +await execFile("qemu-img", ["convert", "-O", "qcow2", ext4Path, "vm.qcow2"]); async function setupRootfsDir() { const artifactsPath = "./artifacts"; @@ -58,3 +80,17 @@ async function setupBasicApkEnvironment(rootfs: string) { ].join("\n") ); } + +async function writeFstab(rootfs: string) { + const virtualDiskName = "/dev/vda"; + await writeFile( + "fstab", + `${virtualDiskName} / ext4 rw,relatime,discard 0 1 +` + ); + await execFile("doas", ["mv", "fstab", join(rootfs, "/etc/fstab")]); +} + +async function chroot(rootfs: string, cmd: string[]) { + await execFile("doas", ["chroot", rootfs, ...cmd]); +}