Add Docker image, Compose, CI/CD workflows and docs
- Multi-arch (amd64/arm64) panel image: static musl binary on scratch, cross-compiled with cargo-zigbuild (no QEMU), non-root, healthcheck - docker-compose.yml + .env.example for one-command deployment - CI: fmt, clippy, tests, web type-checks, Windows launcher build, real-network installs of vanilla/Fabric/Quilt/Forge/NeoForge, Docker build - Release: Windows NSIS installer with baked-in panel URL, GHCR image push and GitHub release (tag push or manual dispatch) - README, admin guide, Microsoft auth setup, architecture, development - rustfmt config and formatting pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011ARcGWxLx21FwXJ3yfGriS
This commit is contained in:
54 files changed
+1019
-219
No files matched your search
+13
-20
@@ -47,13 +47,8 @@ impl Installed {
|
||||
pub fn classpath(&self, layout: &Layout) -> Vec<PathBuf> {
|
||||
let libs_dir = layout.libraries();
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
let mut cp: Vec<PathBuf> = self
|
||||
.libraries
|
||||
.iter()
|
||||
.filter(|l| l.classpath)
|
||||
.map(|l| l.file(&libs_dir))
|
||||
.filter(|p| seen.insert(p.clone()))
|
||||
.collect();
|
||||
let mut cp: Vec<PathBuf> =
|
||||
self.libraries.iter().filter(|l| l.classpath).map(|l| l.file(&libs_dir)).filter(|p| seen.insert(p.clone())).collect();
|
||||
cp.push(self.client_jar.clone());
|
||||
cp
|
||||
}
|
||||
@@ -69,11 +64,8 @@ async fn vanilla_json(client: &reqwest::Client, layout: &Layout, mc: &str) -> Re
|
||||
return Ok(serde_json::from_slice(&bytes)?);
|
||||
}
|
||||
};
|
||||
let entry = manifest
|
||||
.versions
|
||||
.iter()
|
||||
.find(|v| v.id == mc)
|
||||
.ok_or_else(|| anyhow!("Minecraft {mc} doesn't exist in Mojang's version list"))?;
|
||||
let entry =
|
||||
manifest.versions.iter().find(|v| v.id == mc).ok_or_else(|| anyhow!("Minecraft {mc} doesn't exist in Mojang's version list"))?;
|
||||
if !http::file_ok(&path, entry.sha1.as_deref(), None, true) {
|
||||
http::download_one(client, &Download::new(entry.url.clone(), path.clone(), entry.sha1.clone(), None), &|_| {}).await?;
|
||||
}
|
||||
@@ -82,11 +74,8 @@ async fn vanilla_json(client: &reqwest::Client, layout: &Layout, mc: &str) -> Re
|
||||
|
||||
fn library_downloads(libs: &[ResolvedLib], layout: &Layout, deep: bool) -> Vec<Download> {
|
||||
let dir = layout.libraries();
|
||||
let mut out: Vec<Download> = libs
|
||||
.iter()
|
||||
.filter(|l| !http::file_ok(&l.file(&dir), l.sha1.as_deref(), l.size, deep))
|
||||
.filter_map(|l| l.download(&dir))
|
||||
.collect();
|
||||
let mut out: Vec<Download> =
|
||||
libs.iter().filter(|l| !http::file_ok(&l.file(&dir), l.sha1.as_deref(), l.size, deep)).filter_map(|l| l.download(&dir)).collect();
|
||||
out.sort_by(|a, b| a.dest.cmp(&b.dest));
|
||||
out.dedup_by(|a, b| a.dest == b.dest);
|
||||
out
|
||||
@@ -146,7 +135,11 @@ pub async fn install(client: &reqwest::Client, layout: &Layout, spec: &InstallSp
|
||||
Loader::Vanilla => None,
|
||||
Loader::Fabric | Loader::Quilt => {
|
||||
let lv = meta::resolve_loader_version(client, spec.loader, mc, spec.loader_version.as_deref()).await?.unwrap();
|
||||
progress::stage(reporter, Stage::Loader, format!("Installing {} {lv}", if spec.loader == Loader::Fabric { "Fabric" } else { "Quilt" }));
|
||||
progress::stage(
|
||||
reporter,
|
||||
Stage::Loader,
|
||||
format!("Installing {} {lv}", if spec.loader == Loader::Fabric { "Fabric" } else { "Quilt" }),
|
||||
);
|
||||
Some(loaders::fabric::profile(client, layout, spec.loader, mc, &lv).await?)
|
||||
}
|
||||
Loader::Forge | Loader::NeoForge => {
|
||||
@@ -204,8 +197,8 @@ pub async fn install(client: &reqwest::Client, layout: &Layout, spec: &InstallSp
|
||||
};
|
||||
|
||||
let assets_root = layout.assets();
|
||||
let game_assets = assets::materialize_legacy(layout, &asset_ref.id, &asset_index, &spec.game_dir)?
|
||||
.unwrap_or_else(|| assets_root.clone());
|
||||
let game_assets =
|
||||
assets::materialize_legacy(layout, &asset_ref.id, &asset_index, &spec.game_dir)?.unwrap_or_else(|| assets_root.clone());
|
||||
|
||||
Ok(Installed {
|
||||
java: java_windowed,
|
||||
|
||||
Reference in new issue
Block a user