diff --git a/datasetUtils/checkForNewVersion.go b/datasetUtils/checkForNewVersion.go index c2a1a0f..a987012 100644 --- a/datasetUtils/checkForNewVersion.go +++ b/datasetUtils/checkForNewVersion.go @@ -2,66 +2,92 @@ package datasetUtils import ( "bufio" - "io" "log" "net/http" "os" "runtime" "strconv" "strings" - + "encoding/json" version "github.com/mcuadros/go-version" + "fmt" ) var scanner = bufio.NewScanner(os.Stdin) -// check version of program, give hint to update -const DeployLocation = "https://gitlab.psi.ch/scicat/tools/raw/master/" + runtime.GOOS + "/" +var ( + GitHubAPI = "https://api.github.com/repos/paulscherrerinstitute/scicat-cli/releases/latest" + DeployLocation = "https://github.com/paulscherrerinstitute/scicat-cli/releases/download" +) -func CheckForNewVersion(client *http.Client, APP string, VERSION string, interactiveFlag bool) { - resp, err := client.Get(DeployLocation + APP + "Version.txt") +type Release struct { + TagName string `json:"tag_name"` +} + +func fetchLatestVersion(client *http.Client) (string, error) { + resp, err := client.Get(GitHubAPI) if err != nil { - log.Println("Can not find info about latest version for this program") - log.Printf("Error: %s\n", err) - return + return "", err } defer resp.Body.Close() + if resp.StatusCode != 200 { - log.Println("Can not find info about latest version for this program") - log.Printf("Error: Got %s fetching %s\n", resp.Status, DeployLocation + APP + "Version.txt") - return + return "", fmt.Errorf("got %s fetching %s", resp.Status, GitHubAPI) } - - body, err := io.ReadAll(resp.Body) + + var release Release + err = json.NewDecoder(resp.Body).Decode(&release) if err != nil { - log.Println("Can not read version file for this application") - return + return "", err } + + return strings.TrimSpace(release.TagName), nil +} - latestVersion := strings.TrimSpace(string(body)) +// Make sure the version number is stripped of the 'v' prefix. That's required for `strconv.Atoi` to work. +func generateDownloadURL(deployLocation, latestVersion, osName string) string { + if strings.ToLower(osName) == "windows" { + return fmt.Sprintf("%s/v%s/scicat-cli_.%s_%s_x86_64.zip", deployLocation, latestVersion, latestVersion, strings.Title(osName)) + } + return fmt.Sprintf("%s/v%s/scicat-cli_.%s_%s_x86_64.tar.gz", deployLocation, latestVersion, latestVersion, strings.Title(osName)) +} - majorLatest, err := strconv.Atoi(strings.Split(latestVersion, ".")[0]) +func CheckForNewVersion(client *http.Client, APP string, VERSION string, interactiveFlag bool) { + latestVersion, err := fetchLatestVersion(client) + if err != nil { + log.Printf("Can not find info about latest version for this program: %s\n", err) + return + } + + latestVersion = strings.TrimPrefix(latestVersion, "v") + _, err = strconv.Atoi(strings.Split(latestVersion, ".")[0]) if err != nil { log.Fatalf("Illegal latest version number:%v", latestVersion) } - majorCurrent, err := strconv.Atoi(strings.Split(VERSION, ".")[0]) + _, err = strconv.Atoi(strings.Split(VERSION, ".")[0]) if err != nil { log.Fatalf("Illegal version number:%v", VERSION) } log.Printf("Latest version: %s", latestVersion) - if majorLatest > majorCurrent { - log.Println("You must upgrade to a newer version") - log.Println("Current Version: ", VERSION) - log.Println("Latest Version: ", latestVersion) - log.Println("Use the following command to update:") - log.Println("curl -O " + DeployLocation + APP + ";chmod +x " + APP) - log.Fatalf("Execution stopped, please update program now.\n") - } else if version.Compare(latestVersion, VERSION, ">") { + + // Get the operating system name + osName := runtime.GOOS + + // Generate the download URL + downloadURL := generateDownloadURL(DeployLocation, latestVersion, osName) + + if version.Compare(latestVersion, VERSION, ">") { log.Println("You should upgrade to a newer version") log.Println("Current Version: ", VERSION) log.Println("Latest Version: ", latestVersion) - log.Println("Use the following command to update:") - log.Println("curl -O " + DeployLocation + APP + ";chmod +x " + APP) + log.Println("You can either download the file using the browser or use the following command:") + + if strings.ToLower(osName) == "windows" { + log.Printf("Browser: %s\nCommand: curl -L -O %s; unzip scicat-cli_.%s_%s_x86_64.zip; cd scicat-cli\n", downloadURL, downloadURL, latestVersion, strings.Title(osName)) + } else { + log.Printf("Browser: %s\nCommand: curl -L -O %s; tar xzf scicat-cli_.%s_%s_x86_64.tar.gz; cd scicat-cli; chmod +x %s\n", downloadURL, downloadURL, latestVersion, strings.Title(osName), APP) + } + if interactiveFlag { log.Print("Do you want to continue with current version (y/N) ? ") scanner.Scan() @@ -72,5 +98,5 @@ func CheckForNewVersion(client *http.Client, APP string, VERSION string, interac } } else { log.Println("Your version of this program is up-to-date") - } + } } diff --git a/datasetUtils/checkForNewVersion_test.go b/datasetUtils/checkForNewVersion_test.go new file mode 100644 index 0000000..4e227a8 --- /dev/null +++ b/datasetUtils/checkForNewVersion_test.go @@ -0,0 +1,133 @@ +package datasetUtils + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + "bytes" + "log" +) + +func TestFetchLatestVersion(t *testing.T) { + // Create a mock HTTP server + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Return a JSON response similar to the GitHub API + w.Write([]byte(`{"tag_name": "v1.0.0"}`)) + })) + defer server.Close() + + // Replace GitHubAPI with the URL of the mock server + oldGitHubAPI := GitHubAPI + GitHubAPI = server.URL + defer func() { GitHubAPI = oldGitHubAPI }() + + // Create a mock HTTP client + client := server.Client() + + // Call fetchLatestVersion + version, err := fetchLatestVersion(client) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Check the version number + if version != "v1.0.0" { + t.Errorf("Expected version v1.0.0, got %s", version) + } +} + +func TestGenerateDownloadURL(t *testing.T) { + deployLocation := "https://github.com/paulscherrerinstitute/scicat-cli/releases/download" + latestVersion := "0.1.0" + + testCases := []struct { + osName string + expectedURL string + }{ + { + osName: "Linux", + expectedURL: "https://github.com/paulscherrerinstitute/scicat-cli/releases/download/v0.1.0/scicat-cli_.0.1.0_Linux_x86_64.tar.gz", + }, + { + osName: "Windows", + expectedURL: "https://github.com/paulscherrerinstitute/scicat-cli/releases/download/v0.1.0/scicat-cli_.0.1.0_Windows_x86_64.zip", + }, + { + osName: "Darwin", + expectedURL: "https://github.com/paulscherrerinstitute/scicat-cli/releases/download/v0.1.0/scicat-cli_.0.1.0_Darwin_x86_64.tar.gz", + }, + } + + for _, testCase := range testCases { + actualURL := generateDownloadURL(deployLocation, latestVersion, testCase.osName) + + if actualURL != testCase.expectedURL { + t.Errorf("Expected URL to be %s, but got %s", testCase.expectedURL, actualURL) + } + } + } + +func TestCheckForNewVersion(t *testing.T) { + tests := []struct { + name string + currentVersion string + mockResponse string + expectedLog string + }{ + { + name: "New version available", + currentVersion: "0.9.0", + mockResponse: `{"tag_name": "v1.0.0"}`, + expectedLog: "You should upgrade to a newer version", + }, + { + name: "No new version available", + currentVersion: "1.0.0", + mockResponse: `{"tag_name": "v1.0.0"}`, + expectedLog: "Your version of this program is up-to-date", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create a mock HTTP server + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Return a JSON response similar to the GitHub API + w.Write([]byte(tt.mockResponse)) + })) + defer server.Close() + + // Replace GitHubAPI with the URL of the mock server + oldGitHubAPI := GitHubAPI + GitHubAPI = server.URL + defer func() { GitHubAPI = oldGitHubAPI }() + + // Create a mock HTTP client + client := server.Client() + + // Call CheckForNewVersion + CheckForNewVersion(client, "test", tt.currentVersion, false) + + // Check the log output + logOutput := getLogOutput() + if !strings.Contains(logOutput, tt.expectedLog) { + t.Errorf("Expected log message not found: %s", logOutput) + } + + // Clear the log buffer after each test + buf.Reset() + }) + } +} + +var buf bytes.Buffer + +func init() { + // Redirect the output of the logger to buf + log.SetOutput(&buf) +} + +func getLogOutput() string { + return buf.String() +}