Compare commits
3 commits
5502061f21
...
eb0a9d937d
Author | SHA1 | Date | |
---|---|---|---|
eb0a9d937d | |||
c6cd179efd | |||
5c5be0420f |
6 changed files with 245 additions and 347 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,4 +1,7 @@
|
|||
artifacts
|
||||
node_modules
|
||||
index.js
|
||||
index.js.map
|
||||
*.ext4
|
||||
*.qcow2
|
||||
.env
|
||||
initramfs-virt
|
||||
vmlinuz-virt
|
||||
|
|
199
index.js
Normal file
199
index.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
// @ts-check
|
||||
import { nanoid } from "nanoid";
|
||||
import { execFile as execFileCallback } from "node:child_process";
|
||||
import {
|
||||
constants,
|
||||
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";
|
||||
import * as dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
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",
|
||||
"--clean-protected",
|
||||
"--root",
|
||||
currRootPath,
|
||||
"add",
|
||||
...packages,
|
||||
]);
|
||||
await chroot(currRootPath, ["rc-update", "add", "networking", "sysinit"]);
|
||||
await chroot(currRootPath, ["rc-update", "add", "docker", "boot"]);
|
||||
await chroot(currRootPath, ["rc-update", "add", "acpid", "default"]);
|
||||
await chroot(currRootPath, ["rc-update", "add", "local", "default"]);
|
||||
|
||||
await writeFile(
|
||||
"interfaces",
|
||||
`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0
|
||||
use dhcp`,
|
||||
{ mode: 0o600 }
|
||||
);
|
||||
await execFile("doas", [
|
||||
"mv",
|
||||
"interfaces",
|
||||
join(currRootPath, "/etc/network/interfaces"),
|
||||
]);
|
||||
await execFile("doas", [
|
||||
"chown",
|
||||
"0:0",
|
||||
join(currRootPath, "/etc/network/interfaces"),
|
||||
]);
|
||||
|
||||
const woodpeckerSecret = getConfig("WOODPECKER_SECRET");
|
||||
const woodpeckerServer = getConfig("WOODPECKER_SERVER");
|
||||
|
||||
await writeFile(
|
||||
"woodpecker.start",
|
||||
`#!/bin/sh
|
||||
docker pull docker.io/woodpeckerci/woodpecker-agent:latest || exit $?
|
||||
exec docker run --detach --rm \
|
||||
--name=woodpecker-agent \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e WOODPECKER_SERVER='${woodpeckerServer}' \
|
||||
-e WOODPECKER_SECRET='${woodpeckerSecret}' \
|
||||
-e WOODPECKER_MAX_PROCS=8 \
|
||||
docker.io/woodpeckerci/woodpecker-agent:latest \
|
||||
agent`,
|
||||
{ mode: 0o700 }
|
||||
);
|
||||
await execFile("doas", [
|
||||
"mv",
|
||||
"woodpecker.start",
|
||||
join(currRootPath, "/etc/local.d/woodpecker.start"),
|
||||
]);
|
||||
await execFile("doas", [
|
||||
"chown",
|
||||
"0:0",
|
||||
join(currRootPath, "/etc/local.d/woodpecker.start"),
|
||||
]);
|
||||
|
||||
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("doas", [
|
||||
"qemu-img",
|
||||
"convert",
|
||||
"-O",
|
||||
"qcow2",
|
||||
ext4Path,
|
||||
"vm.qcow2",
|
||||
]);
|
||||
|
||||
await copyFile(
|
||||
join(currRootPath, "boot/vmlinuz-virt"),
|
||||
"./vmlinuz-virt",
|
||||
constants.COPYFILE_FICLONE
|
||||
);
|
||||
await copyFile(
|
||||
join(currRootPath, "boot/initramfs-virt"),
|
||||
"./initramfs-virt",
|
||||
constants.COPYFILE_FICLONE
|
||||
);
|
||||
await execFile("doas", [
|
||||
"chown",
|
||||
"1000:1000",
|
||||
"./vmlinuz-virt",
|
||||
"./initramfs-virt",
|
||||
"./vm.qcow2",
|
||||
]);
|
||||
|
||||
async function setupRootfsDir() {
|
||||
const artifactsPath = "./artifacts";
|
||||
const currRootPath = join(artifactsPath, "rootfs" + nanoid());
|
||||
await mkdir(currRootPath, { recursive: true });
|
||||
|
||||
{
|
||||
const currentPath = join(artifactsPath, "current");
|
||||
try {
|
||||
await rm(currentPath);
|
||||
} catch {}
|
||||
await symlink(basename(currRootPath), currentPath);
|
||||
}
|
||||
return currRootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} rootfs
|
||||
*/
|
||||
async function setupBasicApkEnvironment(rootfs) {
|
||||
{
|
||||
const apkKeysDir = join(rootfs, "/etc/apk/keys");
|
||||
const keysSrcDir = "alpine/keys";
|
||||
await mkdir(apkKeysDir, { recursive: true });
|
||||
for await (const { name } of await opendir(keysSrcDir))
|
||||
await copyFile(join(keysSrcDir, name), join(apkKeysDir, name));
|
||||
}
|
||||
|
||||
await writeFile(
|
||||
join(rootfs, "/etc/apk/repositories"),
|
||||
[
|
||||
// "https://dl-cdn.alpinelinux.org/alpine/v3.17/main",
|
||||
// "https://dl-cdn.alpinelinux.org/alpine/v3.17/community",
|
||||
"http://alpinelinux.c3sl.ufpr.br/v3.17/main",
|
||||
"http://alpinelinux.c3sl.ufpr.br/v3.17/community",
|
||||
].join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} rootfs
|
||||
*/
|
||||
async function writeFstab(rootfs) {
|
||||
const virtualDiskName = "/dev/vda";
|
||||
await writeFile(
|
||||
"fstab",
|
||||
`${virtualDiskName} / ext4 rw,relatime,discard 0 1
|
||||
`
|
||||
);
|
||||
await execFile("doas", ["mv", "fstab", join(rootfs, "/etc/fstab")]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Corre comando en chroot
|
||||
* @param {string} rootfs
|
||||
* @param {string[]} cmd
|
||||
*/
|
||||
async function chroot(rootfs, cmd) {
|
||||
await execFile("doas", ["chroot", rootfs, ...cmd]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {string} la variable conseguida
|
||||
*/
|
||||
function getConfig(name) {
|
||||
if (name in process.env) return process.env[name] || "";
|
||||
else throw new Error(`Falta la variable ${name}`);
|
||||
}
|
96
index.ts
96
index.ts
|
@ -1,96 +0,0 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import { execFile as execFileCallback } from "node:child_process";
|
||||
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",
|
||||
"--clean-protected",
|
||||
"--root",
|
||||
currRootPath,
|
||||
"add",
|
||||
...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";
|
||||
const currRootPath = join(artifactsPath, "rootfs" + nanoid());
|
||||
await mkdir(currRootPath, { recursive: true });
|
||||
|
||||
{
|
||||
const currentPath = join(artifactsPath, "current");
|
||||
try {
|
||||
await rm(currentPath);
|
||||
} catch {}
|
||||
await symlink(basename(currRootPath), currentPath);
|
||||
}
|
||||
return currRootPath;
|
||||
}
|
||||
|
||||
async function setupBasicApkEnvironment(rootfs: string) {
|
||||
{
|
||||
const apkKeysDir = join(rootfs, "/etc/apk/keys");
|
||||
const keysSrcDir = "alpine/keys";
|
||||
await mkdir(apkKeysDir, { recursive: true });
|
||||
for await (const { name } of await opendir(keysSrcDir))
|
||||
await copyFile(join(keysSrcDir, name), join(apkKeysDir, name));
|
||||
}
|
||||
|
||||
await writeFile(
|
||||
join(rootfs, "/etc/apk/repositories"),
|
||||
[
|
||||
"https://dl-cdn.alpinelinux.org/alpine/v3.17/main",
|
||||
"https://dl-cdn.alpinelinux.org/alpine/v3.17/community",
|
||||
].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]);
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
{
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"run": "esbuild --log-level=warning --target=node18 --platform=node --sourcemap --outdir=. --format=esm --bundle index.ts && node --enable-source-maps index.js"
|
||||
"run": "node index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.15.5",
|
||||
"esbuild": "^0.17.12",
|
||||
"typescript": "^5.0.2"
|
||||
"@types/node": "^18.15.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.0.3",
|
||||
"nanoid": "^4.0.1"
|
||||
}
|
||||
}
|
||||
|
|
260
pnpm-lock.yaml
260
pnpm-lock.yaml
|
@ -1,261 +1,31 @@
|
|||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@types/node': ^18.15.5
|
||||
esbuild: ^0.17.12
|
||||
nanoid: ^4.0.1
|
||||
typescript: ^5.0.2
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
dependencies:
|
||||
nanoid: 4.0.1
|
||||
dotenv:
|
||||
specifier: ^16.0.3
|
||||
version: 16.0.3
|
||||
nanoid:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
|
||||
devDependencies:
|
||||
'@types/node': 18.15.5
|
||||
esbuild: 0.17.12
|
||||
typescript: 5.0.2
|
||||
'@types/node':
|
||||
specifier: ^18.15.5
|
||||
version: 18.15.5
|
||||
|
||||
packages:
|
||||
|
||||
/@esbuild/android-arm/0.17.12:
|
||||
resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/android-arm64/0.17.12:
|
||||
resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/android-x64/0.17.12:
|
||||
resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/darwin-arm64/0.17.12:
|
||||
resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/darwin-x64/0.17.12:
|
||||
resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/freebsd-arm64/0.17.12:
|
||||
resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/freebsd-x64/0.17.12:
|
||||
resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-arm/0.17.12:
|
||||
resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-arm64/0.17.12:
|
||||
resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-ia32/0.17.12:
|
||||
resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-loong64/0.17.12:
|
||||
resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-mips64el/0.17.12:
|
||||
resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-ppc64/0.17.12:
|
||||
resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-riscv64/0.17.12:
|
||||
resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-s390x/0.17.12:
|
||||
resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-x64/0.17.12:
|
||||
resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/netbsd-x64/0.17.12:
|
||||
resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/openbsd-x64/0.17.12:
|
||||
resolution: {integrity: sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/sunos-x64/0.17.12:
|
||||
resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-arm64/0.17.12:
|
||||
resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-ia32/0.17.12:
|
||||
resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@esbuild/win32-x64/0.17.12:
|
||||
resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@types/node/18.15.5:
|
||||
/@types/node@18.15.5:
|
||||
resolution: {integrity: sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==}
|
||||
dev: true
|
||||
|
||||
/esbuild/0.17.12:
|
||||
resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==}
|
||||
/dotenv@16.0.3:
|
||||
resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@esbuild/android-arm': 0.17.12
|
||||
'@esbuild/android-arm64': 0.17.12
|
||||
'@esbuild/android-x64': 0.17.12
|
||||
'@esbuild/darwin-arm64': 0.17.12
|
||||
'@esbuild/darwin-x64': 0.17.12
|
||||
'@esbuild/freebsd-arm64': 0.17.12
|
||||
'@esbuild/freebsd-x64': 0.17.12
|
||||
'@esbuild/linux-arm': 0.17.12
|
||||
'@esbuild/linux-arm64': 0.17.12
|
||||
'@esbuild/linux-ia32': 0.17.12
|
||||
'@esbuild/linux-loong64': 0.17.12
|
||||
'@esbuild/linux-mips64el': 0.17.12
|
||||
'@esbuild/linux-ppc64': 0.17.12
|
||||
'@esbuild/linux-riscv64': 0.17.12
|
||||
'@esbuild/linux-s390x': 0.17.12
|
||||
'@esbuild/linux-x64': 0.17.12
|
||||
'@esbuild/netbsd-x64': 0.17.12
|
||||
'@esbuild/openbsd-x64': 0.17.12
|
||||
'@esbuild/sunos-x64': 0.17.12
|
||||
'@esbuild/win32-arm64': 0.17.12
|
||||
'@esbuild/win32-ia32': 0.17.12
|
||||
'@esbuild/win32-x64': 0.17.12
|
||||
dev: true
|
||||
dev: false
|
||||
|
||||
/nanoid/4.0.1:
|
||||
/nanoid@4.0.1:
|
||||
resolution: {integrity: sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==}
|
||||
engines: {node: ^14 || ^16 || >=18}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/typescript/5.0.2:
|
||||
resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==}
|
||||
engines: {node: '>=12.20'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
|
23
readme.md
23
readme.md
|
@ -4,3 +4,26 @@
|
|||
1. lo configuré para que borre en el disco real si se borra algo dentro de la vm
|
||||
1. como woodpecker-agent no tiene state, puedo regenerar la vm con el script las veces que quiera
|
||||
1. no tengo que exponer mi docker real al agent porque está en una vm con el suyo
|
||||
|
||||
|
||||
## compilar imágen
|
||||
|
||||
```sh
|
||||
node index.js
|
||||
```
|
||||
|
||||
copiar `initramfs-virt vmlinuz-virt vm.qcow2` al servidor a `/var/lib/libvirt/images`
|
||||
|
||||
## definir vm
|
||||
|
||||
```sh
|
||||
virsh shutdown woodpecker-in-a-vm
|
||||
virsh undefine woodpecker-in-a-vm
|
||||
virt-install --name woodpecker-in-a-vm \
|
||||
--osinfo alpinelinux3.16 \
|
||||
--memory 4096 --vcpus 4 \
|
||||
--import \
|
||||
--disk path=/var/lib/libvirt/images/vm.qcow2,format=qcow2 \
|
||||
--boot kernel=/var/lib/libvirt/images/vmlinuz-virt,initrd=/var/lib/libvirt/images/initramfs-virt,kernel_args="console=/dev/ttyS0 quiet root=/dev/vda rw modules=ext4" \
|
||||
--noautoconsole
|
||||
```
|
||||
|
|
Loading…
Reference in a new issue