Skip to content

Commit

Permalink
Merge pull request #567 from kinode-dao/release-candidate
Browse files Browse the repository at this point in the history
Release candidate 0.9.5
  • Loading branch information
dr-frmr authored Oct 10, 2024
2 parents db7a356 + d1b8aea commit 76c312a
Show file tree
Hide file tree
Showing 33 changed files with 1,545 additions and 459 deletions.
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "kinode_lib"
authors = ["KinodeDAO"]
version = "0.9.4"
version = "0.9.5"
edition = "2021"
description = "A general-purpose sovereign cloud computing platform"
homepage = "https://kinode.org"
Expand Down
47 changes: 47 additions & 0 deletions Dockerfile.buildbase
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
FROM ubuntu:22.04

# Set environment variables to avoid interactive dialog from APT
ENV DEBIAN_FRONTEND=noninteractive
ENV NVM_DIR=/root/.nvm

# Install all necessary packages in one layer and clean up in the same layer
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
pkg-config \
ca-certificates \
libssl-dev \
cmake \
llvm-dev \
libclang-dev \
clang \
curl \
git \
python3 \
&& update-ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Install Rust and wasm tools
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y \
&& . $HOME/.cargo/env \
&& rustup install nightly \
&& rustup target add wasm32-wasi \
&& rustup target add wasm32-wasi --toolchain nightly \
&& rustup target add wasm32-wasip1 \
&& rustup target add wasm32-wasip1 --toolchain nightly \
&& cargo install wasm-tools \
&& cargo install cargo-wasi \
&& rm -rf ~/.cargo/git \
&& rm -rf ~/.cargo/registry

# Install NVM, Node.js
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash \
&& . "$NVM_DIR/nvm.sh" \
&& nvm install node \
&& nvm use node

# Set up environment variables
ENV DEBIAN_FRONTEND=dialog \
PATH="/root/.nvm/versions/node/$(node -v)/bin:${PATH}"

# Set the default command to bash
CMD ["bash"]
14 changes: 14 additions & 0 deletions Dockerfile.buildruntime
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM nick1udwig/buildbase:latest

ARG DOCKER_BUILD_IMAGE_VERSION=latest

ENV NVM_DIR=/root/.nvm \
PATH="/root/.nvm/versions/node/$(node -v)/bin:${PATH}" \
DOCKER_BUILD_IMAGE_VERSION=$DOCKER_BUILD_IMAGE_VERSION

# Bind readonly & copy files in to avoid modifying host files
WORKDIR /input

# Set the default command to run the build script
# TODO: once build is idempotent, remove the `rm -rf` line
CMD ["/bin/bash", "-c", ". ~/.bashrc && . ~/.cargo/env && . $NVM_DIR/nvm.sh && rm -rf target/ kinode/packages/*/pkg/*wasm kinode/packages/*/*/target/ kinode/packages/*/pkg/api.zip kinode/packages/*/*/wit kinode/packages/app_store/pkg/ui kinode/packages/homepage/pkg/ui kinode/src/register-ui/build && ./scripts/build-release.py && cp -r /tmp/kinode-release/* /output && chmod 664 /output/* && rm -rf target/ kinode/packages/*/pkg/*wasm kinode/packages/*/*/target/ kinode/packages/*/pkg/api.zip kinode/packages/*/*/wit kinode/packages/app_store/pkg/ui kinode/packages/homepage/pkg/ui kinode/src/register-ui/build"]
3 changes: 2 additions & 1 deletion kinode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "kinode"
authors = ["KinodeDAO"]
version = "0.9.4"
version = "0.9.5"
edition = "2021"
description = "A general-purpose sovereign cloud computing platform"
homepage = "https://kinode.org"
Expand Down Expand Up @@ -62,6 +62,7 @@ indexmap = "2.4"
jwt = "0.16"
lib = { path = "../lib" }
lazy_static = "1.4.0"
libc = "0.2"
nohash-hasher = "0.2.0"
open = "5.1.4"
public-ip = "0.2.2"
Expand Down
10 changes: 9 additions & 1 deletion kinode/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fn output_reruns(dir: &Path) {
}
}

