Skip to content

Commit

Permalink
Implement Atmos Version Check Configuration (#844)
Browse files Browse the repository at this point in the history
* DEV-2815

* version

* docs update

* Update website/docs/cli/commands/help.mdx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update website/docs/cli/commands/version.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* Update pkg/config/cache.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* Update website/docs/cli/commands/version.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* Update website/docs/cli/commands/version.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* help wording fix as per coderabbit suggestion

* more update frequencies and respective update to the dox

* help wording update

* reviewchanges

* versiondoc

* Update website/docs/cli/commands/help.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* Update website/docs/cli/commands/version.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* Update website/docs/cli/commands/version.mdx

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>

* updates

* atmos.yaml

* updates

---------

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: aknysh <[email protected]>
  • Loading branch information
4 people authored Dec 15, 2024
1 parent e9a610e commit b205a0d
Show file tree
Hide file tree
Showing 18 changed files with 330 additions and 59 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@
# Nix
.envrc
.direnv/

.atmos/cache.yaml
6 changes: 6 additions & 0 deletions atmos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,9 @@ settings:
# If the source and destination lists have the same length, all items in the destination lists are
# deep-merged with all items in the source list.
list_merge_strategy: replace

version:
check:
enabled: true
timeout: 1000 # ms
frequency: 1h
63 changes: 53 additions & 10 deletions cmd/cmd_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path"
"strings"
"time"

"github.com/fatih/color"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -428,18 +429,60 @@ func printMessageForMissingAtmosConfig(cliConfig schema.CliConfiguration) {
u.PrintMessage("https://atmos.tools/quick-start\n")
}

// customHelpMessageToUpgradeToAtmosLatestRelease adds Atmos version info at the end of each help commnad
func customHelpMessageToUpgradeToAtmosLatestRelease(cmd *cobra.Command, args []string) {
originalHelpFunc(cmd, args)
// Check for the latest Atmos release on GitHub
// CheckForAtmosUpdateAndPrintMessage checks if a version update is needed and prints a message if a newer version is found.
// It loads the cache, decides if it's time to check for updates, compares the current version to the latest available release,
// and if newer, prints the update message. It also updates the cache's timestamp after printing.
func CheckForAtmosUpdateAndPrintMessage(cliConfig schema.CliConfiguration) {
// If version checking is disabled in the configuration, do nothing
if !cliConfig.Version.Check.Enabled {
return
}

// Load the cache
cacheCfg, err := cfg.LoadCache()
if err != nil {
u.LogWarning(cliConfig, fmt.Sprintf("Could not load cache: %s", err))
return
}

// Determine if it's time to check for updates based on frequency and last_checked
if !cfg.ShouldCheckForUpdates(cacheCfg.LastChecked, cliConfig.Version.Check.Frequency) {
// Not due for another check yet, so return without printing anything
return
}

// Get the latest Atmos release from GitHub
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestRelease)
}
if err != nil {
u.LogWarning(cliConfig, fmt.Sprintf("Failed to retrieve latest Atmos release info: %s", err))
return
}

if latestReleaseTag == "" {
u.LogWarning(cliConfig, "No release information available")
return
}

// Trim "v" prefix to compare versions
latestVersion := strings.TrimPrefix(latestReleaseTag, "v")
currentVersion := strings.TrimPrefix(version.Version, "v")

// If the versions differ, print the update message
if latestVersion != currentVersion {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestVersion)
}

// Update the cache to mark the current timestamp
cacheCfg.LastChecked = time.Now().Unix()
if saveErr := cfg.SaveCache(cacheCfg); saveErr != nil {
u.LogWarning(cliConfig, fmt.Sprintf("Unable to save cache: %s", saveErr))

}
}

func customHelpMessageToUpgradeToAtmosLatestRelease(cmd *cobra.Command, args []string) {
originalHelpFunc(cmd, args)
CheckForAtmosUpdateAndPrintMessage(cliConfig)
}

// Check Atmos is version command
Expand Down
15 changes: 2 additions & 13 deletions cmd/helmfile.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package cmd

import (
"strings"

"github.com/samber/lo"
"github.com/spf13/cobra"

e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/cloudposse/atmos/pkg/version"
)

// helmfileCmd represents the base command for all helmfile sub-commands
Expand All @@ -34,18 +31,10 @@ var helmfileCmd = &cobra.Command{
if err != nil {
u.LogErrorAndExit(schema.CliConfiguration{}, err)
}

// Check for the latest Atmos release on GitHub and print update message
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestRelease)
}
}
// Exit on help
if info.NeedHelp {
// Check for the latest Atmos release on GitHub and print update message
CheckForAtmosUpdateAndPrintMessage(cliConfig)
return
}
// Check Atmos configuration
Expand Down
30 changes: 16 additions & 14 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
u "github.com/cloudposse/atmos/pkg/utils"
)

var cliConfig schema.CliConfiguration

// originalHelpFunc holds Cobra's original help function to avoid recursion.
var originalHelpFunc func(*cobra.Command, []string)

Expand Down Expand Up @@ -72,14 +74,6 @@ func Execute() error {
Flags: cc.Bold,
})

