Fix CI: pnpm PATH, Obsidian arch matcher, Arch pkg names, Fedora lazygit COPR
- post.go: export PNPM_HOME+PATH before pnpm add -g so global bins install correctly in the non-interactive shell. Applied to installNpmPackage and installPlaywright (incl. browser install). - system.go: treat token-less Obsidian AppImage as x86_64 (upstream publishes "Obsidian-X.Y.Z.AppImage" with no arch suffix). - pkgmgr.go: docker-ce-rootless-extras and vagrant are AUR-only on Arch → skipOverride; pipx → python-pipx on pacman. - repos.go: new setupLazygitCoprRepo enables copr.fedorainfracloud.org/ dejan/lazygit on Fedora; wired into repoGroups so lazygit installs. - Tests: PNPM_HOME export (Linux+macOS), token-less Obsidian asset, pacman pkg overrides, COPR repo setup, updated repoGroups count. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -105,7 +105,8 @@ var packageOverrides = map[string]map[string]overrideEntry{
|
||||
"containerd.io": replace("containerd"),
|
||||
"docker-ce": replace("docker"),
|
||||
"docker-ce-cli": skipOverride(), // covered by docker
|
||||
"docker-ce-rootless-extras": replace("docker-rootless-extras"),
|
||||
"docker-ce-rootless-extras": skipOverride(), // AUR-only
|
||||
"pipx": replace("python-pipx"),
|
||||
"docker-buildx-plugin": replace("docker-buildx"),
|
||||
"docker-compose-plugin": replace("docker-compose"),
|
||||
"dotnet-sdk-10.0": replace("dotnet-sdk"),
|
||||
@@ -121,7 +122,7 @@ var packageOverrides = map[string]map[string]overrideEntry{
|
||||
"rg": replace("ripgrep"),
|
||||
"shutter": skipOverride(), // AUR-only
|
||||
"temurin-25-jdk": replace("jdk-openjdk"),
|
||||
"vagrant": replace("vagrant"),
|
||||
"vagrant": skipOverride(), // AUR-only
|
||||
"vivaldi-stable": replace("vivaldi"),
|
||||
"webcamoid": skipOverride(), // AUR-only; provided via Flatpak when --gui
|
||||
"wireshark": replace("wireshark-qt"),
|
||||
|
||||
+9
-2
@@ -91,8 +91,15 @@ func TestResolveSystemPkgs(t *testing.T) {
|
||||
if len(resolved) != 2 || resolved[0] != "btop" || resolved[1] != "ripgrep" {
|
||||
t.Errorf("expected [btop ripgrep], got %v", resolved)
|
||||
}
|
||||
if len(skipped) != 1 || skipped[0] != "buildah" {
|
||||
t.Errorf("expected skipped to be [buildah], got %v", skipped)
|
||||
// pacman: docker-ce-rootless-extras and vagrant are AUR-only -> skipped;
|
||||
// pipx is replaced with python-pipx.
|
||||
pkgMgr = "pacman"
|
||||
resolved, skipped = resolveSystemPkgs([]string{"docker-ce-rootless-extras", "vagrant", "pipx", "rg"})
|
||||
if len(resolved) != 2 || resolved[0] != "python-pipx" || resolved[1] != "ripgrep" {
|
||||
t.Errorf("expected [python-pipx ripgrep], got %v", resolved)
|
||||
}
|
||||
if len(skipped) != 2 || skipped[0] != "docker-ce-rootless-extras" || skipped[1] != "vagrant" {
|
||||
t.Errorf("expected skipped [docker-ce-rootless-extras vagrant], got %v", skipped)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -478,6 +478,13 @@ func installAgy() {
|
||||
}
|
||||
}
|
||||
|
||||
func pnpmEnvPrefix() string {
|
||||
if isMacOS {
|
||||
return `export PNPM_HOME="$HOME/Library/pnpm" && export PATH="$PNPM_HOME:$PATH" && `
|
||||
}
|
||||
return `export PNPM_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/pnpm" && export PATH="$PNPM_HOME:$PATH" && `
|
||||
}
|
||||
|
||||
func installNpmPackage(pkgName string) {
|
||||
home, _ := os.UserHomeDir()
|
||||
if _, err := osStat(filepath.Join(home, ".nvm")); err != nil {
|
||||
@@ -486,7 +493,8 @@ func installNpmPackage(pkgName string) {
|
||||
}
|
||||
ensureNodeLTS()
|
||||
fmt.Printf(" Installing %s via pnpm ...\n", pkgName)
|
||||
if !runShell(fmt.Sprintf(`bash -c "source ~/.nvm/nvm.sh && pnpm add -g %s"`, pkgName), CmdOpts{}).OK() {
|
||||
cmd := fmt.Sprintf(`bash -c "%ssource ~/.nvm/nvm.sh && pnpm add -g %s"`, pnpmEnvPrefix(), pkgName)
|
||||
if !runShell(cmd, CmdOpts{}).OK() {
|
||||
errLog(fmt.Sprintf("%s installation failed", pkgName))
|
||||
}
|
||||
}
|
||||
@@ -499,7 +507,8 @@ func installPlaywright() {
|
||||
}
|
||||
ensureNodeLTS()
|
||||
fmt.Println(" Installing playwright via pnpm ...")
|
||||
if !runShell(`bash -c "source ~/.nvm/nvm.sh && source ~/.bashrc 2>/dev/null; pnpm add -g playwright"`, CmdOpts{}).OK() {
|
||||
addCmd := fmt.Sprintf(`bash -c "%ssource ~/.nvm/nvm.sh && pnpm add -g playwright"`, pnpmEnvPrefix())
|
||||
if !runShell(addCmd, CmdOpts{}).OK() {
|
||||
errLog("playwright installation failed")
|
||||
return
|
||||
}
|
||||
@@ -510,7 +519,7 @@ func installPlaywright() {
|
||||
} else {
|
||||
fmt.Println(" Installing Playwright browsers ...")
|
||||
}
|
||||
if !runShell(fmt.Sprintf(`bash -c "source ~/.nvm/nvm.sh && source ~/.bashrc 2>/dev/null; %s"`, installCmd), CmdOpts{}).OK() {
|
||||
if !runShell(fmt.Sprintf(`bash -c "%ssource ~/.nvm/nvm.sh && %s"`, pnpmEnvPrefix(), installCmd), CmdOpts{}).OK() {
|
||||
errLog("playwright browser installation failed")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,6 +361,25 @@ func TestInstallPipAgyNpm(t *testing.T) {
|
||||
if len(runShellCmds) < 1 || !strings.Contains(runShellCmds[len(runShellCmds)-1], "pnpm add -g my-package") {
|
||||
t.Errorf("unexpected npm install command: %v", runShellCmds)
|
||||
}
|
||||
if !strings.Contains(runShellCmds[len(runShellCmds)-1], `PNPM_HOME=`) {
|
||||
t.Errorf("expected PNPM_HOME export, got: %v", runShellCmds)
|
||||
}
|
||||
|
||||
// macOS uses ~/Library/pnpm
|
||||
resetMocks()
|
||||
isMacOS = true
|
||||
runShellCmds = nil
|
||||
runShell = func(cmd string, opts CmdOpts) CmdResult {
|
||||
runShellCmds = append(runShellCmds, cmd)
|
||||
return CmdResult{ExitCode: 0}
|
||||
}
|
||||
osStat = func(name string) (os.FileInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
installNpmPackage("my-package")
|
||||
if len(runShellCmds) < 1 || !strings.Contains(runShellCmds[len(runShellCmds)-1], `Library/pnpm`) {
|
||||
t.Errorf("expected macOS PNPM_HOME path, got: %v", runShellCmds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsurePythonAndNode(t *testing.T) {
|
||||
|
||||
@@ -208,6 +208,18 @@ func setupDotnetRepo() {
|
||||
)
|
||||
}
|
||||
|
||||
func setupLazygitCoprRepo() {
|
||||
if pkgMgr != "dnf" {
|
||||
return
|
||||
}
|
||||
if repoFileExists("/etc/yum.repos.d/_copr:copr.fedorainfracloud.org:dejan:lazygit.repo") {
|
||||
return
|
||||
}
|
||||
// dnf-plugins-core provides the `copr` subcommand on dnf4; on dnf5 it's a no-op.
|
||||
runCmd([]string{"dnf", "install", "-y", "dnf-plugins-core"}, CmdOpts{AsSudo: true})
|
||||
runCmd([]string{"dnf", "copr", "enable", "-y", "dejan/lazygit"}, CmdOpts{AsSudo: true})
|
||||
}
|
||||
|
||||
type repoGroup struct {
|
||||
members map[string]bool
|
||||
setup func()
|
||||
@@ -229,5 +241,6 @@ func repoGroups() []repoGroup {
|
||||
{mk("vivaldi-stable"), setupVivaldiRepo},
|
||||
{mk("temurin-25-jdk"), setupTemurinRepo},
|
||||
{mk("dotnet-sdk-10.0"), setupDotnetRepo},
|
||||
{mk("lazygit"), setupLazygitCoprRepo},
|
||||
}
|
||||
}
|
||||
|
||||
+47
-2
@@ -193,10 +193,55 @@ func TestSetupDotnetRepo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupLazygitCoprRepo(t *testing.T) {
|
||||
defer resetMocks()
|
||||
|
||||
// On non-dnf hosts, it's a no-op.
|
||||
pkgMgr = "apt-get"
|
||||
called := false
|
||||
runCmd = func(argv []string, opts CmdOpts) CmdResult {
|
||||
called = true
|
||||
return CmdResult{ExitCode: 0}
|
||||
}
|
||||
setupLazygitCoprRepo()
|
||||
if called {
|
||||
t.Errorf("expected no-op on apt-get, but runCmd was called")
|
||||
}
|
||||
|
||||
// On dnf with repo absent, copr enable is invoked.
|
||||
pkgMgr = "dnf"
|
||||
osStat = func(name string) (os.FileInfo, error) {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
var calls [][]string
|
||||
runCmd = func(argv []string, opts CmdOpts) CmdResult {
|
||||
calls = append(calls, argv)
|
||||
return CmdResult{ExitCode: 0}
|
||||
}
|
||||
setupLazygitCoprRepo()
|
||||
joined := ""
|
||||
for _, c := range calls {
|
||||
joined += strings.Join(c, " ") + "\n"
|
||||
}
|
||||
if !strings.Contains(joined, "copr enable -y dejan/lazygit") {
|
||||
t.Errorf("expected copr enable call, got: %s", joined)
|
||||
}
|
||||
|
||||
// If the COPR repo file already exists, no commands are run.
|
||||
osStat = func(name string) (os.FileInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
calls = nil
|
||||
setupLazygitCoprRepo()
|
||||
if len(calls) != 0 {
|
||||
t.Errorf("expected no commands when repo file exists, got %v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoGroups(t *testing.T) {
|
||||
groups := repoGroups()
|
||||
if len(groups) != 6 {
|
||||
t.Errorf("expected 6 repo groups, got %d", len(groups))
|
||||
if len(groups) != 7 {
|
||||
t.Errorf("expected 7 repo groups, got %d", len(groups))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,18 +170,27 @@ func installObsidian(tmp string) {
|
||||
hostTokens := archTokens[archName]
|
||||
otherTokens := archTokens[otherArch()]
|
||||
|
||||
hasAnyToken := func(n string, tokens []string) bool {
|
||||
for _, t := range tokens {
|
||||
if strings.Contains(n, t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
matches := func(name string) bool {
|
||||
n := strings.ToLower(name)
|
||||
if !strings.HasSuffix(n, ".appimage") {
|
||||
return false
|
||||
}
|
||||
matched := false
|
||||
for _, t := range hostTokens {
|
||||
if strings.Contains(n, t) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
// Obsidian publishes the x86_64 AppImage without an arch suffix
|
||||
// (e.g. "Obsidian-1.12.7.AppImage") and the arm64 build as
|
||||
// "Obsidian-1.12.7-arm64.AppImage". Treat a token-less AppImage as x86_64.
|
||||
if !hasAnyToken(n, hostTokens) && !hasAnyToken(n, otherTokens) {
|
||||
return archName == "x86_64"
|
||||
}
|
||||
matched := hasAnyToken(n, hostTokens)
|
||||
if !matched {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -191,6 +191,30 @@ func TestInstallObsidian(t *testing.T) {
|
||||
if len(runCmdCalls) != 2 || runCmdCalls[0][0] != "cp" || runCmdCalls[1][0] != "chmod" {
|
||||
t.Errorf("expected cp and chmod calls, got %v", runCmdCalls)
|
||||
}
|
||||
|
||||
// Obsidian publishes the x86_64 AppImage without an arch token
|
||||
// (e.g. "Obsidian-1.12.7.AppImage"). It should still match on x86_64.
|
||||
fetchJSON = func(url string, v any) bool {
|
||||
rel := v.(*ghRelease)
|
||||
rel.Assets = []ghAsset{
|
||||
{Name: "Obsidian-1.12.7-arm64.AppImage", BrowserDownloadURL: "http://obs-arm64"},
|
||||
{Name: "Obsidian-1.12.7.AppImage", BrowserDownloadURL: "http://obs-default"},
|
||||
}
|
||||
return true
|
||||
}
|
||||
downloadedURL = ""
|
||||
archName = "x86_64"
|
||||
installObsidian("/tmp")
|
||||
if downloadedURL != "http://obs-default" {
|
||||
t.Errorf("expected token-less AppImage to be selected for x86_64, got %q", downloadedURL)
|
||||
}
|
||||
|
||||
downloadedURL = ""
|
||||
archName = "aarch64"
|
||||
installObsidian("/tmp")
|
||||
if downloadedURL != "http://obs-arm64" {
|
||||
t.Errorf("expected arm64 AppImage for aarch64, got %q", downloadedURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallMinikube(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user