Public dry run dryrun-a43e907efd9d

Source commit: a43e907efd9d1561c23fe73499478e881f868355

Public tree identity: sha256:453dea30195485dd8939f575a69b39f4bb7acd84c4df23f8aa29b55d044f2673
This commit is contained in:
Clusterflux release dry run 2026-07-15 01:54:51 +02:00
commit 6f52bb46cd
210 changed files with 77158 additions and 0 deletions

View file

@ -0,0 +1,18 @@
[package]
name = "launch-build-demo"
version = "0.1.0"
edition.workspace = true
license.workspace = true
repository.workspace = true
[lib]
path = "src/build.rs"
crate-type = ["rlib", "cdylib"]
[dependencies]
clusterflux = { package = "clusterflux-sdk", path = "../../crates/clusterflux-sdk" }
futures-executor.workspace = true
serde.workspace = true
serde_json.workspace = true
[dev-dependencies]

View file

@ -0,0 +1,11 @@
# Launch Build Demo
This demo is the MVP build workflow expressed as Rust source code. It uses `env!("linux")`, recognizes `env!("windows")` when a Windows development node is attached, spawns debugger-visible virtual tasks, and returns artifact/source handles instead of moving large bytes through task arguments.
The Linux environment is defined by `envs/linux/Containerfile`. The Windows environment is a user-attached development contract and does not claim secure managed Windows sandboxing.
Inspect the bundle metadata:
```bash
clusterflux bundle inspect --project examples/launch-build-demo
```

View file

@ -0,0 +1,3 @@
FROM docker.io/library/alpine:3.20
RUN apk add --no-cache build-base tar zstd
WORKDIR /workspace

View file

@ -0,0 +1,2 @@
# User-attached Windows development execution contract for the MVP.
# This is not a managed untrusted Windows sandbox.

View file

@ -0,0 +1,6 @@
#include <stdio.h>
int main(void) {
puts("hello from a real Clusterflux build");
return 0;
}

View file

@ -0,0 +1,33 @@
use std::error::Error;
use futures_executor::block_on;
fn main() -> Result<(), Box<dyn Error>> {
let handle = block_on(
clusterflux::spawn::task_with_arg(41_i32, |_| -> i32 {
panic!("product-mode spawn invoked its local Rust closure")
})
.task_id("task_add_one")
.name("SDK product Wasmtime task")
.env(clusterflux::env!("linux"))
.start(),
)?;
let task_spec = handle
.task_spec()
.cloned()
.ok_or("CLUSTERFLUX_SDK_COORDINATOR did not enable product runtime")?;
let virtual_thread_id = handle.virtual_thread_id();
let result = block_on(handle.join())?;
println!(
"{}",
serde_json::to_string(&serde_json::json!({
"kind": "clusterflux-sdk-product-runtime",
"virtual_thread_id": virtual_thread_id,
"task_spec": task_spec,
"remote_result": result,
"local_function_invoked_by_spawn": false,
}))?
);
Ok(())
}

View file

