-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eb94b5b
commit 188068c
Showing
6 changed files
with
495 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# CLI Build | ||
/runtipi-cli-go | ||
/runtipi-cli-go.bak | ||
|
||
# CLI Created Files | ||
/apps | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path" | ||
|
||
"github.com/Delta456/box-cli-maker" | ||
"github.com/fatih/color" | ||
"github.com/spf13/cobra" | ||
"github.com/steveiliop56/runtipi-cli-go/internal/env" | ||
"github.com/steveiliop56/runtipi-cli-go/internal/release" | ||
"github.com/steveiliop56/runtipi-cli-go/internal/spinner" | ||
"github.com/steveiliop56/runtipi-cli-go/internal/utils" | ||
) | ||
|
||
func init() { | ||
updateCmd.Flags().BoolVar(&noPermissions, "no-permissions", false, "Skip setting permissions.") | ||
updateCmd.Flags().StringVar(&envFile, "env-file", "", "Path to custom .env file") | ||
rootCmd.AddCommand(updateCmd) | ||
} | ||
|
||
var updateCmd = &cobra.Command{ | ||
Use: "update", | ||
Short: "Update to the latest version", | ||
Long: "Use this command to update your runtipi instance to the latest version", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
// Checks args | ||
if len(args) == 0 { | ||
utils.PrintError("Please provide a version to update too, you can use latest, nightly or a specific tag") | ||
os.Exit(1) | ||
} | ||
|
||
// Define colors | ||
blue := color.New(color.FgBlue).SprintFunc() | ||
|
||
// Root folder | ||
rootFolder, osErr := os.Getwd() | ||
|
||
if osErr != nil { | ||
utils.PrintError("Faild to get root folder") | ||
fmt.Printf("Error: %s\n", osErr) | ||
os.Exit(1) | ||
} | ||
|
||
// Define paths | ||
cliPath := path.Join(rootFolder, "runtipi-cli-go") | ||
|
||
// Start spinner | ||
spinner.SetMessage("Updating runtipi...") | ||
spinner.Start() | ||
|
||
// Get versions | ||
version := args[0] | ||
currentVersion, currentVersionErr := env.GetEnvValue("TIPI_VERSION") | ||
if currentVersionErr != nil { | ||
utils.PrintError("Failed to get current environment version") | ||
fmt.Printf("Error: %s\n", currentVersionErr) | ||
os.Exit(1) | ||
} | ||
|
||
spinner.PrintUpdate("Updating from " + blue(currentVersion) + " to " + blue(version)) | ||
|
||
// Validate | ||
spinner.SetMessage("Validating version") | ||
|
||
isValid, validateErr := release.ValidateVersion(version) | ||
|
||
if validateErr != nil { | ||
spinner.Fail("Error in validating version") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", validateErr) | ||
os.Exit(1) | ||
} | ||
|
||
if !isValid { | ||
spinner.Fail("Version is not valid") | ||
spinner.Stop() | ||
os.Exit(1) | ||
} | ||
|
||
spinner.Succeed("Version is valid") | ||
|
||
// Compare versions | ||
spinner.SetMessage("Comparing versions...") | ||
|
||
versionToUpdate := "" | ||
|
||
if version == "latest" { | ||
latestVersion, latestVersionErr := release.GetLatestVersion() | ||
if latestVersionErr != nil { | ||
spinner.Fail("Failed to get latest version") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", latestVersionErr) | ||
os.Exit(1) | ||
} | ||
versionToUpdate = latestVersion | ||
} else if version == "nightly" { | ||
spinner.Fail("Nightly currently not supported") | ||
spinner.Stop() | ||
os.Exit(1) | ||
} else { | ||
if currentVersion != "nightly" { | ||
isMajor, isMajorErr := release.IsMajorBump(version, currentVersion) | ||
|
||
if isMajorErr != nil { | ||
spinner.Fail("Failed to compare versions") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", isMajorErr) | ||
os.Exit(1) | ||
} | ||
|
||
if isMajor { | ||
spinner.Fail("You are trying to update to a new major version. Please update manually using the update instructions on the website. https://runtipi.io/docs/reference/breaking-updates") | ||
spinner.Stop() | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
versionToUpdate = version | ||
} | ||
|
||
spinner.Succeed("Versions compared") | ||
|
||
// Backup CLI | ||
spinner.SetMessage("Backing up current CLI") | ||
|
||
backupErr := release.BackupCurrentCLI() | ||
|
||
if backupErr != nil { | ||
spinner.Fail("Failed to backup current CLI, no modification were made") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", backupErr) | ||
os.Exit(1) | ||
} | ||
|
||
spinner.Succeed("CLI backed up") | ||
|
||
// Download latest CLI | ||
spinner.SetMessage("Downloading latest CLI") | ||
|
||
downloadErr := release.DownloadLatestCLI(versionToUpdate) | ||
|
||
if downloadErr != nil { | ||
spinner.Fail("Failed to download latest CLI, please copy the runtipi-cli-go.bak file to runtipi-cli-go and try again") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", downloadErr) | ||
os.Exit(1) | ||
} | ||
|
||
spinner.Succeed("New CLI downloaded successfully") | ||
|
||
// Start new CLI | ||
spinner.SetMessage("Starting new CLI") | ||
|
||
cliArgs := []string{"start"} | ||
|
||
if envFile != "" { | ||
cliArgs = append(cliArgs, "--env-file") | ||
cliArgs = append(cliArgs, envFile) | ||
} | ||
|
||
if noPermissions { | ||
cliArgs = append(cliArgs, "--no-permissions") | ||
} | ||
|
||
_, startErr := exec.Command(cliPath, cliArgs...).Output() | ||
|
||
if startErr != nil { | ||
spinner.Fail("Failed to start the new CLI, please copy the runtipi-cli-go.bak file to runtipi-cli-go and try again") | ||
spinner.Stop() | ||
fmt.Printf("Error: %s\n", downloadErr) | ||
os.Exit(1) | ||
} | ||
|
||
spinner.Succeed("New CLI started successfully, you are good to go") | ||
|
||
// Succeed | ||
spinner.Stop() | ||
|
||
internalIp, _ := env.GetEnvValue("INTERNAL_IP") | ||
nginxPort, _ := env.GetEnvValue("NGINX_PORT") | ||
|
||
boxMessage := "Visit http://" + internalIp + ":" + nginxPort + " to access the dashboard\n\nFind documentation and guides at: https://runtipi.io\n\nTipi is entirely written in TypeScript and we are looking for contributors!" | ||
|
||
Box := box.New(box.Config{Py: 2, Px: 2, Type: "Double", Color: "Green", TitlePos: "Top", ContentAlign: "Center"}) | ||
Box.Print("Runtipi updated successfully 🎉", boxMessage) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package release | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/steveiliop56/runtipi-cli-go/internal/system" | ||
) | ||
|
||
type GithubRelease struct { | ||
TagName string `json:"tag_name"` | ||
Status string `json:"status"` | ||
} | ||
|
||
func IsMajorBump(newVersion string, currentVersion string) (bool, error) { | ||
newVersionMajor := strings.Split(strings.Replace(newVersion, "v", "", 1), ".")[0] | ||
currentVersionMajor := strings.Split(strings.Replace(currentVersion, "v", "", 1), ".")[0] | ||
|
||
newVersionMajorInt, newVersionMajorIntErr := strconv.ParseInt(newVersionMajor, 10, 64) | ||
|
||
if newVersionMajorIntErr != nil { | ||
return false, newVersionMajorIntErr | ||
} | ||
|
||
currentVersionMajorInt, currentVersionMajorIntErr := strconv.ParseInt(currentVersionMajor, 10, 64) | ||
|
||
if currentVersionMajorIntErr != nil { | ||
return false, currentVersionMajorIntErr | ||
} | ||
|
||
if newVersionMajorInt > currentVersionMajorInt { | ||
return true, nil | ||
} | ||
|
||
return false, nil | ||
} | ||
|
||
func GetLatestVersion() (string, error) { | ||
apiUrl := "https://api.github.com/repos/steveiliop56/runtipi-cli-go/releases/latest" | ||
|
||
response, requestErr := http.Get(apiUrl) | ||
|
||
if requestErr != nil { | ||
return "", requestErr | ||
} | ||
|
||
defer response.Body.Close() | ||
|
||
release := new(GithubRelease) | ||
|
||
jsonErr := json.NewDecoder(response.Body).Decode(&release) | ||
|
||
if jsonErr != nil { | ||
return "", jsonErr | ||
} | ||
|
||
return release.TagName, nil | ||
} | ||
|
||
func ValidateVersion(version string) (bool, error) { | ||
apiUrl := "https://api.github.com/repos/steveiliop56/runtipi-cli-go/releases/tags/" + version | ||
|
||
response, requestErr := http.Get(apiUrl) | ||
|
||
if requestErr != nil { | ||
return false, requestErr | ||
} | ||
|
||
defer response.Body.Close() | ||
|
||
release := new(GithubRelease) | ||
|
||
jsonErr := json.NewDecoder(response.Body).Decode(&release) | ||
|
||
if jsonErr != nil { | ||
return false, jsonErr | ||
} | ||
|
||
if release.Status == "404" { | ||
return false, nil | ||
} | ||
|
||
return true, nil | ||
} | ||
|
||
func DownloadLatestCLI(version string) (error) { | ||
arch := system.GetArch() | ||
assetUrl := fmt.Sprintf("https://github.com/steveiliop56/runtipi-cli-go/releases/download/%s/runtipi-cli-go-%s", version, arch) | ||
|
||
rootFolder, osErr := os.Getwd() | ||
|
||
if osErr != nil { | ||
return osErr | ||
} | ||
|
||
cliPath := path.Join(rootFolder, "runtipi-cli-go") | ||
|
||
os.Remove(cliPath) | ||
|
||
create, createErr := os.Create(cliPath) | ||
|
||
if createErr != nil { | ||
return createErr | ||
} | ||
|
||
defer create.Close() | ||
|
||
response, requestErr := http.Get(assetUrl) | ||
|
||
if requestErr != nil { | ||
return requestErr | ||
} | ||
|
||
defer response.Body.Close() | ||
|
||
_, writeErr := io.Copy(create, response.Body) | ||
|
||
if writeErr != nil { | ||
return writeErr | ||
} | ||
|
||
_, chmodErr := exec.Command("chmod", "+x", cliPath).Output() | ||
|
||
if chmodErr != nil { | ||
return chmodErr | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func BackupCurrentCLI() (error) { | ||
rootFolder, osErr := os.Getwd() | ||
|
||
if osErr != nil { | ||
return osErr | ||
} | ||
|
||
cliPath := path.Join(rootFolder, "runtipi-cli-go") | ||
cliBackupPath := path.Join(rootFolder, "runtipi-cli-go.bak") | ||
|
||
_, copyErr := exec.Command("cp", cliPath, cliBackupPath).Output() | ||
|
||
if copyErr != nil { | ||
return copyErr | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.