feat(platform): detect distro, WSL, and architecture

This commit is contained in:
MDietermann
2026-04-13 19:59:04 +02:00
parent ea0d793461
commit 3b666615d7
2 changed files with 108 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
// Package platform detects the host OS/distro/WSL status.
package platform
import (
"bufio"
"fmt"
"io"
"os"
"runtime"
"strings"
)
// Distro is a narrow enum of distros we care about.
type Distro string
const (
DistroArch Distro = "arch"
DistroUnknown Distro = "unknown"
)
// Platform holds detected host information.
type Platform struct {
Distro Distro
IsWSL bool
Arch string // e.g. "amd64", "arm64"
}
// Detect reads the live system. Returns DistroUnknown rather than an error
// when /etc/os-release is missing or unrecognized; callers decide what to do.
func Detect() (Platform, error) {
f, err := os.Open("/etc/os-release")
distro := DistroUnknown
if err == nil {
distro = parseDistro(f)
_ = f.Close()
} else if !os.IsNotExist(err) {
return Platform{}, fmt.Errorf("open /etc/os-release: %w", err)
}
wsl := false
if data, err := os.ReadFile("/proc/sys/kernel/osrelease"); err == nil {
lower := strings.ToLower(string(data))
wsl = strings.Contains(lower, "microsoft") || strings.Contains(lower, "wsl")
}
return Platform{Distro: distro, IsWSL: wsl, Arch: runtime.GOARCH}, nil
}
func parseDistro(r io.Reader) Distro {
sc := bufio.NewScanner(r)
for sc.Scan() {
line := sc.Text()
if !strings.HasPrefix(line, "ID=") {
continue
}
id := strings.Trim(strings.TrimPrefix(line, "ID="), `"`)
if id == "arch" {
return DistroArch
}
return DistroUnknown
}
return DistroUnknown
}

View File

@@ -0,0 +1,45 @@
package platform
import (
"strings"
"testing"
)
func TestParseDistroArch(t *testing.T) {
osRelease := `NAME="Arch Linux"
ID=arch
ID_LIKE=archlinux
`
if got := parseDistro(strings.NewReader(osRelease)); got != DistroArch {
t.Fatalf("got %v", got)
}
}
func TestParseDistroUbuntu(t *testing.T) {
osRelease := `NAME="Ubuntu"
ID=ubuntu
`
if got := parseDistro(strings.NewReader(osRelease)); got != DistroUnknown {
t.Fatalf("got %v", got)
}
}
func TestParseDistroQuoted(t *testing.T) {
osRelease := `ID="arch"
`
if got := parseDistro(strings.NewReader(osRelease)); got != DistroArch {
t.Fatalf("got %v", got)
}
}
func TestDetectReturnsArch(t *testing.T) {
p, err := Detect()
if err != nil {
t.Fatal(err)
}
if p.Arch == "" {
t.Fatal("arch is empty")
}
// We don't assert Distro here because the test host may not be Arch.
// The parse-level tests above cover that logic.
}