fn untar_gz_file(path: &Path, dest: &Path) -> std::io::Result<()> {
fn _untar_gz_file(path: &Path, dest: &Path) -> std::io::Result<()> {
// Open the .tar.gz file
let tar_gz = File::open(path)?;
let tar_gz_reader = BufReader::new(tar_gz);
Expand Down Expand Up @@ -222,5 +222,13 @@ fn main() -> anyhow::Result<()> {
let bootstrapped_processes_path = target_dir.join("bootstrapped_processes.rs");
fs::write(&bootstrapped_processes_path, bootstrapped_processes)?;

let version = if let Ok(version) = std::env::var("DOCKER_BUILD_IMAGE_VERSION") {
// embed the DOCKER_BUILD_IMAGE_VERSION
version
} else {
"none".to_string()
};
println!("cargo:rustc-env=DOCKER_BUILD_IMAGE_VERSION={version}");

Ok(())
}
8 changes: 8 additions & 0 deletions kinode/packages/app_store/api/app_store:sys-v1.wit
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ interface downloads {
auto-update(auto-update-request),
/// Notify that a download is complete
download-complete(download-complete-request),
/// Auto-update-download complete
auto-download-complete(auto-download-complete-request),
/// Get files for a package
get-files(option<package-id>),
/// Remove a file
Expand Down Expand Up @@ -243,6 +245,12 @@ interface downloads {
err: option<download-error>,
}

/// Request for an auto-download complete
record auto-download-complete-request {
download-info: download-complete-request,
manifest-hash: string,
}

/// Represents a hash mismatch error
record hash-mismatch {
desired: string,
Expand Down
5 changes: 4 additions & 1 deletion kinode/packages/app_store/app_store/src/http_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,10 @@ fn serve_paths(
&our.node().to_string(),
) {
Ok(_) => {
println!("successfully installed package: {:?}", process_package_id);
println!(
"successfully installed {}:{}",
process_package_id.package_name, process_package_id.publisher_node
);
Ok((StatusCode::CREATED, None, vec![]))
}
Err(e) => Ok((
Expand Down
76 changes: 38 additions & 38 deletions kinode/packages/app_store/app_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
//! It delegates these responsibilities to the downloads and chain processes respectively.
//!
use crate::kinode::process::downloads::{
DownloadCompleteRequest, DownloadResponses, ProgressUpdate,
AutoDownloadCompleteRequest, DownloadCompleteRequest, DownloadResponses, ProgressUpdate,
};
use crate::kinode::process::main::{
ApisResponse, GetApiResponse, InstallPackageRequest, InstallResponse, LocalRequest,
Expand Down Expand Up @@ -65,6 +65,7 @@ pub enum Req {
LocalRequest(LocalRequest),
Progress(ProgressUpdate),
DownloadComplete(DownloadCompleteRequest),
AutoDownloadComplete(AutoDownloadCompleteRequest),
Http(http::server::HttpServerRequest),
}

Expand Down Expand Up @@ -161,6 +162,40 @@ fn handle_message(
},
);
}
Req::AutoDownloadComplete(req) => {
if !message.is_local(&our) {
return Err(anyhow::anyhow!(
"auto download complete from non-local node"
));
}
// auto_install case:
// the downloads process has given us the new package manifest's
// capability hashes, and the old package's capability hashes.
// we can use these to determine if the new package has the same
// capabilities as the old one, and if so, auto-install it.

let manifest_hash = req.manifest_hash;
let package_id = req.download_info.package_id;
let version_hash = req.download_info.version_hash;

if let Some(package) = state.packages.get(&package_id.clone().to_process_lib()) {
if package.manifest_hash == Some(manifest_hash) {
print_to_terminal(1, "auto_install:main, manifest_hash match");
if let Err(e) =
utils::install(&package_id, None, &version_hash, state, &our.node)
{
print_to_terminal(1, &format!("error auto_installing package: {e}"));
} else {
println!(
"auto_installed update for package: {:?}",
&package_id.to_process_lib()
);
}
} else {
print_to_terminal(1, "auto_install:main, manifest_hash do not match");
}
}
}
Req::DownloadComplete(req) => {
if !message.is_local(&our) {
return Err(anyhow::anyhow!("download complete from non-local node"));
Expand All @@ -182,41 +217,6 @@ fn handle_message(
.unwrap(),
},
);

// auto_install case:
// the downloads process has given us the new package manifest's
// capability hashes, and the old package's capability hashes.
// we can use these to determine if the new package has the same
// capabilities as the old one, and if so, auto-install it.
if let Some(context) = message.context() {
let manifest_hash = String::from_utf8(context.to_vec())?;
if let Some(package) =
state.packages.get(&req.package_id.clone().to_process_lib())
{
if package.manifest_hash == Some(manifest_hash) {
print_to_terminal(1, "auto_install:main, manifest_hash match");
if let Err(e) = utils::install(
&req.package_id,
None,
&req.version_hash,
state,
&our.node,
) {
print_to_terminal(
1,
&format!("error auto_installing package: {e}"),
);
} else {
println!(
"auto_installed update for package: {:?}",
&req.package_id.to_process_lib()
);
}
} else {
print_to_terminal(1, "auto_install:main, manifest_hash do not match");
}
}
}
}
}
} else {
Expand Down Expand Up @@ -261,8 +261,8 @@ fn handle_local_request(
match utils::install(&package_id, metadata, &version_hash, state, &our.node) {
Ok(()) => {
println!(
"successfully installed package: {:?}",
&package_id.to_process_lib()
"successfully installed {}:{}",
package_id.package_name, package_id.publisher_node
);
LocalResponse::InstallResponse(InstallResponse::Success)
}
Expand Down
33 changes: 23 additions & 10 deletions kinode/packages/app_store/downloads/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
//! mechanism is implemented in the FT worker for improved modularity and performance.
//!
use crate::kinode::process::downloads::{
AutoUpdateRequest, DirEntry, DownloadCompleteRequest, DownloadError, DownloadRequests,
DownloadResponses, Entry, FileEntry, HashMismatch, LocalDownloadRequest, RemoteDownloadRequest,
RemoveFileRequest,
AutoDownloadCompleteRequest, AutoUpdateRequest, DirEntry, DownloadCompleteRequest,
DownloadError, DownloadRequests, DownloadResponses, Entry, FileEntry, HashMismatch,
LocalDownloadRequest, RemoteDownloadRequest, RemoveFileRequest,
};
use std::{collections::HashSet, io::Read, str::FromStr};

Expand Down Expand Up @@ -245,15 +245,15 @@ fn handle_message(
// if we have a pending auto_install, forward that context to the main process.
// it will check if the caps_hashes match (no change in capabilities), and auto_install if it does.

let context = if auto_updates.remove(&(
let manifest_hash = if auto_updates.remove(&(
req.package_id.clone().to_process_lib(),
req.version_hash.clone(),
)) {
match get_manifest_hash(
req.package_id.clone().to_process_lib(),
req.version_hash.clone(),
) {
Ok(manifest_hash) => Some(manifest_hash.as_bytes().to_vec()),
Ok(manifest_hash) => Some(manifest_hash),
Err(e) => {
print_to_terminal(
1,
Expand All @@ -267,13 +267,26 @@ fn handle_message(
};

// pushed to UI via websockets
let mut request = Request::to(("our", "main", "app_store", "sys"))
.body(serde_json::to_vec(&req)?);
Request::to(("our", "main", "app_store", "sys"))
.body(serde_json::to_vec(&req)?)
.send()?;

if let Some(ctx) = context {
request = request.context(ctx);
// trigger auto-update install trigger to main:app_store:sys
if let Some(manifest_hash) = manifest_hash {
let auto_download_complete_req = AutoDownloadCompleteRequest {
download_info: req.clone(),
manifest_hash,
};
print_to_terminal(
1,
&format!(
"auto_update download complete: triggering install on main:app_store:sys"
),
);
Request::to(("our", "main", "app_store", "sys"))
.body(serde_json::to_vec(&auto_download_complete_req)?)
.send()?;
}
request.send()?;
}
DownloadRequests::GetFiles(maybe_id) => {
// if not local, throw to the boonies.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface PackageSelectorProps {
}

const PackageSelector: React.FC<PackageSelectorProps> = ({ onPackageSelect }) => {
const { installed } = useAppsStore();
const { installed, fetchInstalled } = useAppsStore();
const [selectedPackage, setSelectedPackage] = useState<string>("");
const [customPackage, setCustomPackage] = useState<string>("");
const [isCustomPackageSelected, setIsCustomPackageSelected] = useState(false);
Expand All @@ -18,6 +18,10 @@ const PackageSelector: React.FC<PackageSelectorProps> = ({ onPackageSelect }) =>
}
}, [selectedPackage, onPackageSelect]);

useEffect(() => {
fetchInstalled();
}, []);

const handlePackageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value;
if (value === "custom") {
Expand Down
Loading

0 comments on commit 76c312a

Please sign in to comment.