diff --git a/container-runtime/package-lock.json b/container-runtime/package-lock.json index 2abce19f8..acb6ac38d 100644 --- a/container-runtime/package-lock.json +++ b/container-runtime/package-lock.json @@ -37,7 +37,7 @@ }, "../sdk/dist": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.24", + "version": "0.4.0-beta.25", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/container-runtime/src/Adapters/RpcListener.ts b/container-runtime/src/Adapters/RpcListener.ts index 77edf0d3a..8033478da 100644 --- a/container-runtime/src/Adapters/RpcListener.ts +++ b/container-runtime/src/Adapters/RpcListener.ts @@ -324,6 +324,7 @@ export class RpcListener { }), ) const callbacks = this.callbacks.child("init") + console.error("Initializing...") await system.init( makeEffects({ procedureId: params.id, @@ -331,6 +332,7 @@ export class RpcListener { }), params.kind, ) + console.error("Initialization complete.") this._system = system } })().then((result) => ({ result })), diff --git a/core/Cargo.lock b/core/Cargo.lock index 1a562388e..14cf74bc4 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -6023,7 +6023,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "start-os" -version = "0.4.0-alpha.4" +version = "0.4.0-alpha.5" dependencies = [ "aes 0.7.5", "async-acme", diff --git a/core/startos/Cargo.toml b/core/startos/Cargo.toml index 8a32ae561..aa6d8fff1 100644 --- a/core/startos/Cargo.toml +++ b/core/startos/Cargo.toml @@ -14,7 +14,7 @@ keywords = [ name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" -version = "0.4.0-alpha.4" # VERSION_BUMP +version = "0.4.0-alpha.5" # VERSION_BUMP license = "MIT" [lib] diff --git a/core/startos/src/control.rs b/core/startos/src/control.rs index e831e07d6..ce0478774 100644 --- a/core/startos/src/control.rs +++ b/core/startos/src/control.rs @@ -31,13 +31,12 @@ pub async fn start(ctx: RpcContext, ControlParams { id }: ControlParams) -> Resu } pub async fn stop(ctx: RpcContext, ControlParams { id }: ControlParams) -> Result<(), Error> { - // TODO: why did this return last_status before? ctx.services .get(&id) .await .as_ref() .ok_or_else(|| Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest))? - .stop(Guid::new()) + .stop(Guid::new(), true) .await?; Ok(()) diff --git a/core/startos/src/registry/package/mod.rs b/core/startos/src/registry/package/mod.rs index fa395a479..4419b4d19 100644 --- a/core/startos/src/registry/package/mod.rs +++ b/core/startos/src/registry/package/mod.rs @@ -35,7 +35,7 @@ pub fn package_api() -> ParentHandler { "remove", from_fn_async(add::remove_package) .no_display() - .with_about("Add package to registry index") + .with_about("Remove package from registry index") .with_call_remote::(), ) .subcommand( diff --git a/core/startos/src/service/control.rs b/core/startos/src/service/control.rs index 8b920bb32..9190a1417 100644 --- a/core/startos/src/service/control.rs +++ b/core/startos/src/service/control.rs @@ -1,3 +1,5 @@ +use futures::future::OptionFuture; + use crate::prelude::*; use crate::rpc_continuations::Guid; use crate::service::action::RunAction; @@ -26,13 +28,20 @@ impl Service { } } -struct Stop; +struct Stop { + wait: bool, +} impl Handler for ServiceActor { type Response = (); fn conflicts_with(_: &Stop) -> ConflictBuilder { ConflictBuilder::everything().except::() } - async fn handle(&mut self, _: Guid, _: Stop, _: &BackgroundJobQueue) -> Self::Response { + async fn handle( + &mut self, + _: Guid, + Stop { wait }: Stop, + _: &BackgroundJobQueue, + ) -> Self::Response { let mut transition_state = None; self.0.persistent_container.state.send_modify(|x| { x.desired_state = StartStop::Stop; @@ -40,14 +49,19 @@ impl Handler for ServiceActor { transition_state = std::mem::take(&mut x.transition_state); } }); + let notif = if wait { + Some(self.0.synchronized.notified()) + } else { + None + }; if let Some(restart) = transition_state { restart.abort().await; } - self.0.synchronized.notified().await + OptionFuture::from(notif).await; } } impl Service { - pub async fn stop(&self, id: Guid) -> Result<(), Error> { - self.actor.send(id, Stop).await + pub async fn stop(&self, id: Guid, wait: bool) -> Result<(), Error> { + self.actor.send(id, Stop { wait }).await } } diff --git a/core/startos/src/service/effects/action.rs b/core/startos/src/service/effects/action.rs index cd6157ad7..4c5c554e8 100644 --- a/core/startos/src/service/effects/action.rs +++ b/core/startos/src/service/effects/action.rs @@ -262,7 +262,7 @@ async fn create_task( None => true, }; if active && task.severity == TaskSeverity::Critical { - context.stop(procedure_id).await?; + context.stop(procedure_id, false).await?; } context .seed diff --git a/core/startos/src/service/effects/control.rs b/core/startos/src/service/effects/control.rs index eeaec0187..9321d73cf 100644 --- a/core/startos/src/service/effects/control.rs +++ b/core/startos/src/service/effects/control.rs @@ -35,7 +35,7 @@ pub async fn shutdown( ProcedureId { procedure_id }: ProcedureId, ) -> Result<(), Error> { let context = context.deref()?; - context.stop(procedure_id).await?; + context.stop(procedure_id, false).await?; Ok(()) } diff --git a/core/startos/src/version/mod.rs b/core/startos/src/version/mod.rs index 6919edb7d..1817837c1 100644 --- a/core/startos/src/version/mod.rs +++ b/core/startos/src/version/mod.rs @@ -44,8 +44,9 @@ mod v0_4_0_alpha_1; mod v0_4_0_alpha_2; mod v0_4_0_alpha_3; mod v0_4_0_alpha_4; +mod v0_4_0_alpha_5; -pub type Current = v0_4_0_alpha_4::Version; // VERSION_BUMP +pub type Current = v0_4_0_alpha_5::Version; // VERSION_BUMP impl Current { #[instrument(skip(self, db))] @@ -153,7 +154,8 @@ enum Version { V0_4_0_alpha_1(Wrapper), V0_4_0_alpha_2(Wrapper), V0_4_0_alpha_3(Wrapper), - V0_4_0_alpha_4(Wrapper), // VERSION_BUMP + V0_4_0_alpha_4(Wrapper), + V0_4_0_alpha_5(Wrapper), // VERSION_BUMP Other(exver::Version), } @@ -200,7 +202,8 @@ impl Version { Self::V0_4_0_alpha_1(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_2(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_3(v) => DynVersion(Box::new(v.0)), - Self::V0_4_0_alpha_4(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP + Self::V0_4_0_alpha_4(v) => DynVersion(Box::new(v.0)), + Self::V0_4_0_alpha_5(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP Self::Other(v) => { return Err(Error::new( eyre!("unknown version {v}"), @@ -239,7 +242,8 @@ impl Version { Version::V0_4_0_alpha_1(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_2(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_3(Wrapper(x)) => x.semver(), - Version::V0_4_0_alpha_4(Wrapper(x)) => x.semver(), // VERSION_BUMP + Version::V0_4_0_alpha_4(Wrapper(x)) => x.semver(), + Version::V0_4_0_alpha_5(Wrapper(x)) => x.semver(), // VERSION_BUMP Version::Other(x) => x.clone(), } } diff --git a/core/startos/src/version/v0_4_0_alpha_5.rs b/core/startos/src/version/v0_4_0_alpha_5.rs new file mode 100644 index 000000000..1a3c75211 --- /dev/null +++ b/core/startos/src/version/v0_4_0_alpha_5.rs @@ -0,0 +1,38 @@ +use exver::{PreReleaseSegment, VersionRange}; + +use super::v0_3_5::V0_3_0_COMPAT; +use super::{v0_4_0_alpha_4, VersionT}; +use crate::context::RpcContext; +use crate::prelude::*; + +lazy_static::lazy_static! { + static ref V0_4_0_alpha_5: exver::Version = exver::Version::new( + [0, 4, 0], + [PreReleaseSegment::String("alpha".into()), 5.into()] + ); +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct Version; + +impl VersionT for Version { + type Previous = v0_4_0_alpha_4::Version; + type PreUpRes = (); + + async fn pre_up(self) -> Result { + Ok(()) + } + fn semver(self) -> exver::Version { + V0_4_0_alpha_5.clone() + } + fn compat(self) -> &'static VersionRange { + &V0_3_0_COMPAT + } + #[instrument] + fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> { + Ok(()) + } + fn down(self, _db: &mut Value) -> Result<(), Error> { + Ok(()) + } +} diff --git a/sdk/base/lib/inits/setupInit.ts b/sdk/base/lib/inits/setupInit.ts index 80eae8571..a8a33946e 100644 --- a/sdk/base/lib/inits/setupInit.ts +++ b/sdk/base/lib/inits/setupInit.ts @@ -51,41 +51,3 @@ export function setupOnInit(onInit: InitScriptOrFn): InitScript { }, } } - -export function setupOnInstall( - onInstall: InitScriptOrFn<"install">, -): InitScript { - return { - init: async (effects, kind) => { - if (kind === "install") { - if ("init" in onInstall) await onInstall.init(effects, kind) - else await onInstall(effects, kind) - } - }, - } -} - -export function setupOnUpdate(onUpdate: InitScriptOrFn<"update">): InitScript { - return { - init: async (effects, kind) => { - if (kind === "update") { - if ("init" in onUpdate) await onUpdate.init(effects, kind) - else await onUpdate(effects, kind) - } - }, - } -} - -export function setupOnInstallOrUpdate( - onInstallOrUpdate: InitScriptOrFn<"install" | "update">, -): InitScript { - return { - init: async (effects, kind) => { - if (kind === "install" || kind === "update") { - if ("init" in onInstallOrUpdate) - await onInstallOrUpdate.init(effects, kind) - else await onInstallOrUpdate(effects, kind) - } - }, - } -} diff --git a/sdk/base/lib/inits/setupUninit.ts b/sdk/base/lib/inits/setupUninit.ts index 8fc907de7..263a64caf 100644 --- a/sdk/base/lib/inits/setupUninit.ts +++ b/sdk/base/lib/inits/setupUninit.ts @@ -3,18 +3,34 @@ import * as T from "../../../base/lib/types" export type UninitFn = ( effects: T.Effects, + /** + * @description the target version to prepare for + * + * on update: the canMigrateFrom of the new package + * on uninstall: null + * on shutdown: the current version + */ target: VersionRange | ExtendedVersion | null, ) => Promise export interface UninitScript { uninit( effects: T.Effects, + /** + * @description the target version to prepare for + * + * on update: the canMigrateFrom of the new package + * on uninstall: null + * on shutdown: the current version + */ target: VersionRange | ExtendedVersion | null, ): Promise } +export type UninitScriptOrFn = UninitScript | UninitFn + export function setupUninit( - ...uninits: (UninitScript | UninitFn)[] + ...uninits: UninitScriptOrFn[] ): T.ExpectedExports.uninit { return async (opts) => { for (const uninit of uninits) { @@ -23,3 +39,13 @@ export function setupUninit( } } } + +export function setupOnUninit(onUninit: UninitScriptOrFn): UninitScript { + return "uninit" in onUninit + ? onUninit + : { + uninit: async (effects, target) => { + await onUninit(effects, target) + }, + } +} diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 9f303fa87..9bf8fd36a 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -64,13 +64,11 @@ import * as fs from "node:fs/promises" import { setupInit, setupUninit, - setupOnInstall, - setupOnUpdate, - setupOnInstallOrUpdate, setupOnInit, + setupOnUninit, } from "../../base/lib/inits" -export const OSVersion = testTypeVersion("0.4.0-alpha.4") +export const OSVersion = testTypeVersion("0.4.0-alpha.5") // prettier-ignore type AnyNeverCond = @@ -506,21 +504,13 @@ export class StartSdk { */ setupDependencies: setupDependencies, /** - * @description Use this function to create an InitScript that runs every time the service initializes + * @description Use this function to create an InitScript that runs every time the service initializes (install, update, restore, rebuild, and server bootup) */ setupOnInit, /** - * @description Use this function to create an InitScript that runs only when the service is freshly installed + * @description Use this function to create an UninitScript that runs every time the service uninitializes (update, uninstall, and server shutdown) */ - setupOnInstall, - /** - * @description Use this function to create an InitScript that runs only when the service is updated - */ - setupOnUpdate, - /** - * @description Use this function to create an InitScript that runs only when the service is installed or updated - */ - setupOnInstallOrUpdate, + setupOnUninit, /** * @description Use this function to setup what happens when the service initializes. * diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index cada2299d..2a5836ad5 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.24", + "version": "0.4.0-beta.25", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.24", + "version": "0.4.0-beta.25", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/sdk/package/package.json b/sdk/package/package.json index 36bfc09cb..0ba452849 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.24", + "version": "0.4.0-beta.25", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", diff --git a/web/package-lock.json b/web/package-lock.json index db8c72d1f..6fd93e5cd 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "startos-ui", - "version": "0.4.0-alpha.4", + "version": "0.4.0-alpha.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "startos-ui", - "version": "0.4.0-alpha.4", + "version": "0.4.0-alpha.5", "license": "MIT", "dependencies": { "@angular/animations": "^17.3.1", diff --git a/web/package.json b/web/package.json index ee17e1f8f..7e37e3d73 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "startos-ui", - "version": "0.4.0-alpha.4", + "version": "0.4.0-alpha.5", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "license": "MIT", diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index 0bfb4fa87..1cb9dcda9 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -101,16 +101,16 @@ export namespace Mock { }, img: {}, }, - '0.4.0-alpha.4': { - headline: 'v0.4.0-alpha.4', + '0.4.0-alpha.5': { + headline: 'v0.4.0-alpha.5', releaseNotes: '', - sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.4:0', + sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.5:0', authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'], iso: {}, squashfs: { aarch64: { publishedAt: '2025-04-21T20:58:48.140749883Z', - url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_aarch64.squashfs', + url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_aarch64.squashfs', commitment: { hash: '4elBFVkd/r8hNadKmKtLIs42CoPltMvKe2z3LRqkphk=', size: 1343500288, @@ -122,7 +122,7 @@ export namespace Mock { }, 'aarch64-nonfree': { publishedAt: '2025-04-21T21:07:00.249285116Z', - url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_aarch64-nonfree.squashfs', + url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_aarch64-nonfree.squashfs', commitment: { hash: 'MrCEi4jxbmPS7zAiGk/JSKlMsiuKqQy6RbYOxlGHOIQ=', size: 1653075968, @@ -134,7 +134,7 @@ export namespace Mock { }, raspberrypi: { publishedAt: '2025-04-21T21:16:12.933319237Z', - url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_raspberrypi.squashfs', + url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_raspberrypi.squashfs', commitment: { hash: '/XTVQRCqY3RK544PgitlKu7UplXjkmzWoXUh2E4HCw0=', size: 1490731008, @@ -146,7 +146,7 @@ export namespace Mock { }, x86_64: { publishedAt: '2025-04-21T21:14:20.246908903Z', - url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_x86_64.squashfs', + url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_x86_64.squashfs', commitment: { hash: '/6romKTVQGSaOU7FqSZdw0kFyd7P+NBSYNwM3q7Fe44=', size: 1411657728, @@ -158,7 +158,7 @@ export namespace Mock { }, 'x86_64-nonfree': { publishedAt: '2025-04-21T21:15:17.955265284Z', - url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_x86_64-nonfree.squashfs', + url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_x86_64-nonfree.squashfs', commitment: { hash: 'HCRq9sr/0t85pMdrEgNBeM4x11zVKHszGnD1GDyZbSE=', size: 1731035136,