github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/task/version_checker.go (about)

     1  package task
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  	"log"
     8  	"net/url"
     9  	"time"
    10  
    11  	"github.com/go-git/go-git/v5/plumbing/transport/http"
    12  	"github.com/turbot/steampipe/pkg/utils"
    13  	"github.com/turbot/steampipe/pkg/version"
    14  )
    15  
    16  // the current version of the Steampipe CLI application
    17  var currentVersion = version.SteampipeVersion.String()
    18  
    19  type CLIVersionCheckResponse struct {
    20  	NewVersion   string    `json:"latest_version,omitempty"` // `json:"current_version"`
    21  	DownloadURL  string    `json:"download_url,omitempty"`   // `json:"download_url"`
    22  	ChangelogURL string    `json:"html,omitempty"`           // `json:"changelog_url"`
    23  	Alerts       []*string `json:"alerts,omitempty"`
    24  }
    25  
    26  // VersionChecker :: the version checker struct composition container.
    27  // This MUST not be instantiated manually. Use `CreateVersionChecker` instead
    28  type versionChecker struct {
    29  	checkResult *CLIVersionCheckResponse // a channel to store the HTTP response
    30  	signature   string                   // flags whether update check should be done
    31  }
    32  
    33  // get the latest available version of the CLI
    34  func fetchAvailableCLIVersion(ctx context.Context, installationId string) (*CLIVersionCheckResponse, error) {
    35  	v := new(versionChecker)
    36  	v.signature = installationId
    37  	err := v.doCheckRequest(ctx)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	return v.checkResult, nil
    42  }
    43  
    44  // contact the Turbot Artifacts Server and retrieve the latest released version
    45  func (c *versionChecker) doCheckRequest(ctx context.Context) error {
    46  	payload := utils.BuildRequestPayload(c.signature, map[string]interface{}{})
    47  	sendRequestTo := c.versionCheckURL()
    48  	timeout := 5 * time.Second
    49  
    50  	ctx, cancel := context.WithTimeout(ctx, timeout)
    51  	defer cancel()
    52  
    53  	resp, err := utils.SendRequest(ctx, c.signature, "POST", sendRequestTo, payload)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	bodyBytes, err := io.ReadAll(resp.Body)
    58  	if err != nil {
    59  		log.Fatal(err)
    60  	}
    61  	bodyString := string(bodyBytes)
    62  	defer resp.Body.Close()
    63  
    64  	if resp.StatusCode == 204 {
    65  		return nil
    66  	}
    67  
    68  	if resp.StatusCode != 200 {
    69  		log.Printf("[TRACE] Unknown response during version check: %d\n", resp.StatusCode)
    70  		return http.NewErr(resp)
    71  	}
    72  
    73  	c.checkResult = c.decodeResult(bodyString)
    74  	return nil
    75  }
    76  
    77  func (c *versionChecker) decodeResult(body string) *CLIVersionCheckResponse {
    78  	var result CLIVersionCheckResponse
    79  
    80  	if err := json.Unmarshal([]byte(body), &result); err != nil {
    81  		return nil
    82  	}
    83  	return &result
    84  }
    85  
    86  func (c *versionChecker) versionCheckURL() url.URL {
    87  	var u url.URL
    88  	//https://hub.steampipe.io/api/cli/version/latest
    89  	u.Scheme = "https"
    90  	u.Host = "hub.steampipe.io"
    91  	u.Path = "api/cli/version/latest"
    92  	return u
    93  }