Merge branch 'next/minor' of github.com:Start9Labs/start-os into next/major

This commit is contained in:
Matt Hill
2025-02-08 19:19:35 -07:00
parent 95cad7bdd9
commit 95722802dc
206 changed files with 11364 additions and 4104 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -216,12 +216,6 @@ export function makeEffects(context: EffectContext): Effects {
}) as ReturnType<T.Effects["getServiceInterface"]>
},
getPrimaryUrl(...[options]: Parameters<T.Effects["getPrimaryUrl"]>) {
return rpcRound("get-primary-url", {
...options,
callback: context.callbacks?.addCallback(options.callback) || null,
}) as ReturnType<T.Effects["getPrimaryUrl"]>
},
getServicePortForward(
...[options]: Parameters<T.Effects["getServicePortForward"]>
) {

View File

@@ -212,16 +212,22 @@ export class RpcListener {
s.on("data", (a) =>
Promise.resolve(a)
.then((b) => b.toString())
.then(logData("dataIn"))
.then(jsonParse)
.then(captureId)
.then((x) => this.dealWithInput(x))
.catch(mapError)
.then(logData("response"))
.then(writeDataToSocket)
.catch((e) => {
console.error(`Major error in socket handling: ${e}`)
console.debug(`Data in: ${a.toString()}`)
.then((buf) => {
for (let s of buf.split("\n")) {
if (s)
Promise.resolve(s)
.then(logData("dataIn"))
.then(jsonParse)
.then(captureId)
.then((x) => this.dealWithInput(x))
.catch(mapError)
.then(logData("response"))
.then(writeDataToSocket)
.catch((e) => {
console.error(`Major error in socket handling: ${e}`)
console.debug(`Data in: ${a.toString()}`)
})
}
}),
)
})
@@ -390,7 +396,7 @@ export class RpcListener {
.defaultToLazy(() => {
console.warn(
`Coudln't parse the following input ${JSON.stringify(input)}`,
`Couldn't parse the following input ${JSON.stringify(input)}`,
)
return {
jsonrpc,

View File

@@ -43,7 +43,7 @@ export class DockerProcedureContainer {
) {
const subcontainer = await SubContainer.of(
effects,
{ id: data.image },
{ imageId: data.image },
name,
)

View File

@@ -113,7 +113,6 @@ export class MainLoop {
}))
.find((conf) => conf.internal == internalPort)
await effects.bind({
kind: "multi",
id: interfaceId,
internalPort,
preferredExternalPort: torConf?.external || internalPort,

View File

@@ -51,6 +51,7 @@ function todo(): never {
const MANIFEST_LOCATION = "/usr/lib/startos/package/embassyManifest.json"
export const EMBASSY_JS_LOCATION = "/usr/lib/startos/package/embassy.js"
const EMBASSY_POINTER_PATH_PREFIX = "/embassyConfig" as utils.StorePath
const EMBASSY_DEPENDS_ON_PATH_PREFIX = "/embassyDependsOn" as utils.StorePath
const matchResult = object({
result: any,
@@ -314,7 +315,7 @@ export class SystemForEmbassy implements System {
)
.catch(() => []),
)
await this.setDependencies(effects, oldDeps)
await this.setDependencies(effects, oldDeps, false)
}
async exit(): Promise<void> {
@@ -401,6 +402,7 @@ export class SystemForEmbassy implements System {
return [
port,
{
protocol: null,
secure: null,
preferredExternalPort: Number.parseInt(
torPort || lanPort || String(port),
@@ -425,7 +427,6 @@ export class SystemForEmbassy implements System {
name: interfaceValue.name,
id: `${id}-${internal}`,
description: interfaceValue.description,
hasPrimary: false,
type:
interfaceValue.ui &&
(origin.scheme === "http" || origin.sslScheme === "https")
@@ -664,7 +665,7 @@ export class SystemForEmbassy implements System {
),
)
const dependsOn = answer["depends-on"] ?? answer.dependsOn ?? {}
await this.setDependencies(effects, dependsOn)
await this.setDependencies(effects, dependsOn, true)
return
} else if (setConfigValue.type === "script") {
const moduleCode = await this.moduleCode
@@ -687,48 +688,47 @@ export class SystemForEmbassy implements System {
}),
)
const dependsOn = answer["depends-on"] ?? answer.dependsOn ?? {}
await this.setDependencies(effects, dependsOn)
await this.setDependencies(effects, dependsOn, true)
return
}
}
private async setDependencies(
effects: Effects,
rawDepends: { [x: string]: readonly string[] },
configuring: boolean,
) {
const dependsOn: Record<string, readonly string[] | null> = {
const storedDependsOn = (await effects.store.get({
packageId: this.manifest.id,
path: EMBASSY_DEPENDS_ON_PATH_PREFIX,
})) as Record<string, readonly string[]>
const requiredDeps = {
...Object.fromEntries(
Object.entries(this.manifest.dependencies || {})?.map((x) => [
x[0],
null,
]) || [],
Object.entries(this.manifest.dependencies || {})
?.filter((x) => x[1].requirement.type === "required")
.map((x) => [x[0], []]) || [],
),
...rawDepends,
}
const dependsOn: Record<string, readonly string[]> = configuring
? {
...requiredDeps,
...rawDepends,
}
: storedDependsOn
? storedDependsOn
: requiredDeps
await effects.store.set({
path: EMBASSY_DEPENDS_ON_PATH_PREFIX,
value: dependsOn,
})
await effects.setDependencies({
dependencies: Object.entries(dependsOn).flatMap(
([key, value]): T.Dependencies => {
const dependency = this.manifest.dependencies?.[key]
if (!dependency) return []
if (value == null) {
const versionRange = dependency.version
if (dependency.requirement.type === "required") {
return [
{
id: key,
versionRange,
kind: "running",
healthChecks: [],
},
]
}
return [
{
kind: "exists",
id: key,
versionRange,
},
]
}
const versionRange = dependency.version
const kind = "running"
return [

View File

@@ -109,7 +109,7 @@ export const polyfillEffects = (
return startSdk
.runCommand(
effects,
{ id: manifest.main.image },
{ imageId: manifest.main.image },
commands,
{},
commands.join(" "),
@@ -165,7 +165,7 @@ export const polyfillEffects = (
await startSdk
.runCommand(
effects,
{ id: manifest.main.image },
{ imageId: manifest.main.image },
commands,
{
mounts: [
@@ -207,7 +207,7 @@ export const polyfillEffects = (
await startSdk
.runCommand(
effects,
{ id: manifest.main.image },
{ imageId: manifest.main.image },
commands,
{
mounts: [

View File

@@ -74,8 +74,8 @@ export class SystemForStartOs implements System {
async exit(): Promise<void> {}
async start(effects: Effects): Promise<void> {
if (this.runningMain) return
effects.constRetry = utils.once(() => effects.restart())
if (this.runningMain) await this.stop()
let mainOnTerm: () => Promise<void> | undefined
const started = async (onTerm: () => Promise<void>) => {
await effects.setMainStatus({ status: "running" })
@@ -98,8 +98,11 @@ export class SystemForStartOs implements System {
async stop(): Promise<void> {
if (this.runningMain) {
await this.runningMain.stop()
this.runningMain = undefined
try {
await this.runningMain.stop()
} finally {
this.runningMain = undefined
}
}
}
}

View File

@@ -11,7 +11,7 @@ new RpcListener(getDependencies)
/**
So, this is going to be sent into a running comtainer along with any of the other node modules that are going to be needed and used.
So, this is going to be sent into a running container along with any of the other node modules that are going to be needed and used.
Once the container is started, we will go into a loading/ await state.
This is the init system, and it will always be running, and it will be waiting for a command to be sent to it.
@@ -38,5 +38,5 @@ There are
/**
TODO:
Should I seperate those adapter in/out?
Should I separate those adapter in/out?
*/

View File

@@ -18,6 +18,13 @@ sudo mount -t overlay -olowerdir=tmp/lower,upperdir=tmp/upper,workdir=tmp/work o
QEMU=
if [ "$ARCH" != "$(uname -m)" ]; then
QEMU=/usr/bin/qemu-${ARCH}-static
if ! which qemu-$ARCH-static > /dev/null; then
>&2 echo qemu-user-static is required for cross-platform builds
sudo umount tmp/combined
sudo umount tmp/lower
sudo rm -rf tmp
exit 1
fi
sudo cp $(which qemu-$ARCH-static) tmp/combined${QEMU}
fi