hacky
This commit is contained in:
commit
7bbf52a757
6 changed files with 113 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
1
.npmrc
Normal file
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@nulo:registry=https://gitea.nulo.in/api/packages/nulo/npm/
|
67
index.js
Normal file
67
index.js
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import { execFile as _execFile } from "node:child_process";
|
||||||
|
import { readFile, stat, symlink, writeFile } from "node:fs/promises";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { promisify } from "node:util";
|
||||||
|
const execFile = promisify(_execFile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} Alpine
|
||||||
|
* @prop {(packages: string[]) => Promise<void>} install
|
||||||
|
* @prop {(runlevel: string, service: string) => Promise<void>} rcUpdate
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an Alpine 3.18 rootfs at `root`
|
||||||
|
* @param {string} root
|
||||||
|
* @returns {Promise<Alpine>}
|
||||||
|
*/
|
||||||
|
export async function init(root) {
|
||||||
|
await runInContainer(
|
||||||
|
root,
|
||||||
|
`
|
||||||
|
mkdir -p /rootfs/etc/apk
|
||||||
|
cp -r /etc/apk/keys /rootfs/etc/apk/
|
||||||
|
echo https://dl-cdn.alpinelinux.org/alpine/v3.18/main >> /rootfs/etc/apk/repositories
|
||||||
|
echo https://dl-cdn.alpinelinux.org/alpine/v3.18/community >> /rootfs/etc/apk/repositories
|
||||||
|
apk add --initdb --root /rootfs alpine-base
|
||||||
|
`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
async install(packages) {
|
||||||
|
const worldPath = join(root, "/etc/apk/world");
|
||||||
|
const oldWorld = (await readFile(worldPath, "utf-8")).split("\n");
|
||||||
|
const newWorld = oldWorld.concat(packages);
|
||||||
|
await writeFile(worldPath, newWorld.join("\n"));
|
||||||
|
|
||||||
|
await runInContainer(root, `apk fix --root /rootfs`);
|
||||||
|
},
|
||||||
|
async rcUpdate(runlevel, service) {
|
||||||
|
const servicePath = `/etc/init.d/${service}`;
|
||||||
|
try {
|
||||||
|
await stat(servicePath);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Can't stat service ${service}: ${error}`);
|
||||||
|
}
|
||||||
|
await symlink(servicePath, join(root, `/etc/runlevels/`, runlevel));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run script inside an Alpine 3.18 container with `root` mounted in /rootfs
|
||||||
|
* @param {string} root
|
||||||
|
* @param {string} script
|
||||||
|
*/
|
||||||
|
async function runInContainer(root, script) {
|
||||||
|
await execFile("podman", [
|
||||||
|
"run",
|
||||||
|
"-it",
|
||||||
|
"--rm",
|
||||||
|
"-v",
|
||||||
|
`${root}:/rootfs:Z`,
|
||||||
|
"docker.io/alpine:3.18",
|
||||||
|
"sh",
|
||||||
|
"-ec",
|
||||||
|
script,
|
||||||
|
]);
|
||||||
|
}
|
17
package.json
Normal file
17
package.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "@nulo/apkit",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@tsconfig/node16": "^1.0.4",
|
||||||
|
"@types/node": "^20.2.5"
|
||||||
|
}
|
||||||
|
}
|
19
pnpm-lock.yaml
Normal file
19
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
|
devDependencies:
|
||||||
|
'@tsconfig/node16':
|
||||||
|
specifier: ^1.0.4
|
||||||
|
version: 1.0.4
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.2.5
|
||||||
|
version: 20.2.5
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/@tsconfig/node16@1.0.4:
|
||||||
|
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/node@20.2.5:
|
||||||
|
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
|
||||||
|
dev: true
|
8
tsconfig.json
Normal file
8
tsconfig.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "@tsconfig/node16/tsconfig.json",
|
||||||
|
"exclude": ["build.js/", "build/"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue