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