From 8fd183273df9d14fa805f7766e5cac3975cf88c7 Mon Sep 17 00:00:00 2001 From: akirilov <***REDACTED***> Date: Sun, 31 May 2026 09:04:51 +0000 Subject: [PATCH 1/3] Adding support for fedora --- .devcontainer/Dockerfile | 3 +- .devcontainer/devcontainer.json | 5 +- src/steamcmd/steamcmd-helper.go | 107 +++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 12 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3c8d5272..f665842e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -24,8 +24,7 @@ RUN mkdir -p /go/bin && chown -R vscode:vscode /go # Install Node.js 22.15.0 RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get install -y nodejs && \ - npm install -g npm@latest + apt-get install -y nodejs # Set up non-root user and workspace USER vscode diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 44166e0b..74805d67 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,8 +21,7 @@ "vscode": { "extensions": [ "golang.go", - "svelte.svelte-vscode", - "eamodio.gitlens" + "svelte.svelte-vscode" ], "settings": { "go.toolsManagement.autoUpdate": true, @@ -30,5 +29,5 @@ } } }, - "postCreateCommand": "go mod tidy && cd frontend && npm install && npm install @sveltejs/vite-plugin-svelte" + "postCreateCommand": "go mod tidy && cd frontend && npm install && npm install @sveltejs/vite-plugin-svelte && npm audit fix" } \ No newline at end of file diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index 4caee4fe..e8330fc1 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -14,6 +14,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "time" @@ -293,9 +294,64 @@ func untarWrapper(r io.ReaderAt, _ int64, dest string) error { return untar(dest, io.NewSectionReader(r, 0, 1<<63-1)) // Use a large size for the section reader } +type distroFamily int + +const ( + distroUnknown distroFamily = iota + distroDebian + distroRHEL +) + +// parseOSRelease parses a /etc/os-release file into a key-value map. +func parseOSRelease(content string) map[string]string { + fields := make(map[string]string) + for _, line := range strings.Split(content, "\n") { + parts := strings.SplitN(line, "=", 2) + if len(parts) != 2 { + continue + } + fields[parts[0]] = strings.Trim(parts[1], `"`) + } + return fields +} + +// detectDistroFamily reads /etc/os-release and returns the distro family. +// ID is checked first (single value); ID_LIKE is the fallback (space-separated list). +func detectDistroFamily() distroFamily { + data, err := os.ReadFile("/etc/os-release") + if err != nil { + return distroUnknown + } + + debianIDs := []string{"ubuntu", "debian", "linuxmint", "pop", "elementary", "raspbian"} + rhelIDs := []string{"rhel", "centos", "fedora", "rocky", "almalinux", "ol"} + + fields := parseOSRelease(string(data)) + + // Check ID first — it's a single value identifying the primary distro. + id := strings.ToLower(fields["ID"]) + if slices.Contains(debianIDs, id) { + return distroDebian + } + if slices.Contains(rhelIDs, id) { + return distroRHEL + } + + // Fall back to ID_LIKE — a space-separated list of closely related distros. + for _, like := range strings.Fields(strings.ToLower(fields["ID_LIKE"])) { + if slices.Contains(debianIDs, like) { + return distroDebian + } + if slices.Contains(rhelIDs, like) { + return distroRHEL + } + } + + return distroUnknown +} + // installRequiredLibraries installs the required libraries for SteamCMD if they are not already installed. func installRequiredLibraries() error { - // Check if the system is Debian-based if runtime.GOOS != "linux" { return nil // Only Linux systems need this } @@ -306,8 +362,19 @@ func installRequiredLibraries() error { return nil } - // According to https://developer.valvesoftware.com/wiki/SteamCMD#Manually only lib32gcc-s1 is needed - // List of required libraries + switch detectDistroFamily() { + case distroDebian: + return installRequiredLibrariesDebian() + case distroRHEL: + return installRequiredLibrariesRHEL() + default: + return fmt.Errorf("unsupported Linux distribution: only Ubuntu/Debian and RHEL-based distros are supported") + } +} + +// installRequiredLibrariesDebian installs SteamCMD dependencies on Ubuntu/Debian using apt-get. +// According to https://developer.valvesoftware.com/wiki/SteamCMD#Manually only lib32gcc-s1 is needed. +func installRequiredLibrariesDebian() error { requiredLibs := []string{ "lib32gcc-s1", //"lib32stdc++6", @@ -316,10 +383,9 @@ func installRequiredLibraries() error { // Check and install each library for _, lib := range requiredLibs { // Check if the library is already installed - cmd := exec.Command("dpkg", "-s", lib) - if err := cmd.Run(); err == nil { + if err := exec.Command("dpkg", "-s", lib).Run(); err == nil { logger.Install.Debug("✅ Library already installed: " + lib + "\n") - continue // Library is already installed, skip to the next one + continue } // Library is not installed, attempt to install it @@ -327,12 +393,39 @@ func installRequiredLibraries() error { installCmd := exec.Command("sudo", "apt-get", "install", "-y", lib) installCmd.Stdout = os.Stdout installCmd.Stderr = os.Stderr - if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install library %s: %w", lib, err) } logger.Install.Debug("✅ Installed library: " + lib + "\n") } + return nil +} + +// installRequiredLibrariesRHEL installs SteamCMD dependencies on RHEL-based distros using dnf. +// libgcc.i686 is the RHEL equivalent of lib32gcc-s1 on Debian-based distros. +func installRequiredLibrariesRHEL() error { + requiredLibs := []string{ + "libgcc.i686", + "libstdc++.i686", + } + + // Check and install each library + for _, lib := range requiredLibs { + // Check if the library is already installed + if err := exec.Command("rpm", "-q", lib).Run(); err == nil { + logger.Install.Debug("✅ Library already installed: " + lib + "\n") + continue + } + // Library is not installed, attempt to install it + logger.Install.Debug("🔄 Installing library: " + lib + "\n") + installCmd := exec.Command("sudo", "dnf", "install", "-y", lib) + installCmd.Stdout = os.Stdout + installCmd.Stderr = os.Stderr + if err := installCmd.Run(); err != nil { + return fmt.Errorf("failed to install library %s: %w", lib, err) + } + logger.Install.Debug("✅ Installed library: " + lib + "\n") + } return nil } From aca9ef1e1874e2079c5b5f22f25b827349e0de6c Mon Sep 17 00:00:00 2001 From: akirilov Date: Sun, 31 May 2026 10:19:37 +0000 Subject: [PATCH 2/3] add devcontainer lock file --- .devcontainer/devcontainer-lock.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .devcontainer/devcontainer-lock.json diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 00000000..94b2b7fe --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/go:1": { + "version": "1.3.4", + "resolved": "ghcr.io/devcontainers/features/go@sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032", + "integrity": "sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032" + } + } +} From 9b2148b18e181094a73b6e212b2de43fada7569e Mon Sep 17 00:00:00 2001 From: akirilov <***REDACTED***> Date: Mon, 1 Jun 2026 01:39:40 +0000 Subject: [PATCH 3/3] trim both single and double quotes when parsing OS type --- src/steamcmd/steamcmd-helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index e8330fc1..c7dad485 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -310,7 +310,7 @@ func parseOSRelease(content string) map[string]string { if len(parts) != 2 { continue } - fields[parts[0]] = strings.Trim(parts[1], `"`) + fields[parts[0]] = strings.Trim(parts[1], "\"'") } return fields }