Skip to content

Commit

Permalink
almost done
Browse files Browse the repository at this point in the history
  • Loading branch information
gerblesh committed Nov 29, 2024
1 parent d209efa commit 0de044d
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 69 deletions.
16 changes: 16 additions & 0 deletions checks/hardware.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,19 @@ func cpu() Info {
nil,
}
}

func RunHwChecks() error {
// (some hardware checks require dbus access)
conn, err := dbus.SystemBus()
if err != nil {
return err
}
defer conn.Close()
checkInfo := Hardware(conn)
for _, info := range checkInfo {
if info.Err != nil {
return fmt.Errorf("%s, returned error: %v", info.Name, info.Err)
}
}
return nil
}
15 changes: 3 additions & 12 deletions cmd/hw-check.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
package cmd

import (
"log"

"github.com/gerblesh/update-next/checks"
"github.com/godbus/dbus/v5"
"github.com/spf13/cobra"
"log"
)

func HwCheck(cmd *cobra.Command, args []string) {
// (some hardware checks require dbus access)
conn, err := dbus.SystemBus()
err := checks.RunHwChecks()
if err != nil {
log.Fatalf("Failed to connect to session bus: %v", err)
}
defer conn.Close()
checkInfo := checks.Hardware(conn)
for _, info := range checkInfo {
if info.Err != nil {
log.Fatalf("Hardware checks failed for %s, returned error: %v", info.Name, info.Err)
}
log.Fatalf("Hardware checks failed: %v", err)
}
log.Println("Hardware checks passed")
}
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ var (

waitCmd = &cobra.Command{
Use: "wait",
Short: "Wait for a condition or time period",
Long: "This command simulates waiting for some event or process to complete.",
Short: "Waits for ostree sysroot to unlock",
Run: Wait,
}

Expand Down Expand Up @@ -44,4 +43,5 @@ func init() {
rootCmd.AddCommand(waitCmd)
rootCmd.AddCommand(updateCheckCmd)
rootCmd.AddCommand(hardwareCheckCmd)
rootCmd.Flags().BoolP("hw-check", "c", false, "run hardware check before running updates")
}
142 changes: 119 additions & 23 deletions cmd/update.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,150 @@
package cmd

import (
"fmt"
"log"
"os/exec"
"strings"

"github.com/gerblesh/update-next/checks"
"github.com/gerblesh/update-next/drv"
"github.com/gerblesh/update-next/lib"
"github.com/godbus/dbus/v5"
// "github.com/schollz/progressbar/v3"
"github.com/spf13/cobra"
"log"
)

func Update(cmd *cobra.Command, args []string) {
type Failure struct {
Err error
Output string
}

// (some hardware checks require dbus access)
conn, err := dbus.SystemBus()
func Update(cmd *cobra.Command, args []string) {
hwCheck, err := cmd.Flags().GetBool("hw-check")
if err != nil {
log.Fatalf("Failed to connect to session bus: %v", err)
log.Fatalf("Failed to get hw-check flag: %v", err)
}
defer conn.Close()
checkInfo := checks.Hardware(conn)
for _, info := range checkInfo {
if info.Err != nil {
log.Fatalf("Hardware checks failed for %s, returned error: %v", info.Name, info.Err)

if hwCheck {
err := checks.RunHwChecks()
if err != nil {
log.Fatalf("Hardware checks failed: %v", err)
}
log.Println("Hardware checks passed")
}
log.Println("Hardware checks passed")

users, err := lib.ListUsers()
if err != nil {
log.Fatalf("Failed to list users")
}
// Check if bootc update is available
updateAvailable, err := drv.CheckForUpdate()
bootcUpdate := 0
if updateAvailable {
bootcUpdate = 1
}

// Check if brew is installed
brewUid, brewErr := drv.GetBrewUID()
brewUpdate := 0
if brewErr == nil {
brewUpdate = 1
}

totalUpdates := brewUpdate + bootcUpdate + 1 + len(users) + 1 + len(users) // Bootc + Brew + Flatpak (users + root) + Distrobox (users + root)
currentUpdate := 0
if err != nil {
log.Fatalf("Failed to check for image updates: %v", err)
}
log.Printf("update available: %v", updateAvailable)
failures := make(map[string]Failure)

if updateAvailable {
err = drv.BootcUpdate()
currentUpdate++
log.Printf("[%d/%d] Updating System (Bootc)", currentUpdate, totalUpdates)
out, err := drv.BootcUpdate()
if err != nil {
log.Fatalf("Failed to update system: %v", err)
failures["Bootc"] = Failure{
err,
string(out),
}
}
}
err = drv.BrewUpdate()
if err != nil {
log.Fatalf("Failed to update brew: %v", err)

if brewUpdate == 1 {
currentUpdate++
log.Printf("[%d/%d] Updating CLI Apps (Brew)", currentUpdate, totalUpdates)
out, err := drv.BrewUpdate(brewUid)
if err != nil {
failures["Brew"] = Failure{
err,
string(out),
}
}
}

users, err := lib.ListUsers()
// Run flatpak updates
currentUpdate++
log.Printf("[%d/%d] Updating System Apps (Flatpak)", currentUpdate, totalUpdates)
flatpakCmd := exec.Command("/usr/bin/flatpak", "update", "-y")
out, err := flatpakCmd.CombinedOutput()
if err != nil {
log.Fatalf("ERROR: %v", err)
failures["Flatpak"] = Failure{
err,
string(out),
}
}
err = drv.FlatpakUpdate(users)
for _, user := range users {
currentUpdate++
log.Printf("[%d/%d] Updating User Apps for user: %s (Flatpak)", currentUpdate, totalUpdates, user.Name)
out, err := lib.RunUID(user.UID, []string{"/usr/bin/flatpak", "update", "-y"}, nil)
if err != nil {
failures[fmt.Sprintf("Flatpak User: %s", user.Name)] = Failure{
err,
string(out),
}
}
}

// Run distrobox updates
log.Printf("[%d/%d] Updating System Distroboxes", currentUpdate, totalUpdates)
currentUpdate++
// distrobox doesn't support sudo, run with systemd-run
out, err = lib.RunUID(0, []string{"/usr/bin/distrobox", "upgrade", "-a"}, nil)
if err != nil {
log.Fatalf("Failed to update flatpak: %v", err)
failures["Distrobox"] = Failure{
err,
string(out),
}
}
for _, user := range users {
currentUpdate++
log.Printf("[%d/%d] Updating User Distroboxes: %s", currentUpdate, totalUpdates, user.Name)
out, err := lib.RunUID(user.UID, []string{"/usr/bin/distrobox", "upgrade", "-a"}, nil)
if err != nil {
failures[fmt.Sprintf("Distrobox User: %s", user.Name)] = Failure{
err,
string(out),
}
}
}

if len(failures) > 0 {
failedSystemsList := make([]string, 0, len(failures))
for systemName := range failures {
failedSystemsList = append(failedSystemsList, systemName)
}
failedSystemsStr := strings.Join(failedSystemsList, ", ")
lib.Notify("Updates failed", fmt.Sprintf("ublue-upd failed to update: %s", failedSystemsStr))

log.Printf("Update Failures:")
for name, fail := range failures {
indentedOutput := "\t | "
lines := strings.Split(fail.Output, "\n")
for i, line := range lines {
if i > 0 {
indentedOutput += "\n\t | "
}
indentedOutput += line
}
log.Printf("---> %s \n\t | Failure error: %v \n\t | Command Output: \n%s", name, fail.Err, indentedOutput)
}
}
}
8 changes: 4 additions & 4 deletions drv/bootc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"strings"
)

func BootcUpdate() error {
func BootcUpdate() ([]byte, error) {
cmd := exec.Command("/usr/bin/bootc", "upgrade")
err := cmd.Run()
out, err := cmd.CombinedOutput()
if err != nil {
return err
return out, err
}
return nil
return out, nil
}

func CheckForUpdate() (bool, error) {
Expand Down
18 changes: 7 additions & 11 deletions drv/brew.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var (
brewPath = fmt.Sprintf("%s/bin/brew", brewPrefix)
)

func getBrewUID() (int, error) {
func GetBrewUID() (int, error) {
inf, err := os.Stat(brewPrefix)
if err != nil {
log.Printf("Unable to stat: %v, got error: %v", brewPrefix, err)
Expand All @@ -32,25 +32,21 @@ func getBrewUID() (int, error) {
return int(stat.Uid), nil
}

func BrewUpdate() error {
uid, err := getBrewUID()
if err != nil {
return err
}
func BrewUpdate(uid int) ([]byte, error) {
env := map[string]string{
"HOMEBREW_PREFIX": brewPrefix,
"HOMEBREW_REPOSITORY": brewRepo,
"HOMEBREW_CELLAR": brewCellar,
}
_, err = lib.RunUID(uid, []string{brewPath, "update"}, env)
out, err := lib.RunUID(uid, []string{brewPath, "update"}, env)
if err != nil {
return err
return out, err
}

_, err = lib.RunUID(uid, []string{brewPath, "upgrade"}, env)
out, err = lib.RunUID(uid, []string{brewPath, "upgrade"}, env)
if err != nil {
return err
return out, err
}

return nil
return out, nil
}
15 changes: 0 additions & 15 deletions drv/flatpak.go

This file was deleted.

16 changes: 15 additions & 1 deletion lib/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ func RunUID(uid int, command []string, env map[string]string) ([]byte, error) {
// Just fork systemd-run, using the systemd API gave me a massive headache
cmdArgs := []string{
"/usr/bin/systemd-run",
"--user",
"--machine",
fmt.Sprintf("%d@", uid),
"--pipe",
"--quiet",
}
if uid != 0 {
cmdArgs = append(cmdArgs, "--user")
}
cmdArgs = append(cmdArgs, command...)

cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
Expand Down Expand Up @@ -67,3 +69,15 @@ func ListUsers() ([]User, error) {
}
return users, nil
}

func Notify(summary string, body string) error {
users, err := ListUsers()
if err != nil {
return err
}
for _, user := range users {
// we don't care if these exit
RunUID(user.UID, []string{"/usr/bin/notify-send", "--app-name", "ublue-upd", summary, body}, nil)
}
return nil
}
14 changes: 13 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package main

import "github.com/gerblesh/update-next/cmd"
import (
"github.com/gerblesh/update-next/cmd"
"log"
"os/user"
)

func main() {
log.SetFlags(0)
currentUser, err := user.Current()
if err != nil {
log.Fatalf("Error fetching current user: %v", err)
}
if currentUser.Uid != "0" {
log.Fatalf("ublue-upd needs to be invoked as root.")
}
cmd.Execute()
}

0 comments on commit 0de044d

Please sign in to comment.