mirror of
https://github.com/rustfs/rustfs.git
synced 2026-03-17 14:24:08 +00:00
feat: add build-rustfs-gui process and optimize utils/helper.rs
1. Added a new build process `build-rustfs-gui` in `build.yaml` to streamline the build operations for the RustFS GUI. 2. Optimized `cli/rustfs-gui/utils/helper.rs` by using `rust-embed` to embed the `rustfs` resources directly into the binary.
This commit is contained in:
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags: [ 'v*', '*' ]
|
||||
|
||||
jobs:
|
||||
build-rustfs:
|
||||
@@ -60,9 +61,12 @@ jobs:
|
||||
# Create package
|
||||
mkdir -p ${ARTIFACT_NAME}
|
||||
cp "$bin_path" ${ARTIFACT_NAME}/rustfs
|
||||
# cp -r static ${ARTIFACT_NAME}/
|
||||
zip -r ${ARTIFACT_NAME}.zip ${ARTIFACT_NAME}
|
||||
ls -la
|
||||
|
||||
# Copy files to the specified directory
|
||||
mkdir -p cli/rustfs-gui/embedded-rustfs
|
||||
cp -r ${ARTIFACT_NAME}/rustfs cli/rustfs-gui/embedded-rustfs/
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -70,9 +74,40 @@ jobs:
|
||||
path: ${{ steps.package.outputs.artifact_name }}.zip
|
||||
retention-days: 7
|
||||
|
||||
merge:
|
||||
build-rustfs-gui:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-rustfs
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dioxus-cli
|
||||
run: cargo install dioxus-cli
|
||||
|
||||
- name: Build and Bundle rustfs-gui
|
||||
run: |
|
||||
relaese_path = "target/${{ matrix.variant.target }}"
|
||||
mkdir -p ${relaese_path}
|
||||
cd cli/rustfs-gui
|
||||
if [[ "${{ matrix.variant.target }}" == *"apple-darwin"* ]]; then
|
||||
dx bundle --platform macos --package-types "macos" --package-types "dmg" --package-types "ios" --release --profile release --out-dir ../../${relaese_path}
|
||||
elif [[ "${{ matrix.variant.target }}" == *"windows-msvc"* ]]; then
|
||||
dx bundle --platform windows --package-types "msi" --release --profile release --out-dir ../../target/${relaese_path}
|
||||
fi
|
||||
cd ../..
|
||||
GUI_ARTIFACT_NAME="rustfs-gui-${{ matrix.variant.profile }}-${{ matrix.variant.target }}"
|
||||
zip -r ${GUI_ARTIFACT_NAME}.zip target/${{ matrix.variant.target }}/rustfs-gui
|
||||
echo "gui_artifact_name=${GUI_ARTIFACT_NAME}" >> $GITHUB_OUTPUT
|
||||
ls -la
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.package.outputs.gui_artifact_name }}
|
||||
path: ${{ steps.package.outputs.gui_artifact_name }}.zip
|
||||
retention-days: 7
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ build-rustfs, build-rustfs-gui ]
|
||||
steps:
|
||||
- uses: actions/upload-artifact/merge@v4
|
||||
with:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@
|
||||
/logs
|
||||
.devcontainer
|
||||
rustfs/static/*
|
||||
vendor
|
||||
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -5468,11 +5468,14 @@ dependencies = [
|
||||
"dioxus",
|
||||
"dirs 6.0.0",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"keyring",
|
||||
"reqwest",
|
||||
"rfd 0.15.2",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"tokio",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
|
||||
30
Cargo.toml
30
Cargo.toml
@@ -1,18 +1,18 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"madmin", # Management dashboard and admin API interface
|
||||
"rustfs", # Core file system implementation
|
||||
"ecstore", # Erasure coding storage implementation
|
||||
"e2e_test", # End-to-end test suite
|
||||
"common/common", # Shared utilities and data structures
|
||||
"common/lock", # Distributed locking implementation
|
||||
"common/protos", # Protocol buffer definitions
|
||||
"api/admin", # Admin HTTP API endpoints
|
||||
"reader", # Object reading service
|
||||
"common/workers", # Worker thread pools and task scheduling
|
||||
"iam", # Identity and Access Management
|
||||
"crypto", # Cryptography and security features
|
||||
"cli/rustfs-gui", # Graphical user interface client
|
||||
"madmin", # Management dashboard and admin API interface
|
||||
"rustfs", # Core file system implementation
|
||||
"ecstore", # Erasure coding storage implementation
|
||||
"e2e_test", # End-to-end test suite
|
||||
"common/common", # Shared utilities and data structures
|
||||
"common/lock", # Distributed locking implementation
|
||||
"common/protos", # Protocol buffer definitions
|
||||
"api/admin", # Admin HTTP API endpoints
|
||||
"reader", # Object reading service
|
||||
"common/workers", # Worker thread pools and task scheduling
|
||||
"iam", # Identity and Access Management
|
||||
"crypto", # Cryptography and security features
|
||||
"cli/rustfs-gui", # Graphical user interface client
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
@@ -45,6 +45,7 @@ futures = "0.3.31"
|
||||
futures-util = "0.3.31"
|
||||
common = { path = "./common/common" }
|
||||
reader = { path = "./reader" }
|
||||
hex = "0.4.3"
|
||||
hyper = "1.6.0"
|
||||
hyper-util = { version = "0.1.10", features = [
|
||||
"tokio",
|
||||
@@ -57,6 +58,7 @@ humantime = "2.1.0"
|
||||
keyring = { version = "3.6.1", features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||
lock = { path = "./common/lock" }
|
||||
lazy_static = "1.5.0"
|
||||
local-ip-address = "0.6.3"
|
||||
mime = "0.3.17"
|
||||
netif = "0.1.6"
|
||||
pin-project-lite = "0.2"
|
||||
@@ -71,6 +73,7 @@ reqwest = { version = "0.12.12", default-features = false, features = ["rustls-t
|
||||
rfd = { version = "0.15.2", default-features = false, features = ["xdg-portal", "tokio"] }
|
||||
rmp = "0.8.14"
|
||||
rmp-serde = "1.3.0"
|
||||
rust-embed = "8.6.0"
|
||||
s3s = { git = "https://github.com/Nugine/s3s.git", rev = "ab139f72fe768fb9d8cecfe36269451da1ca9779", default-features = true, features = [
|
||||
"tower",
|
||||
] }
|
||||
@@ -78,6 +81,7 @@ s3s-policy = { git = "https://github.com/Nugine/s3s.git", rev = "ab139f72fe768fb
|
||||
shadow-rs = { version = "0.38.0", default-features = false }
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.138"
|
||||
sha2 = "0.10.8"
|
||||
tempfile = "3.16.0"
|
||||
thiserror = "2.0.11"
|
||||
time = { version = "0.3.37", features = [
|
||||
|
||||
@@ -11,11 +11,14 @@ chrono = { workspace = true }
|
||||
dioxus = { workspace = true, features = ["router"] }
|
||||
dirs = { workspace = true }
|
||||
futures-util = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
keyring = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rfd = { workspace = true }
|
||||
rust-embed = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
tokio = { workspace = true, features = ["io-util", "net", "process", "sync"] }
|
||||
tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "tracing-log", "time", "local-time", "json"] }
|
||||
tracing-appender = { workspace = true }
|
||||
|
||||
1
cli/rustfs-gui/embedded-rustfs/README.md
Normal file
1
cli/rustfs-gui/embedded-rustfs/README.md
Normal file
@@ -0,0 +1 @@
|
||||
rustfs bin path, do not delete
|
||||
@@ -1,14 +1,32 @@
|
||||
use crate::utils::RustFSConfig;
|
||||
use dioxus::logger::tracing::{debug, error, info};
|
||||
use futures_util::TryStreamExt;
|
||||
use lazy_static::lazy_static;
|
||||
use rust_embed::RustEmbed;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command as StdCommand;
|
||||
use std::time::Duration;
|
||||
use tokio::fs;
|
||||
use tokio::fs::File;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::{mpsc, Mutex};
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "$CARGO_MANIFEST_DIR/embedded-rustfs/"]
|
||||
struct Asset;
|
||||
|
||||
// Use `lazy_static` to cache the checksum of embedded resources
|
||||
lazy_static! {
|
||||
static ref RUSTFS_HASH: Mutex<String> = {
|
||||
let rustfs_file = if cfg!(windows) { "rustfs.exe" } else { "rustfs" };
|
||||
let rustfs_data = Asset::get(rustfs_file).expect("RustFs binary not embedded");
|
||||
let hash = hex::encode(Sha256::digest(&rustfs_data.data));
|
||||
Mutex::new(hash)
|
||||
};
|
||||
}
|
||||
|
||||
/// Service command
|
||||
/// This enum represents the commands that can be sent to the service manager
|
||||
@@ -159,45 +177,37 @@ impl ServiceManager {
|
||||
}
|
||||
}
|
||||
|
||||
let executable_path = if cfg!(windows) {
|
||||
bin_dir.join("rustfs.exe")
|
||||
} else {
|
||||
bin_dir.join("rustfs")
|
||||
};
|
||||
let rustfs_file = if cfg!(windows) { "rustfs.exe" } else { "rustfs" };
|
||||
let executable_path = bin_dir.join(rustfs_file);
|
||||
let hash_path = bin_dir.join("embedded_rustfs.sha256");
|
||||
|
||||
// If the executable file doesn't exist, download and unzip it
|
||||
if !executable_path.exists() {
|
||||
// download the file
|
||||
let tmp_zip = rustfs_dir.join("rustfs.zip");
|
||||
let file_download_url = if cfg!(windows) {
|
||||
"https://api.xmb.xyz/download/rustfs-win.zip"
|
||||
} else {
|
||||
"https://api.xmb.xyz/download/rustfs.zip"
|
||||
};
|
||||
|
||||
let download_task = Self::download_file(file_download_url, &tmp_zip);
|
||||
let unzip_task = async {
|
||||
download_task.await?;
|
||||
Self::unzip_file(&tmp_zip, &bin_dir)?;
|
||||
tokio::fs::remove_file(&tmp_zip).await?;
|
||||
Ok::<(), Box<dyn Error>>(())
|
||||
};
|
||||
unzip_task.await?;
|
||||
|
||||
// delete the temporary zip file
|
||||
tokio::fs::remove_file(&tmp_zip).await?;
|
||||
|
||||
// set execution permissions on unix systems
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perms = std::fs::metadata(&executable_path)?.permissions();
|
||||
perms.set_mode(0o755);
|
||||
std::fs::set_permissions(&executable_path, perms)?;
|
||||
if executable_path.exists() && hash_path.exists() {
|
||||
let cached_hash = fs::read_to_string(&hash_path).await?;
|
||||
let expected_hash = RUSTFS_HASH.lock().await;
|
||||
if cached_hash == *expected_hash {
|
||||
println!("Use cached rustfs: {:?}", executable_path);
|
||||
return Ok(executable_path);
|
||||
}
|
||||
Self::show_info("服务程序已成功下载并准备就绪");
|
||||
}
|
||||
|
||||
// Extract and write files
|
||||
let rustfs_data = Asset::get(rustfs_file).expect("RustFS binary not embedded");
|
||||
let mut file = File::create(&executable_path).await?;
|
||||
file.write_all(&rustfs_data.data).await?;
|
||||
let expected_hash = hex::encode(Sha256::digest(&rustfs_data.data));
|
||||
fs::write(&hash_path, expected_hash).await?;
|
||||
|
||||
// set execution permissions on unix systems
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perms = std::fs::metadata(&executable_path)?.permissions();
|
||||
perms.set_mode(0o755);
|
||||
std::fs::set_permissions(&executable_path, perms)?;
|
||||
}
|
||||
// Self::show_info("服务程序已成功下载并准备就绪");
|
||||
// }
|
||||
|
||||
Ok(executable_path)
|
||||
}
|
||||
|
||||
@@ -236,7 +246,8 @@ impl ServiceManager {
|
||||
/// let extract_path = Path::new("rustfs");
|
||||
/// unzip_file(zip_path, extract_path);
|
||||
/// ```
|
||||
fn unzip_file(zip_path: &Path, extract_path: &Path) -> Result<(), Box<dyn Error>> {
|
||||
async fn unzip_file(zip_path: &Path, extract_path: &Path) -> Result<(), Box<dyn Error>> {
|
||||
use std::fs::File;
|
||||
let file = File::open(zip_path)?;
|
||||
let mut archive = zip::ZipArchive::new(file)?;
|
||||
|
||||
|
||||
@@ -73,9 +73,9 @@ iam = { path = "../iam" }
|
||||
jsonwebtoken = "9.3.0"
|
||||
tower-http = { version = "0.6.2", features = ["cors"] }
|
||||
mime_guess = "2.0.5"
|
||||
rust-embed = { version = "8.6.0", features = ["interpolate-folder-path"] }
|
||||
local-ip-address = "0.6.3"
|
||||
chrono = "0.4"
|
||||
rust-embed = { workspace = true, features = ["interpolate-folder-path"] }
|
||||
local-ip-address = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
prost-build.workspace = true
|
||||
@@ -87,7 +87,7 @@ futures-util.workspace = true
|
||||
# uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
|
||||
ecstore = { path = "../ecstore" }
|
||||
s3s.workspace = true
|
||||
clap = { version = "4.5.31", features = ["derive","env"] }
|
||||
clap = { version = "4.5.31", features = ["derive", "env"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "time"] }
|
||||
hyper-util = { version = "0.1.10", features = [
|
||||
"tokio",
|
||||
|
||||
Reference in New Issue
Block a user