diff --git a/.gitignore b/.gitignore index f231eff31..7eeb05d79 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ # Nix .envrc .direnv/ + +.atmos/cache.yaml diff --git a/atmos.yaml b/atmos.yaml index adfd5176b..e9793b62f 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -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 diff --git a/cmd/cmd_utils.go b/cmd/cmd_utils.go index 3d55bf630..149969cf6 100644 --- a/cmd/cmd_utils.go +++ b/cmd/cmd_utils.go @@ -7,6 +7,7 @@ import ( "os" "path" "strings" + "time" "github.com/fatih/color" "github.com/spf13/cobra" @@ -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 diff --git a/cmd/helmfile.go b/cmd/helmfile.go index ae7280fe7..d2236e835 100644 --- a/cmd/helmfile.go +++ b/cmd/helmfile.go @@ -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 @@ -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 diff --git a/cmd/root.go b/cmd/root.go index 0027776c1..c7b043a3f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -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) @@ -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) { @@ -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) diff --git a/cmd/terraform.go b/cmd/terraform.go index 3b5ec3783..586e79d22 100644 --- a/cmd/terraform.go +++ b/cmd/terraform.go @@ -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 @@ -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 diff --git a/cmd/version.go b/cmd/version.go index 5146f4ff3..c865d81d0 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -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", @@ -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) } diff --git a/examples/quick-start-advanced/Dockerfile b/examples/quick-start-advanced/Dockerfile index 8ad376f7e..895f09c56 100644 --- a/examples/quick-start-advanced/Dockerfile +++ b/examples/quick-start-advanced/Dockerfile @@ -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 diff --git a/go.mod b/go.mod index ef51bcbdf..1c01ef148 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index f557e9bc6..90b091ecb 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/pkg/config/cache.go b/pkg/config/cache.go new file mode 100644 index 000000000..6833e67b5 --- /dev/null +++ b/pkg/config/cache.go @@ -0,0 +1,164 @@ +package config + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/gofrs/flock" + "github.com/pkg/errors" + "github.com/spf13/viper" + + "github.com/cloudposse/atmos/pkg/schema" + u "github.com/cloudposse/atmos/pkg/utils" +) + +type CacheConfig struct { + LastChecked int64 `mapstructure:"last_checked"` +} + +func GetCacheFilePath() (string, error) { + xdgCacheHome := os.Getenv("XDG_CACHE_HOME") + var cacheDir string + if xdgCacheHome == "" { + cacheDir = filepath.Join(".", ".atmos") + } else { + cacheDir = filepath.Join(xdgCacheHome, "atmos") + } + + if err := os.MkdirAll(cacheDir, 0755); err != nil { + return "", errors.Wrap(err, "error creating cache directory") + } + + return filepath.Join(cacheDir, "cache.yaml"), nil +} + +func withCacheFileLock(cacheFile string, fn func() error) error { + lock := flock.New(cacheFile) + err := lock.Lock() + if err != nil { + return errors.Wrap(err, "error acquiring file lock") + } + defer lock.Unlock() + return fn() +} + +func LoadCache() (CacheConfig, error) { + cacheFile, err := GetCacheFilePath() + if err != nil { + return CacheConfig{}, err + } + + var cfg CacheConfig + if _, err := os.Stat(cacheFile); os.IsNotExist(err) { + // No file yet, return default + return cfg, nil + } + + v := viper.New() + v.SetConfigFile(cacheFile) + if err := v.ReadInConfig(); err != nil { + return cfg, errors.Wrap(err, "failed to read cache file") + } + if err := v.Unmarshal(&cfg); err != nil { + return cfg, errors.Wrap(err, "failed to unmarshal cache file") + } + return cfg, nil +} + +func SaveCache2(cfg CacheConfig) error { + cacheFile, err := GetCacheFilePath() + if err != nil { + return err + } + + return withCacheFileLock(cacheFile, func() error { + v := viper.New() + v.Set("last_checked", cfg.LastChecked) + if err := v.WriteConfigAs(cacheFile); err != nil { + return errors.Wrap(err, "failed to write cache file") + } + return nil + }) +} + +func SaveCache(cfg CacheConfig) error { + cacheFile, err := GetCacheFilePath() + if err != nil { + return err + } + + v := viper.New() + v.Set("last_checked", cfg.LastChecked) + if err := v.WriteConfigAs(cacheFile); err != nil { + return errors.Wrap(err, "failed to write cache file") + } + return nil +} + +func ShouldCheckForUpdates(lastChecked int64, frequency string) bool { + now := time.Now().Unix() + + interval, err := parseFrequency(frequency) + if err != nil { + // Log warning and default to daily if we can’t parse + u.LogWarning(schema.CliConfiguration{}, fmt.Sprintf("Unsupported frequency '%s' encountered. Defaulting to daily.", frequency)) + interval = 86400 // daily + } + return now-lastChecked >= interval +} + +// parseFrequency attempts to parse the frequency string in three ways: +// 1. As an integer (seconds) +// 2. As a duration with a suffix (e.g., "1h", "5m", "30s") +// 3. As one of the predefined keywords (daily, hourly, etc.) +func parseFrequency(frequency string) (int64, error) { + freq := strings.TrimSpace(frequency) + + if intVal, err := strconv.ParseInt(freq, 10, 64); err == nil { + if intVal > 0 { + return intVal, nil + } + } + + // Parse duration with suffix + if len(freq) > 1 { + unit := freq[len(freq)-1] + valPart := freq[:len(freq)-1] + if valInt, err := strconv.ParseInt(valPart, 10, 64); err == nil && valInt > 0 { + switch unit { + case 's': + return valInt, nil + case 'm': + return valInt * 60, nil + case 'h': + return valInt * 3600, nil + case 'd': + return valInt * 86400, nil + default: + return 0, fmt.Errorf("unrecognized duration unit: %s", string(unit)) + } + } + } + + // Handle predefined keywords + switch freq { + case "minute": + return 60, nil + case "hourly": + return 3600, nil + case "daily": + return 86400, nil + case "weekly": + return 604800, nil + case "monthly": + return 2592000, nil + case "yearly": + return 31536000, nil + default: + return 0, fmt.Errorf("unrecognized frequency: %s", freq) + } +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 8cbfb8c36..a0a1f0167 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -82,6 +82,13 @@ var ( }, }, Initialized: true, + Version: schema.Version{ + Check: schema.VersionCheck{ + Enabled: true, + Timeout: 1000, + Frequency: "daily", + }, + }, } ) diff --git a/pkg/config/utils.go b/pkg/config/utils.go index 929243c3f..060a1cf2a 100644 --- a/pkg/config/utils.go +++ b/pkg/config/utils.go @@ -371,6 +371,17 @@ func processEnvVars(cliConfig *schema.CliConfiguration) error { cliConfig.Settings.ListMergeStrategy = listMergeStrategy } + versionEnabled := os.Getenv("ATMOS_VERSION_CHECK_ENABLED") + if len(versionEnabled) > 0 { + u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_VERSION_CHECK_ENABLED=%s", versionEnabled)) + enabled, err := strconv.ParseBool(versionEnabled) + if err != nil { + u.LogWarning(*cliConfig, fmt.Sprintf("Invalid boolean value '%s' for ATMOS_VERSION_CHECK_ENABLED; using default.", versionEnabled)) + } else { + cliConfig.Version.Check.Enabled = enabled + } + } + return nil } diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index ff05ed6dc..e44396a38 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -26,6 +26,7 @@ type CliConfiguration struct { StackConfigFilesAbsolutePaths []string `yaml:"stackConfigFilesAbsolutePaths,omitempty" json:"stackConfigFilesAbsolutePaths,omitempty" mapstructure:"stackConfigFilesAbsolutePaths"` StackType string `yaml:"stackType,omitempty" json:"StackType,omitempty" mapstructure:"stackType"` Default bool `yaml:"default" json:"default" mapstructure:"default"` + Version Version `yaml:"version,omitempty" json:"version,omitempty" mapstructure:"version"` } type CliSettings struct { @@ -128,6 +129,16 @@ type Context struct { TerraformWorkspace string `yaml:"terraform_workspace" json:"terraform_workspace" mapstructure:"terraform_workspace"` } +type VersionCheck struct { + Enabled bool `yaml:"enabled,omitempty" mapstructure:"enabled"` + Timeout int `yaml:"timeout,omitempty" mapstructure:"timeout"` + Frequency string `yaml:"frequency,omitempty" mapstructure:"frequency"` +} + +type Version struct { + Check VersionCheck `yaml:"check,omitempty" mapstructure:"check"` +} + type ArgsAndFlagsInfo struct { AdditionalArgsAndFlags []string SubCommand string diff --git a/website/docs/cli/commands/help.mdx b/website/docs/cli/commands/help.mdx index fcbc1c2e3..1df2ef3a1 100644 --- a/website/docs/cli/commands/help.mdx +++ b/website/docs/cli/commands/help.mdx @@ -13,6 +13,10 @@ import Terminal from '@site/src/components/Terminal' The `atmos --help` and `atmos -h` commands show help for all Atmos CLI commands. +From time to time, Atmos will check for a newer release and let you know if one is available. +Please see the [`atmos version`](/cli/commands/version) documentation to configure this behavior. + + ```shell atmos help atmos --help diff --git a/website/docs/cli/commands/version.mdx b/website/docs/cli/commands/version.mdx index a8aabaf56..2deb20a4f 100644 --- a/website/docs/cli/commands/version.mdx +++ b/website/docs/cli/commands/version.mdx @@ -20,7 +20,27 @@ Execute the `atmos version` command like this: atmos version ``` -This will show the CLI version. +This will show the CLI version. + +From time to time, Atmos will check for updates. The frequency of these checks is configured in the `atmos.yaml` file. + +Atmos supports three ways to specify the update check frequency: + +1. As an integer: Specify the number of seconds between checks (for example, 3600 for hourly checks). +2. As a duration with a suffix: Use a time suffix to indicate the interval (for example, `1m` for one minute, `5h` for five hours, or `2d` for two days). +3. As one of the predefined keywords: Choose from the following options: minute, hourly, daily, weekly, monthly, and yearly. The default is daily. +The default is to check `daily`, and if any unsupported values are passed this default will be used. + +It is also possible to turn off version checks in `atmos.yaml` by setting `version.check.enabled` to `false`, +or by setting the `ATMOS_VERSION_CHECK_ENABLED` environment variable to `false`, which overrides +the `version.check.enabled` settings in `atmos.yaml`. + +```shell +atmos version --check +``` + +The version command supports a `--check` flag. +This will force Atmos to check for a new version, irrespective of the configuration settings. :::tip To find the latest version of Atmos, go to the [releases](https://github.com/cloudposse/atmos/releases) page on GitHub. diff --git a/website/docs/cli/configuration/configuration.mdx b/website/docs/cli/configuration/configuration.mdx index 4e95a6850..9268c0cb3 100644 --- a/website/docs/cli/configuration/configuration.mdx +++ b/website/docs/cli/configuration/configuration.mdx @@ -652,6 +652,7 @@ setting `ATMOS_STACKS_BASE_PATH` to a path in `/localhost` to your local develop | ATMOS_LOGS_FILE | logs.file | The file to write Atmos logs to. Logs can be written to any file or any standard file descriptor, including `/dev/stdout`, `/dev/stderr` and `/dev/null`). If omitted, `/dev/stdout` will be used | | ATMOS_LOGS_LEVEL | logs.level | Logs level. Supported log levels are `Trace`, `Debug`, `Info`, `Warning`, `Off`. If the log level is set to `Off`, Atmos will not log any messages (note that this does not prevent other tools like Terraform from logging) | | ATMOS_SETTINGS_LIST_MERGE_STRATEGY | settings.list_merge_strategy | Specifies how lists are merged in Atmos stack manifests. The following strategies are supported: `replace`, `append`, `merge` | +| ATMOS_VERSION_CHECK_ENABLED | version.check.enabled | Enable/disable Atmos version checks for updates to the newest release | ### Context diff --git a/website/docs/integrations/atlantis.mdx b/website/docs/integrations/atlantis.mdx index 842404516..e3a544497 100644 --- a/website/docs/integrations/atlantis.mdx +++ b/website/docs/integrations/atlantis.mdx @@ -673,7 +673,7 @@ on: branches: [ main ] env: - ATMOS_VERSION: 1.122.0 + ATMOS_VERSION: 1.127.0 ATMOS_CLI_CONFIG_PATH: ./ jobs: