Feature/registry improvements (#2772)

* add build cli script for cross-building cli

* sdk alpha.13

* registry improvements
This commit is contained in:
Aiden McClelland
2024-11-05 20:38:52 -07:00
committed by GitHub
parent 020268fe67
commit b79c029f21
19 changed files with 636 additions and 89 deletions

View File

@@ -58,7 +58,7 @@ touch:
metadata: $(VERSION_FILE) $(PLATFORM_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE)
sudo:
sudo -v
sudo true
clean:
rm -f system-images/**/*.tar

88
core/Cargo.lock generated
View File

@@ -128,9 +128,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
@@ -162,9 +162,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.91"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
[[package]]
name = "arrayref"
@@ -237,7 +237,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -248,7 +248,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -538,7 +538,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.85",
"syn 2.0.86",
"which",
]
@@ -847,7 +847,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1255,7 +1255,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1279,7 +1279,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1290,7 +1290,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1321,7 +1321,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1344,7 +1344,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1367,7 +1367,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1589,7 +1589,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -1868,7 +1868,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -2849,9 +2849,9 @@ dependencies = [
[[package]]
name = "libm"
version = "0.2.10"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00419de735aac21d53b0de5ce2c03bd3627277cf471300f27ebc89f7d828047"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "libredox"
@@ -3302,7 +3302,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3368,7 +3368,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3575,7 +3575,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3631,7 +3631,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3707,7 +3707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [
"proc-macro2",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3805,7 +3805,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -3828,7 +3828,7 @@ dependencies = [
"itertools 0.12.1",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -4169,7 +4169,7 @@ dependencies = [
[[package]]
name = "rpc-toolkit"
version = "0.2.3"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=refactor%2Fno-dyn-ctx#39a872a1294c7d864faca63f072092ce300ffbe5"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=refactor%2Fno-dyn-ctx#021379f21c4d11c5a62c07460f4531ce9b555155"
dependencies = [
"async-stream",
"async-trait",
@@ -4496,7 +4496,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -4570,7 +4570,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -5003,7 +5003,7 @@ dependencies = [
"quote",
"regex-syntax 0.6.29",
"strsim 0.10.0",
"syn 2.0.85",
"syn 2.0.86",
"unicode-width",
]
@@ -5245,9 +5245,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.85"
version = "2.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
dependencies = [
"proc-macro2",
"quote",
@@ -5363,22 +5363,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.65"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5"
checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.65"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602"
checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -5494,7 +5494,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -5768,7 +5768,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -5920,7 +5920,7 @@ dependencies = [
"Inflector",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
"termcolor",
]
@@ -5990,7 +5990,7 @@ checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -6215,7 +6215,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
"wasm-bindgen-shared",
]
@@ -6249,7 +6249,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -6633,7 +6633,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]
@@ -6653,7 +6653,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
"syn 2.0.86",
]
[[package]]

50
core/build-cli.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
set -ea
shopt -s expand_aliases
if [ -z "$ARCH" ]; then
ARCH=$(uname -m)
fi
if [ "$ARCH" = "arm64" ]; then
ARCH="aarch64"
fi
if [ -z "$KERNEL_NAME" ]; then
KERNEL_NAME=$(uname -s)
fi
if [ -z "$TARGET" ]; then
if [ "$KERNEL_NAME" = "Linux" ]; then
TARGET="$ARCH-unknown-linux-musl"
elif [ "$KERNEL_NAME" = "Darwin" ]; then
TARGET="$ARCH-apple-darwin"
else
>&2 echo "unknown kernel $KERNEL_NAME"
exit 1
fi
fi
USE_TTY=
if tty -s; then
USE_TTY="-it"
fi
cd ..
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
RUSTFLAGS=""
if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable"
fi
alias 'rust-zig-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/cargo-zigbuild'
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder sh -c "cd core && cargo zigbuild --release --no-default-features --features cli,daemon,$FEATURES --locked --bin start-cli --target=$TARGET"
if [ "$(ls -nd core/target/$TARGET/release/start-cli | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "cd core && chown -R $UID:$UID target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -0,0 +1,13 @@
[Unit]
Description=StartOS Registry
[Service]
Type=simple
Environment=RUST_LOG=startos=debug,patch_db=warn
ExecStart=/usr/local/bin/registry
Restart=always
RestartSec=3
ManagedOOMPreference=avoid
[Install]
WantedBy=multi-user.target

View File

@@ -28,6 +28,16 @@ fn select_executable(name: &str) -> Option<fn(VecDeque<OsString>)> {
"embassy-sdk" => Some(|_| deprecated::renamed("embassy-sdk", "start-sdk")),
"embassyd" => Some(|_| deprecated::renamed("embassyd", "startd")),
"embassy-init" => Some(|_| deprecated::removed("embassy-init")),
"contents" => Some(|_| {
#[cfg(feature = "cli")]
println!("start-cli");
#[cfg(feature = "container-runtime")]
println!("start-cli (container)");
#[cfg(feature = "daemon")]
println!("startd");
#[cfg(feature = "registry")]
println!("registry");
}),
_ => None,
}
}

View File

@@ -115,8 +115,7 @@ pub fn main_api<C: Context>() -> ParentHandler<C> {
let api = ParentHandler::new()
.subcommand(
"git-info",
from_fn(|_: RpcContext| version::git_info())
.with_about("Display the githash of StartOS CLI"),
from_fn(|_: C| version::git_info()).with_about("Display the githash of StartOS CLI"),
)
.subcommand(
"echo",

View File

@@ -360,11 +360,7 @@ pub fn logs<
source: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> ParentHandler<C, LogsParams<Extra>> {
ParentHandler::new()
.root_handler(
logs_nofollow::<C, Extra>(source.clone())
.with_inherited(|params, _| params)
.no_cli(),
)
.root_handler(logs_nofollow::<C, Extra>(source.clone()).no_cli())
.subcommand(
"follow",
logs_follow::<C, Extra>(source)
@@ -436,7 +432,7 @@ where
fn logs_nofollow<C, Extra>(
f: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> impl HandlerFor<C, Params = Empty, InheritedParams = LogsParams<Extra>, Ok = LogResponse, Err = Error>
) -> impl HandlerFor<C, Params = LogsParams<Extra>, InheritedParams = Empty, Ok = LogResponse, Err = Error>
where
C: Context,
Extra: FromArgMatches + Args + Send + Sync + 'static,
@@ -444,7 +440,7 @@ where
from_fn_async(
move |HandlerArgs {
context,
inherited_params:
params:
LogsParams {
extra,
limit,
@@ -453,7 +449,7 @@ where
before,
},
..
}: HandlerArgs<C, Empty, LogsParams<Extra>>| {
}: HandlerArgs<C, LogsParams<Extra>>| {
let f = f.clone();
async move {
fetch_logs(

View File

@@ -60,6 +60,13 @@ fn signers_api<C: Context>() -> ParentHandler<C> {
"add",
from_fn_async(cli_add_signer).with_about("Add signer"),
)
.subcommand(
"edit",
from_fn_async(edit_signer)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_call_remote::<CliContext>(),
)
}
impl Model<BTreeMap<Guid, SignerInfo>> {
@@ -143,6 +150,64 @@ pub async fn add_signer(ctx: RegistryContext, signer: SignerInfo) -> Result<Guid
.await
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct EditSignerParams {
pub id: Guid,
#[arg(short = 'n', long)]
pub set_name: Option<String>,
#[arg(short = 'c', long)]
pub add_contact: Vec<ContactInfo>,
#[arg(short = 'k', long)]
pub add_key: Vec<AnyVerifyingKey>,
#[arg(short = 'C', long)]
pub remove_contact: Vec<ContactInfo>,
#[arg(short = 'K', long)]
pub remove_key: Vec<AnyVerifyingKey>,
}
pub async fn edit_signer(
ctx: RegistryContext,
EditSignerParams {
id,
set_name,
add_contact,
add_key,
remove_contact,
remove_key,
}: EditSignerParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| {
db.as_index_mut()
.as_signers_mut()
.as_idx_mut(&id)
.or_not_found(&id)?
.mutate(|s| {
if let Some(name) = set_name {
s.name = name;
}
s.contact.extend(add_contact);
for rm in remove_contact {
let Some((idx, _)) = s.contact.iter().enumerate().find(|(_, c)| *c == &rm)
else {
continue;
};
s.contact.remove(idx);
}
s.keys.extend(add_key);
for rm in remove_key {
s.keys.remove(&rm);
}
Ok(())
})
})
.await
}
#[derive(Debug, Deserialize, Serialize, Parser)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]

View File

@@ -0,0 +1,126 @@
use std::collections::BTreeMap;
use std::path::PathBuf;
use clap::Parser;
use imbl_value::InternedString;
use itertools::Itertools;
use models::DataUrl;
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::context::CliContext;
use crate::prelude::*;
use crate::registry::context::RegistryContext;
use crate::registry::package::index::Category;
use crate::util::serde::{HandlerExtSerde, WithIoFormat};
pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
ParentHandler::<C, WithIoFormat<Empty>>::new()
.root_handler(
from_fn_async(get_info)
.with_display_serializable()
.with_about("Display registry name, icon, and package categories")
.with_call_remote::<CliContext>(),
)
.subcommand(
"set-name",
from_fn_async(set_name)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("Set the name for the registry")
.with_call_remote::<CliContext>(),
)
.subcommand(
"set-icon",
from_fn_async(set_icon)
.with_metadata("admin", Value::Bool(true))
.no_cli(),
)
.subcommand(
"set-icon",
from_fn_async(cli_set_icon)
.no_display()
.with_about("Set the icon for the registry"),
)
}
#[derive(Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryInfo {
pub name: Option<String>,
pub icon: Option<DataUrl<'static>>,
#[ts(as = "BTreeMap::<String, Category>")]
pub categories: BTreeMap<InternedString, Category>,
}
pub async fn get_info(ctx: RegistryContext) -> Result<RegistryInfo, Error> {
let peek = ctx.db.peek().await.into_index();
Ok(RegistryInfo {
name: peek.as_name().de()?,
icon: peek.as_icon().de()?,
categories: peek.as_package().as_categories().de()?,
})
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetNameParams {
pub name: String,
}
pub async fn set_name(
ctx: RegistryContext,
SetNameParams { name }: SetNameParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| db.as_index_mut().as_name_mut().ser(&Some(name)))
.await
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetIconParams {
pub icon: DataUrl<'static>,
}
pub async fn set_icon(
ctx: RegistryContext,
SetIconParams { icon }: SetIconParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| db.as_index_mut().as_icon_mut().ser(&Some(icon)))
.await
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CliSetIconParams {
pub icon: PathBuf,
}
pub async fn cli_set_icon(
HandlerArgs {
context: ctx,
parent_method,
method,
params: CliSetIconParams { icon },
..
}: HandlerArgs<CliContext, CliSetIconParams>,
) -> Result<(), Error> {
let data_url = DataUrl::from_path(icon).await?;
ctx.call_remote::<RegistryContext>(
&parent_method.into_iter().chain(method).join("."),
imbl_value::json!({
"icon": data_url,
}),
)
.await?;
Ok(())
}

View File

@@ -28,6 +28,7 @@ pub mod auth;
pub mod context;
pub mod db;
pub mod device_info;
pub mod info;
pub mod os;
pub mod package;
pub mod signer;
@@ -57,25 +58,6 @@ pub async fn get_full_index(ctx: RegistryContext) -> Result<FullIndex, Error> {
ctx.db.peek().await.into_index().de()
}
#[derive(Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryInfo {
pub name: Option<String>,
pub icon: Option<DataUrl<'static>>,
#[ts(as = "BTreeMap::<String, Category>")]
pub categories: BTreeMap<InternedString, Category>,
}
pub async fn get_info(ctx: RegistryContext) -> Result<RegistryInfo, Error> {
let peek = ctx.db.peek().await.into_index();
Ok(RegistryInfo {
name: peek.as_name().de()?,
icon: peek.as_icon().de()?,
categories: peek.as_package().as_categories().de()?,
})
}
pub fn registry_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand(
@@ -85,13 +67,8 @@ pub fn registry_api<C: Context>() -> ParentHandler<C> {
.with_about("List info including registry name and packages")
.with_call_remote::<CliContext>(),
)
.subcommand(
"info",
from_fn_async(get_info)
.with_display_serializable()
.with_about("Display registry name, icon, and package categories")
.with_call_remote::<CliContext>(),
)
.subcommand("info", info::info_api::<C>())
// set info and categories
.subcommand(
"os",
os::os_api::<C>().with_about("Commands related to OS assets and versions"),

View File

@@ -40,7 +40,12 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
.with_about("Download img"),
)
.subcommand("squashfs", from_fn_async(get_squashfs).no_cli())
.subcommand("squashfs", from_fn_async(cli_get_os_asset).no_display().with_about("Download squashfs"))
.subcommand(
"squashfs",
from_fn_async(cli_get_os_asset)
.no_display()
.with_about("Download squashfs"),
)
}
#[derive(Debug, Deserialize, Serialize, TS)]
@@ -104,7 +109,11 @@ pub async fn get_squashfs(
pub struct CliGetOsAssetParams {
pub version: Version,
pub platform: InternedString,
#[arg(long = "download", short = 'd')]
#[arg(
long = "download",
short = 'd',
help = "The path of the directory to download to"
)]
pub download: Option<PathBuf>,
#[arg(
long = "reverify",

View File

@@ -0,0 +1,147 @@
use std::collections::BTreeMap;
use clap::Parser;
use imbl_value::InternedString;
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::context::CliContext;
use crate::prelude::*;
use crate::registry::context::RegistryContext;
use crate::registry::package::index::Category;
use crate::s9pk::manifest::Description;
use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
pub fn category_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand(
"add",
from_fn_async(add_category)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("Add a category to the registry")
.with_call_remote::<CliContext>(),
)
.subcommand(
"remove",
from_fn_async(remove_category)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("Remove a category from the registry")
.with_call_remote::<CliContext>(),
)
.subcommand(
"list",
from_fn_async(list_categories)
.with_display_serializable()
.with_custom_display_fn(|params, categories| {
Ok(display_categories(params.params, categories))
})
.with_call_remote::<CliContext>(),
)
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddCategoryParams {
#[ts(type = "string")]
pub id: InternedString,
pub name: String,
#[arg(short, long, help = "Short description for the category")]
pub short: String,
#[arg(short, long, help = "Long description for the category")]
pub long: String,
}
pub async fn add_category(
ctx: RegistryContext,
AddCategoryParams {
id,
name,
short,
long,
}: AddCategoryParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| {
db.as_index_mut()
.as_package_mut()
.as_categories_mut()
.insert(
&id,
&Category {
name,
description: Description { short, long },
},
)
})
.await?;
Ok(())
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveCategoryParams {
#[ts(type = "string")]
pub id: InternedString,
}
pub async fn remove_category(
ctx: RegistryContext,
RemoveCategoryParams { id }: RemoveCategoryParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| {
db.as_index_mut()
.as_package_mut()
.as_categories_mut()
.remove(&id)
})
.await?;
Ok(())
}
pub async fn list_categories(
ctx: RegistryContext,
) -> Result<BTreeMap<InternedString, Category>, Error> {
ctx.db
.peek()
.await
.into_index()
.into_package()
.into_categories()
.de()
}
pub fn display_categories<T>(
params: WithIoFormat<T>,
categories: BTreeMap<InternedString, Category>,
) {
use prettytable::*;
if let Some(format) = params.format {
return display_serializable(format, categories);
}
let mut table = Table::new();
table.add_row(row![bc =>
"ID",
"NAME",
"SHORT DESCRIPTION",
"LONG DESCRIPTION",
]);
for (id, info) in categories {
table.add_row(row![
&*id,
&info.name,
&info.description.short,
&info.description.long,
]);
}
table.print_tty(false).unwrap();
}

View File

@@ -5,8 +5,10 @@ use crate::prelude::*;
use crate::util::serde::HandlerExtSerde;
pub mod add;
pub mod category;
pub mod get;
pub mod index;
pub mod signer;
pub fn package_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
@@ -29,6 +31,10 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
.no_display()
.with_about("Add package to registry index"),
)
.subcommand(
"signer",
signer::signer_api::<C>().with_about("Add, remove, and list package signers"),
)
.subcommand(
"get",
from_fn_async(get::get_package)
@@ -40,4 +46,9 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
.with_about("List installation candidate package(s)")
.with_call_remote::<CliContext>(),
)
.subcommand(
"category",
category::category_api::<C>()
.with_about("Update the categories for packages on the registry"),
)
}

View File

@@ -0,0 +1,133 @@
use std::collections::BTreeMap;
use clap::Parser;
use models::PackageId;
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::context::CliContext;
use crate::prelude::*;
use crate::registry::admin::display_signers;
use crate::registry::context::RegistryContext;
use crate::registry::signer::SignerInfo;
use crate::rpc_continuations::Guid;
use crate::util::serde::HandlerExtSerde;
pub fn signer_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand(
"add",
from_fn_async(add_package_signer)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("Add package signer")
.with_call_remote::<CliContext>(),
)
.subcommand(
"remove",
from_fn_async(remove_package_signer)
.with_metadata("admin", Value::Bool(true))
.no_display()
.with_about("Remove package signer")
.with_call_remote::<CliContext>(),
)
.subcommand(
"list",
from_fn_async(list_package_signers)
.with_display_serializable()
.with_custom_display_fn(|handle, result| Ok(display_signers(handle.params, result)))
.with_about("List package signers and related signer info")
.with_call_remote::<CliContext>(),
)
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PackageSignerParams {
pub id: PackageId,
pub signer: Guid,
}
pub async fn add_package_signer(
ctx: RegistryContext,
PackageSignerParams { id, signer }: PackageSignerParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| {
ensure_code!(
db.as_index().as_signers().contains_key(&signer)?,
ErrorKind::InvalidRequest,
"unknown signer {signer}"
);
db.as_index_mut()
.as_package_mut()
.as_packages_mut()
.as_idx_mut(&id)
.or_not_found(&id)?
.as_authorized_mut()
.mutate(|s| Ok(s.insert(signer)))?;
Ok(())
})
.await
}
pub async fn remove_package_signer(
ctx: RegistryContext,
PackageSignerParams { id, signer }: PackageSignerParams,
) -> Result<(), Error> {
ctx.db
.mutate(|db| {
if !db
.as_index_mut()
.as_package_mut()
.as_packages_mut()
.as_idx_mut(&id)
.or_not_found(&id)?
.as_authorized_mut()
.mutate(|s| Ok(s.remove(&signer)))?
{
return Err(Error::new(
eyre!("signer {signer} is not authorized to sign for {id}"),
ErrorKind::NotFound,
));
}
Ok(())
})
.await
}
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ListPackageSignersParams {
pub id: PackageId,
}
pub async fn list_package_signers(
ctx: RegistryContext,
ListPackageSignersParams { id }: ListPackageSignersParams,
) -> Result<BTreeMap<Guid, SignerInfo>, Error> {
let db = ctx.db.peek().await;
db.as_index()
.as_package()
.as_packages()
.as_idx(&id)
.or_not_found(&id)?
.as_authorized()
.de()?
.into_iter()
.filter_map(|guid| {
db.as_index()
.as_signers()
.as_idx(&guid)
.map(|s| s.de().map(|s| (guid, s)))
})
.collect()
}

View File

@@ -25,7 +25,7 @@ pub struct SignerInfo {
pub keys: HashSet<AnyVerifyingKey>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
// TODO: better types

View File

@@ -3,7 +3,7 @@ Description=StartOS Daemon
[Service]
Type=simple
Environment=RUST_LOG=startos=debug,js_engine=debug,patch_db=warn
Environment=RUST_LOG=startos=debug,patch_db=warn
ExecStart=/usr/bin/startd
Restart=always
RestartSec=3

View File

@@ -6,6 +6,7 @@ import {
} from "../../../base/lib/types/ManifestTypes"
import { SDKVersion } from "../StartSdk"
import { VersionGraph } from "../version/VersionGraph"
import { execSync } from "child_process"
/**
* @description Use this function to define critical information about your package
@@ -26,6 +27,16 @@ export function setupManifest<
return manifest
}
function gitHash(): string {
const hash = execSync("git rev-parse HEAD").toString().trim()
try {
execSync("git diff-index --quiet HEAD --")
return hash
} catch (e) {
return hash + "-modified"
}
}
export function buildManifest<
Id extends string,
Version extends string,
@@ -56,7 +67,7 @@ export function buildManifest<
)
return {
...manifest,
gitHash: null,
gitHash: gitHash(),
osVersion: SDKVersion,
version: versions.current.options.version,
releaseNotes: versions.current.options.releaseNotes,

View File

@@ -1,12 +1,12 @@
{
"name": "@start9labs/start-sdk",
"version": "0.3.6-alpha9",
"version": "0.3.6-alpha.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@start9labs/start-sdk",
"version": "0.3.6-alpha9",
"version": "0.3.6-alpha.13",
"license": "MIT",
"dependencies": {
"@iarna/toml": "^2.2.5",

View File

@@ -1,6 +1,6 @@
{
"name": "@start9labs/start-sdk",
"version": "0.3.6-alpha.12",
"version": "0.3.6-alpha.13",
"description": "Software development kit to facilitate packaging services for StartOS",
"main": "./package/lib/index.js",
"types": "./package/lib/index.d.ts",