@ -0,0 +1,367 @@
use clusterflux::{Artifact, EnvRef, SourceSnapshot};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, clusterflux::TaskArg)]
pub struct BuildReport {
pub linux_thread: u64,
pub linux_parallel_thread: u64,
pub package_thread: u64,
pub linux_artifact: Artifact,
pub package_artifact: Artifact,
pub source: SourceSnapshot,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, clusterflux::TaskArg)]
pub struct PackageInput {
pub release_name: String,
pub source: SourceSnapshot,
pub executable: Option<Artifact>,
pub inputs: Vec<Artifact>,
}
pub fn linux_env() -> EnvRef {
clusterflux::env!("linux")
}
pub fn windows_env() -> EnvRef {
clusterflux::env!("windows")
}
#[clusterflux::task(capabilities = "source_filesystem")]
pub async fn prepare_source() -> SourceSnapshot {
#[cfg(target_arch = "wasm32")]
{
return clusterflux::source::snapshot()
.await
.expect("the source task should snapshot the node checkout it was placed on");
}
#[cfg(not(target_arch = "wasm32"))]
SourceSnapshot {
digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
.to_owned(),
}
}
#[clusterflux::task(capabilities = "command")]
pub async fn compile_linux(source: SourceSnapshot) -> Artifact {
let _ = &source;
#[cfg(target_arch = "wasm32")]
{
let executable = clusterflux::fs::output_path("hello-clusterflux")
.expect("the executable output path should be task-local");
let output = clusterflux::command::Command::new("cc")
.args([
"-Os",
"-static",
"-s",
"fixture/hello-clusterflux.c",
"-o",
executable.as_str(),
])
.current_dir("/workspace")
.env("SOURCE_DATE_EPOCH", "0")
.timeout(std::time::Duration::from_secs(180))
.network_disabled()
.output()
.await
.expect("the declared Linux environment should provide a real C compiler");
assert_eq!(output.status_code, Some(0));
return clusterflux::fs::flush(&executable)
.await
.expect("the command-created executable should flush to node artifact storage");
}
#[cfg(not(target_arch = "wasm32"))]
Artifact {
id: "hello-clusterflux-native-test".to_owned(),
digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
.to_owned(),
size_bytes: 0,
}
}
#[clusterflux::task]
#[unsafe(no_mangle)]
pub extern "C" fn task_add_one(input: i32) -> i32 {
input + 1
}
#[clusterflux::task]
#[unsafe(no_mangle)]
pub extern "C" fn task_trap(_input: i32) -> i32 {
#[cfg(target_arch = "wasm32")]
core::arch::wasm32::unreachable();
#[cfg(not(target_arch = "wasm32"))]
panic!("intentional task trap")
}
#[clusterflux::task(capabilities = "command")]
pub async fn package_release(input: PackageInput) -> Artifact {
#[cfg(target_arch = "wasm32")]
{
assert_eq!(input.release_name, "release.tar");
let executable = input
.executable
.as_ref()
.expect("the package input should contain the compiler artifact");
assert!(input.inputs.iter().any(|artifact| artifact == executable));
let executable = clusterflux::fs::materialize(&executable, "package/hello-clusterflux")
.await
.expect("the retaining node should materialize the compiler artifact locally");
let release = clusterflux::fs::output_path("release.tar")
.expect("the release output path should be task-local");
let output = clusterflux::command::Command::new("tar")
.args([
"--sort=name",
"--mtime=@0",
"--owner=0",
"--group=0",
"--numeric-owner",
"--mode=0755",
"-cf",
release.as_str(),
"-C",
"/clusterflux/output/package",
"hello-clusterflux",
])
.current_dir("/workspace")
.env("SOURCE_DATE_EPOCH", "0")
.timeout(std::time::Duration::from_secs(180))
.network_disabled()
.output()
.await
.expect("the declared Linux environment should package the materialized executable");
assert_eq!(output.status_code, Some(0));
assert_eq!(
executable.as_str(),
"/clusterflux/output/package/hello-clusterflux"
);
return clusterflux::fs::flush(&release)
.await
.expect("the command-created release archive should flush as the final artifact");
}
#[cfg(not(target_arch = "wasm32"))]
{
let _ = input;
Artifact {
id: "release-native-test".to_owned(),
digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
.to_owned(),
size_bytes: 0,
}
}
}
#[clusterflux::task(capabilities = "command")]
pub async fn abort_probe() -> i32 {
#[cfg(target_arch = "wasm32")]
{
let output = clusterflux::command::Command::new("sh")
.args(["-c", "sleep 30"])
.output()
.await
.expect("abort probe command should either finish or be stopped by process abort");
return output.status_code.unwrap_or(-1);
}
#[cfg(not(target_arch = "wasm32"))]
0
}
#[clusterflux::task]
pub fn cooperative_cancellation_probe() -> i32 {
#[cfg(target_arch = "wasm32")]
loop {
if clusterflux::process::cancellation_requested()
.expect("task control should remain available while the Wasm task is running")
{
// Cancellation is a request observed and handled by task code. Returning
// normally is intentionally distinct from the runtime's forced abort path.
return 17;
}
}
#[cfg(not(target_arch = "wasm32"))]
17
}
#[clusterflux::task]
pub fn debug_child_probe() -> i32 {
#[cfg(target_arch = "wasm32")]
loop {
if clusterflux::process::cancellation_requested()
.expect("child debug participant should retain task control")
{
return 23;
}
}
#[cfg(not(target_arch = "wasm32"))]
23
}
#[clusterflux::task]
pub async fn debug_parent_probe() -> i32 {
#[cfg(target_arch = "wasm32")]
{
let child = clusterflux::spawn::task(debug_child_probe)
.name("debug child participant")
.start()
.await
.expect("parent debug participant should spawn its child");
return child
.join()
.await
.expect("parent debug participant should join its child");
}
#[cfg(not(target_arch = "wasm32"))]
23
}
#[clusterflux::main]
pub async fn build_main() -> BuildReport {
run_build_workflow().await
}
#[clusterflux::main(name = "fail")]
pub async fn fail_main() -> Result<i32, String> {
#[cfg(target_arch = "wasm32")]
{
let child = clusterflux::spawn::task_with_arg(0_i32, |value| task_trap(value))
.task_id("task_trap")
.name("intentional failing child")
.start()
.await
.map_err(|error| format!("failing entrypoint could not launch its child: {error}"))?;
return child
.join()
.await
.map_err(|error| format!("intentional child failure: {error}"));
}
#[cfg(not(target_arch = "wasm32"))]
Err("intentional child failure".to_owned())
}
#[clusterflux::main(name = "restart")]
pub async fn restart_main() -> i32 {
#[cfg(target_arch = "wasm32")]
{
return clusterflux::spawn::task_with_arg(0_i32, |value| task_trap(value))
.task_id("task_trap")
.name("edited restart probe")
.failure_policy(clusterflux::spawn::TaskFailurePolicy::AwaitOperator)
.start()
.await
.expect("restart probe should launch its child")
.join()
.await
.expect("restart probe child should complete");
}
#[cfg(not(target_arch = "wasm32"))]
task_add_one(41)
}
#[clusterflux::main(name = "park-wake")]
pub async fn park_wake_main() -> i32 {
#[cfg(target_arch = "wasm32")]
{
let mut value = 0_i32;
for _ in 0..16 {
let next = clusterflux::spawn::task_with_arg(value, |input| task_add_one(input))
.task_id("task_add_one")
.name("park/wake fuel refill probe")
.start()
.await
.expect("park/wake probe should launch")
.join()
.await
.expect("park/wake probe should complete");
value = i32::try_from(next).expect("park/wake result should remain in i32 range");
}
return value;
}
#[cfg(not(target_arch = "wasm32"))]
16
}
pub async fn run_build_workflow() -> BuildReport {
let source = clusterflux::spawn::async_task(prepare_source)
.name("prepare source snapshot")
.start()
.await
.unwrap()
.join()
.await
.unwrap();
let linux = clusterflux::spawn::async_task_with_arg(source.clone(), compile_linux)
.name("compile linux")
.env(linux_env())
.start()
.await
.unwrap();
let linux_parallel = clusterflux::spawn::async_task_with_arg(source.clone(), compile_linux)
.name("compile linux in parallel")
.env(linux_env())
.start()
.await
.unwrap();
let linux_thread = linux.virtual_thread_id();
let linux_parallel_thread = linux_parallel.virtual_thread_id();
let linux_artifact = linux.join().await.unwrap();
let linux_parallel_artifact = linux_parallel.join().await.unwrap();
assert_eq!(linux_artifact.digest, linux_parallel_artifact.digest);
let package = clusterflux::spawn::async_task_with_arg(
PackageInput {
release_name: "release.tar".to_owned(),
source: source.clone(),
executable: Some(linux_artifact.clone()),
inputs: vec![linux_artifact.clone()],
},
package_release,
)
.name("package artifacts")
.env(linux_env())
.start()
.await
.unwrap();
let package_thread = package.virtual_thread_id();
let package_artifact = package.join().await.unwrap();
BuildReport {
linux_thread,
linux_parallel_thread,
package_thread,
linux_artifact,
package_artifact,
source,
}
}
#[cfg(test)]
mod tests {
use futures_executor::block_on;
use super::*;
#[test]
fn flagship_workflow_is_rust_source_with_spawned_virtual_tasks() {
let main_report = block_on(build_main());
assert_eq!(
main_report.linux_artifact.id,
"hello-clusterflux-native-test"
);
assert_eq!(task_add_one(41), 42);
assert_eq!(block_on(restart_main()), 42);
assert_eq!(block_on(park_wake_main()), 16);
assert_eq!(linux_env().name, "linux");
assert_eq!(windows_env().name, "windows");
let report = block_on(run_build_workflow());
assert_ne!(report.linux_thread, report.package_thread);
assert_ne!(report.linux_thread, report.linux_parallel_thread);
assert_eq!(report.linux_artifact.id, "hello-clusterflux-native-test");
assert_eq!(report.package_artifact.id, "release-native-test");
assert_eq!(
report.source.digest,
"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
}