// Save the original help function to prevent infinite recursion when overriding it.
// This allows us to call the original help functionality within our custom help function.
originalHelpFunc = RootCmd.HelpFunc()

// Override the help function with a custom one that adds an upgrade message after displaying help.
// This custom help function will call the original help function and then display the bordered message.
RootCmd.SetHelpFunc(customHelpMessageToUpgradeToAtmosLatestRelease)

// Check if the `help` flag is passed and print a styled Atmos logo to the terminal before printing the help
err := RootCmd.ParseFlags(os.Args)
if err != nil && errors.Is(err, pflag.ErrHelp) {
Expand All @@ -89,21 +83,29 @@ func Execute() error {
u.LogErrorAndExit(schema.CliConfiguration{}, err)
}
}

// InitCliConfig finds and merges CLI configurations in the following order:
// system dir, home dir, current dir, ENV vars, command-line arguments
// Here we need the custom commands from the config
cliConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)
if err != nil && !errors.Is(err, cfg.NotFound) {
var initErr error
cliConfig, initErr = cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)
if initErr != nil && !errors.Is(initErr, cfg.NotFound) {
if isVersionCommand() {
u.LogTrace(schema.CliConfiguration{}, fmt.Sprintf("warning: CLI configuration 'atmos.yaml' file not found. Error: %s", err))
u.LogTrace(schema.CliConfiguration{}, fmt.Sprintf("warning: CLI configuration 'atmos.yaml' file not found. Error: %s", initErr))
} else {
u.LogErrorAndExit(schema.CliConfiguration{}, err)
u.LogErrorAndExit(schema.CliConfiguration{}, initErr)
}
}

// Save the original help function to prevent infinite recursion when overriding it.
// This allows us to call the original help functionality within our custom help function.
originalHelpFunc = RootCmd.HelpFunc()

// Override the help function with a custom one that adds an upgrade message after displaying help.
// This custom help function will call the original help function and then display the bordered message.
RootCmd.SetHelpFunc(customHelpMessageToUpgradeToAtmosLatestRelease)

// If CLI configuration was found, process its custom commands and command aliases
if err == nil {
if initErr == nil {
err = processCustomCommands(cliConfig, cliConfig.Commands, RootCmd, true)
if err != nil {
u.LogErrorAndExit(schema.CliConfiguration{}, err)
Expand Down
15 changes: 3 additions & 12 deletions cmd/terraform.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package cmd

import (
"strings"

"github.com/samber/lo"
"github.com/spf13/cobra"

e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/cloudposse/atmos/pkg/version"
)

// terraformCmd represents the base command for all terraform sub-commands
Expand All @@ -35,17 +32,11 @@ var terraformCmd = &cobra.Command{
if err != nil {
u.LogErrorAndExit(schema.CliConfiguration{}, err)
}
// Check for the latest Atmos release on GitHub and print update message
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestRelease)
}
}

// Exit on help
if info.NeedHelp {
// Check for the latest Atmos release on GitHub and print update message
CheckForAtmosUpdateAndPrintMessage(cliConfig)
return
}
// Check Atmos configuration
Expand Down
31 changes: 24 additions & 7 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/cloudposse/atmos/pkg/version"
)

var checkFlag bool

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the CLI version",
Expand All @@ -29,18 +31,33 @@ var versionCmd = &cobra.Command{
u.PrintMessage(fmt.Sprintf("\U0001F47D Atmos %s on %s/%s", version.Version, runtime.GOOS, runtime.GOARCH))
fmt.Println()

// Check for the latest Atmos release on GitHub
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestRelease)
if checkFlag {
// Check for the latest Atmos release on GitHub
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
if err != nil {
u.LogWarning(schema.CliConfiguration{}, fmt.Sprintf("Failed to check for updates: %v", err))
return
}
if latestReleaseTag == "" {
u.LogWarning(schema.CliConfiguration{}, "No release information available")
return
}
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
u.PrintMessageToUpgradeToAtmosLatestRelease(latestRelease)
}
}
return
}

// Check for the cache and print update message
CheckForAtmosUpdateAndPrintMessage(cliConfig)
},
}

func init() {
versionCmd.Flags().BoolVarP(&checkFlag, "check", "c", false, "Run additional checks after displaying version info")
RootCmd.AddCommand(versionCmd)
}
2 changes: 1 addition & 1 deletion examples/quick-start-advanced/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ARG GEODESIC_OS=debian
# https://atmos.tools/
# https://github.com/cloudposse/atmos
# https://github.com/cloudposse/atmos/releases
ARG ATMOS_VERSION=1.122.0
ARG ATMOS_VERSION=1.127.0

# Terraform: https://github.com/hashicorp/terraform/releases
ARG TF_VERSION=1.5.7
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/elewis787/boa v0.1.2
github.com/fatih/color v1.18.0
github.com/go-git/go-git/v5 v5.12.0
github.com/gofrs/flock v0.12.1
github.com/google/go-containerregistry v0.20.2
github.com/google/go-github/v59 v59.0.0
github.com/google/uuid v1.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down
Loading

0 comments on commit b205a0d

Please sign in to comment.