diff --git a/cli/cmd/turbo/main.go b/cli/cmd/turbo/main.go index 79255df0c36bb..77a8ce1a8d39a 100644 --- a/cli/cmd/turbo/main.go +++ b/cli/cmd/turbo/main.go @@ -66,6 +66,14 @@ func main() { os.Exit(1) } + if cf != nil { + err = config.CheckTurboVersionCompatibility(turboVersion, cf) + if err != nil { + ui.Error(fmt.Sprintf("%s %s", uiPkg.ERROR_PREFIX, color.RedString(err.Error()))) + os.Exit(1) + } + } + var logger hclog.Logger if cf != nil { logger = cf.Logger diff --git a/cli/internal/config/version_compatibility.go b/cli/internal/config/version_compatibility.go new file mode 100644 index 0000000000000..a58c2c08609da --- /dev/null +++ b/cli/internal/config/version_compatibility.go @@ -0,0 +1,36 @@ +package config + +import ( + "fmt" + + "github.com/Masterminds/semver" + "github.com/vercel/turborepo/cli/internal/fs" +) + +// CheckTurboVersionCompatibility makes sure that the Turbo version is compatible with the configuration +func CheckTurboVersionCompatibility(turboVersion string, c *Config) error { + v, err := semver.NewVersion(turboVersion) + if err != nil { + panic(err) + } + err = checkPackageTurboEngineConstraint(v, c.RootPackageJSON) + if err != nil { + return err + } + return nil +} + +func checkPackageTurboEngineConstraint(turboVersion *semver.Version, packageJSON *fs.PackageJSON) error { + // The lack of an engine constraint means there's nothing to validate and isn't an error. + if packageJSON == nil || packageJSON.Engines["turbo"] == "" { + return nil + } + c, err := semver.NewConstraint(packageJSON.Engines["turbo"]) + if err != nil { + return fmt.Errorf("package.json: the 'engines.turbo' constraint is not valid") + } + if !c.Check(turboVersion) { + return fmt.Errorf("package.json: version '%v' of Turbo does not meet the '%v' engine constraint", turboVersion, packageJSON.Engines["turbo"]) + } + return nil +} diff --git a/cli/internal/fs/package_json.go b/cli/internal/fs/package_json.go index 11cce425b3c53..32ba08f75b951 100644 --- a/cli/internal/fs/package_json.go +++ b/cli/internal/fs/package_json.go @@ -10,6 +10,7 @@ import ( type PackageJSON struct { Name string `json:"name,omitempty"` Version string `json:"version,omitempty"` + Engines map[string]string `json:"engines,omitempty"` Scripts map[string]string `json:"scripts,omitempty"` Dependencies map[string]string `json:"dependencies,omitempty"` DevDependencies map[string]string `json:"devDependencies,omitempty"`