package changes #23
@@ -321,6 +321,48 @@ func installNeovim(_ *CustomPackage, tmp string) {
|
||||
taskPrintf(" Neovim installed to %s, symlinked at %s\n", installDir, symlink)
|
||||
}
|
||||
|
||||
func installRustup(archive string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"chmod", "+x", archive}, CmdOpts{Out: out})
|
||||
runCmd([]string{archive, "-y", "--no-modify-path"}, CmdOpts{Out: out})
|
||||
taskPrintln(" rustup installed.")
|
||||
}
|
||||
|
||||
func installYq(archive string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"cp", archive, "/usr/local/bin/yq"}, CmdOpts{AsSudo: true, Out: out})
|
||||
runCmd([]string{"chmod", "+x", "/usr/local/bin/yq"}, CmdOpts{AsSudo: true, Out: out})
|
||||
taskPrintln(" yq installed.")
|
||||
}
|
||||
|
||||
func installDagger(archive, tmp string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"tar", "-C", tmp, "-xzf", archive}, CmdOpts{Out: out})
|
||||
runCmd([]string{"mv", filepath.Join(tmp, "dagger"), "/usr/local/bin/dagger"}, CmdOpts{AsSudo: true, Out: out})
|
||||
taskPrintln(" dagger installed.")
|
||||
}
|
||||
|
||||
func installTrivy(archive, tmp string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"tar", "-C", tmp, "-xzf", archive}, CmdOpts{Out: out})
|
||||
runCmd([]string{"mv", filepath.Join(tmp, "trivy"), "/usr/local/bin/trivy"}, CmdOpts{AsSudo: true, Out: out})
|
||||
taskPrintln(" trivy installed.")
|
||||
}
|
||||
|
||||
func installCosign(archive string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"cp", archive, "/usr/local/bin/cosign"}, CmdOpts{AsSudo: true, Out: out})
|
||||
runCmd([]string{"chmod", "+x", "/usr/local/bin/cosign"}, CmdOpts{AsSudo: true, Out: out})
|
||||
taskPrintln(" cosign installed.")
|
||||
}
|
||||
|
||||
func installGitleaks(archive, tmp string) {
|
||||
out := taskOut()
|
||||
runCmd([]string{"tar", "-C", tmp, "-xzf", archive}, CmdOpts{Out: out})
|
||||
runCmd([]string{"mv", filepath.Join(tmp, "gitleaks"), "/usr/local/bin/gitleaks"}, CmdOpts{AsSudo: true, Out: out})
|
||||
taskPrintln(" gitleaks installed.")
|
||||
}
|
||||
|
||||
// ── latest-version resolvers ────────────────────────────────────────────
|
||||
|
||||
func resolveLatestGo(_ *CustomPackage) (string, string, bool) {
|
||||
@@ -434,10 +476,23 @@ func cmpSemver(a, b string) int {
|
||||
return len(pa) - len(pb)
|
||||
}
|
||||
|
||||
func resolveLatestYq(_ *CustomPackage) (string, string, bool) {
|
||||
var rel ghRelease
|
||||
if !fetchJSON("https://api.github.com/repos/mikefarah/yq/releases/latest", &rel) {
|
||||
return "", "", false
|
||||
}
|
||||
version := strings.TrimPrefix(rel.TagName, "v")
|
||||
if version == "" {
|
||||
return "", "", false
|
||||
}
|
||||
return version, "", true
|
||||
}
|
||||
|
||||
var latestResolvers = map[string]func(*CustomPackage) (string, string, bool){
|
||||
"go": resolveLatestGo,
|
||||
"firecracker": resolveLatestFirecracker,
|
||||
"zig": resolveLatestZig,
|
||||
"yq": resolveLatestYq,
|
||||
}
|
||||
|
||||
// resolveLatest best-effort upgrades pkg.Version/SHA256 to the latest release.
|
||||
@@ -598,6 +653,18 @@ func runOneCustomInstall(pkg *CustomPackage) {
|
||||
installFirecracker(archive, tmp)
|
||||
case "zig":
|
||||
installZig(pkg, archive)
|
||||
case "rustup":
|
||||
installRustup(archive)
|
||||
case "yq":
|
||||
installYq(archive)
|
||||
case "dagger":
|
||||
installDagger(archive, tmp)
|
||||
case "trivy":
|
||||
installTrivy(archive, tmp)
|
||||
case "cosign":
|
||||
installCosign(archive)
|
||||
case "gitleaks":
|
||||
installGitleaks(archive, tmp)
|
||||
default:
|
||||
warn(fmt.Sprintf("No install handler for '%s' — skipping", pkg.Name))
|
||||
}
|
||||
|
||||
@@ -64,6 +64,12 @@ var (
|
||||
osZig = map[string]string{"linux": "linux", "macos": "macos"}
|
||||
osNvim = map[string]string{"linux": "linux", "macos": "macos"}
|
||||
|
||||
osRustup = map[string]string{"linux": "unknown-linux-gnu", "macos": "apple-darwin"}
|
||||
archRustup = map[string]string{"x86_64": "x86_64", "aarch64": "aarch64"}
|
||||
osTrivy = map[string]string{"linux": "Linux", "macos": "macOS"}
|
||||
archTrivy = map[string]string{"x86_64": "64bit", "aarch64": "ARM64"}
|
||||
archGitleaks = map[string]string{"x86_64": "x64", "aarch64": "arm64"}
|
||||
|
||||
archTokens = map[string][]string{
|
||||
"x86_64": {"x86_64", "amd64", "x64"},
|
||||
"aarch64": {"aarch64", "arm64"},
|
||||
@@ -81,6 +87,11 @@ func formatURL(template, version string) string {
|
||||
"{os_go}", osGo[osName],
|
||||
"{os_zig}", osZig[osName],
|
||||
"{os_nvim}", osNvim[osName],
|
||||
"{os_rustup}", osRustup[osName],
|
||||
"{arch_rustup}", archRustup[archName],
|
||||
"{os_trivy}", osTrivy[osName],
|
||||
"{arch_trivy}", archTrivy[archName],
|
||||
"{arch_gitleaks}", archGitleaks[archName],
|
||||
)
|
||||
return r.Replace(template)
|
||||
}
|
||||
|
||||
+42
-1
@@ -10,10 +10,11 @@ package main
|
||||
// URL templates use the substitutions described in formatURL.
|
||||
|
||||
var SystemPackages = []string{
|
||||
"age",
|
||||
"ansible",
|
||||
"ansible-core",
|
||||
"aria2",
|
||||
"bashtop",
|
||||
"btm",
|
||||
"build-essential",
|
||||
"buildah",
|
||||
"containerd.io",
|
||||
@@ -29,10 +30,14 @@ var SystemPackages = []string{
|
||||
"git",
|
||||
"github-desktop",
|
||||
"google-chrome-stable",
|
||||
"helm",
|
||||
"jq",
|
||||
"kubectl",
|
||||
"lazygit",
|
||||
"lua",
|
||||
"minisign",
|
||||
"minikube",
|
||||
"nmap",
|
||||
"obs-studio",
|
||||
"obsidian",
|
||||
"pipx",
|
||||
@@ -42,8 +47,11 @@ var SystemPackages = []string{
|
||||
"qemu",
|
||||
"restic",
|
||||
"rg",
|
||||
"semgrep",
|
||||
"shutter",
|
||||
"sops",
|
||||
"temurin-25-jdk",
|
||||
"tmux",
|
||||
"vagrant",
|
||||
"virt-manager",
|
||||
"vivaldi-stable",
|
||||
@@ -52,6 +60,8 @@ var SystemPackages = []string{
|
||||
"yt-dlp",
|
||||
"zoom",
|
||||
"zsh",
|
||||
"fzf",
|
||||
"fd",
|
||||
"bzip2",
|
||||
"bzip2-devel",
|
||||
"curl",
|
||||
@@ -142,5 +152,36 @@ func customPackages() []CustomPackage {
|
||||
{Name: "copilot"},
|
||||
{Name: "playwright"},
|
||||
{Name: "gh-repo-bootstrap"},
|
||||
{
|
||||
Name: "rustup",
|
||||
Version: "latest",
|
||||
URLTemplate: "https://static.rust-lang.org/rustup/dist/{arch_rustup}-{os_rustup}/rustup-init",
|
||||
},
|
||||
{
|
||||
Name: "yq",
|
||||
Version: "4.44.1",
|
||||
URLTemplate: "https://github.com/mikefarah/yq/releases/download/v{version}/yq_{os_go}_{arch_go}",
|
||||
FetchLatest: "yq",
|
||||
},
|
||||
{
|
||||
Name: "dagger",
|
||||
Version: "0.11.4",
|
||||
URLTemplate: "https://github.com/dagger/dagger/releases/download/v{version}/dagger_v{version}_{os_go}_{arch_go}.tar.gz",
|
||||
},
|
||||
{
|
||||
Name: "trivy",
|
||||
Version: "0.52.0",
|
||||
URLTemplate: "https://github.com/aquasecurity/trivy/releases/download/v{version}/trivy_{version}_{os_trivy}-{arch_trivy}.tar.gz",
|
||||
},
|
||||
{
|
||||
Name: "cosign",
|
||||
Version: "2.2.4",
|
||||
URLTemplate: "https://github.com/sigstore/cosign/releases/download/v{version}/cosign-{os_go}-{arch_go}",
|
||||
},
|
||||
{
|
||||
Name: "gitleaks",
|
||||
Version: "8.18.2",
|
||||
URLTemplate: "https://github.com/gitleaks/gitleaks/releases/download/v{version}/gitleaks_{version}_{os_go}_{arch_gitleaks}.tar.gz",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ var packageOverrides = map[string]map[string]overrideEntry{
|
||||
"webcamoid": skipOverride(),
|
||||
},
|
||||
"apt-get": {
|
||||
"fd": replace("fd-find"),
|
||||
"ffmpeg-free": replace("ffmpeg"),
|
||||
"lua": replace("lua5.4"),
|
||||
"qemu": replace("qemu-system"),
|
||||
@@ -165,7 +166,6 @@ var packageOverrides = map[string]map[string]overrideEntry{
|
||||
"rg": replace("ripgrep"),
|
||||
"temurin-25-jdk": replace("temurin"),
|
||||
"vivaldi-stable": replace("vivaldi"),
|
||||
"bashtop": replace("btop"),
|
||||
"buildah": skipOverride(),
|
||||
"shutter": skipOverride(),
|
||||
"virt-manager": skipOverride(),
|
||||
@@ -223,6 +223,25 @@ func resolveSystemPkgs(names []string) ([]string, []string) {
|
||||
return resolved, skipped
|
||||
}
|
||||
|
||||
func installSystemPackages(pkgs []string, special []string) {
|
||||
if len(special) > 0 {
|
||||
tmp, err := os.MkdirTemp("", "bootstrap-special-")
|
||||
if err != nil {
|
||||
errLog(fmt.Sprintf("could not create temp dir for special packages: %v", err))
|
||||
return
|
||||
}
|
||||
defer osRemoveAll(tmp)
|
||||
for _, pkg := range special {
|
||||
fmt.Printf("\n [SPECIAL] Installing %s ...\n", pkg)
|
||||
installSpecialPkg(pkg, tmp)
|
||||
}
|
||||
}
|
||||
|
||||
if pkgMgr == "apt-get" && hasCmd("fdfind") {
|
||||
runCmd([]string{"ln", "-sf", "/usr/bin/fdfind", "/usr/local/bin/fd"}, CmdOpts{AsSudo: true})
|
||||
}
|
||||
}
|
||||
|
||||
// isSystemPkgInstalled queries the host package manager.
|
||||
func isSystemPkgInstalled(pkg string) bool {
|
||||
switch pkgMgr {
|
||||
|
||||
@@ -16,8 +16,8 @@ func specialPkgs() map[string]bool {
|
||||
}
|
||||
return map[string]bool{
|
||||
"github-desktop": true, "zoom": true, "obsidian": true,
|
||||
"minikube": true, "bashtop": true, "pipx": true,
|
||||
"poetry": true, "pulumi": true,
|
||||
"minikube": true, "pipx": true,
|
||||
"poetry": true, "pulumi": true, "semgrep": true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,14 +44,14 @@ func isSpecialPkgInstalled(pkg string) bool {
|
||||
return exists("/usr/local/bin/obsidian")
|
||||
case "minikube":
|
||||
return exists("/usr/local/bin/minikube") || hasCmd("minikube")
|
||||
case "bashtop":
|
||||
return exists("/usr/local/bin/bashtop") || exists(filepath.Join(home, "bashtop"))
|
||||
case "pulumi":
|
||||
return exists("/opt/pulumi/pulumi") || hasCmd("pulumi")
|
||||
case "pipx":
|
||||
return hasCmd("pipx")
|
||||
case "poetry":
|
||||
return hasCmd("poetry")
|
||||
case "semgrep":
|
||||
return hasCmd("semgrep")
|
||||
}
|
||||
return isSystemPkgInstalled(pkg)
|
||||
}
|
||||
@@ -259,30 +259,6 @@ func installMinikube(tmp string) {
|
||||
fmt.Printf(" minikube installed to %s\n", installPath)
|
||||
}
|
||||
|
||||
func installBashtop(_ string) {
|
||||
home, _ := os.UserHomeDir()
|
||||
cloneDir := filepath.Join(home, "bashtop")
|
||||
if _, err := osStat(cloneDir); err == nil {
|
||||
fmt.Printf(" Updating existing clone at %s ...\n", cloneDir)
|
||||
if !runCmd([]string{"git", "-C", cloneDir, "pull"}, CmdOpts{}).OK() {
|
||||
errLog("bashtop git pull failed")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
fmt.Printf(" Cloning bashtop to %s ...\n", cloneDir)
|
||||
if !runCmd([]string{"git", "clone", "https://github.com/aristocratos/bashtop.git", cloneDir}, CmdOpts{}).OK() {
|
||||
errLog("bashtop git clone failed")
|
||||
return
|
||||
}
|
||||
}
|
||||
if !runCmd([]string{"make", "install"}, CmdOpts{AsSudo: true, Cwd: cloneDir}).OK() {
|
||||
errLog("bashtop 'make install' failed")
|
||||
return
|
||||
}
|
||||
appendProfileLine("bashtop", "export PATH=$PATH:"+cloneDir)
|
||||
fmt.Printf(" bashtop installed. Clone at %s, binary at /usr/local/bin/bashtop\n", cloneDir)
|
||||
}
|
||||
|
||||
func installPulumi(tmp string) {
|
||||
version := fetchText("https://www.pulumi.com/latest-version")
|
||||
if version == "" {
|
||||
@@ -356,6 +332,14 @@ func installPoetry(_ string) {
|
||||
runCmd([]string{"pipx", "install", "poetry"}, CmdOpts{})
|
||||
}
|
||||
|
||||
func installSemgrep(_ string) {
|
||||
if !hasCmd("pipx") {
|
||||
errLog("pipx is not installed — cannot install semgrep")
|
||||
return
|
||||
}
|
||||
runCmd([]string{"pipx", "install", "semgrep"}, CmdOpts{})
|
||||
}
|
||||
|
||||
func installSpecialPkg(pkg, tmp string) {
|
||||
switch pkg {
|
||||
case "github-desktop":
|
||||
@@ -366,14 +350,14 @@ func installSpecialPkg(pkg, tmp string) {
|
||||
installObsidian(tmp)
|
||||
case "minikube":
|
||||
installMinikube(tmp)
|
||||
case "bashtop":
|
||||
installBashtop(tmp)
|
||||
case "pulumi":
|
||||
installPulumi(tmp)
|
||||
case "pipx":
|
||||
installPipx(tmp)
|
||||
case "poetry":
|
||||
installPoetry(tmp)
|
||||
case "semgrep":
|
||||
installSemgrep(tmp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user