From ebb2b525314ffae5c262277f7c381ea7b4972e7f Mon Sep 17 00:00:00 2001 From: Pierre Chalamet Date: Sat, 14 Jun 2025 14:38:33 +0200 Subject: [PATCH] add support for managed at workspace level --- .../TestFiles/Success_WORKSPACE | 1 + .../Workspace.fs | 18 +++-- src/Terrabuild.Configuration/AST/Workspace.fs | 3 +- .../Transpiler/Workspace.fs | 6 +- src/Terrabuild/Core/Configuration.fs | 69 +++++++++---------- 5 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/Terrabuild.Configuration.Tests/TestFiles/Success_WORKSPACE b/src/Terrabuild.Configuration.Tests/TestFiles/Success_WORKSPACE index af48896f..9b6688f1 100644 --- a/src/Terrabuild.Configuration.Tests/TestFiles/Success_WORKSPACE +++ b/src/Terrabuild.Configuration.Tests/TestFiles/Success_WORKSPACE @@ -13,6 +13,7 @@ target build { # comment at end of line target dist { depends_on = [ target.build ] + managed = false rebuild = true } diff --git a/src/Terrabuild.Configuration.Tests/Workspace.fs b/src/Terrabuild.Configuration.Tests/Workspace.fs index 159bb579..21d1099a 100644 --- a/src/Terrabuild.Configuration.Tests/Workspace.fs +++ b/src/Terrabuild.Configuration.Tests/Workspace.fs @@ -13,13 +13,16 @@ let parseWorkspace() = let expectedWorkspace = let targetBuild = { TargetBlock.DependsOn = Set [ "^build" ] |> Some - TargetBlock.Rebuild = None } + TargetBlock.Rebuild = None + TargetBlock.Managed = None } let targetDist = { TargetBlock.DependsOn = Set [ "build" ] |> Some - TargetBlock.Rebuild = Expr.Bool true |> Some } + TargetBlock.Rebuild = Expr.Bool true |> Some + TargetBlock.Managed = Expr.False |> Some } let targetDummy = { TargetBlock.DependsOn = None - TargetBlock.Rebuild = None } + TargetBlock.Rebuild = None + TargetBlock.Managed = None } let extDotnet = { Container = Some (Expr.String "mcr.microsoft.com/dotnet/sdk:8.0.101") @@ -63,13 +66,16 @@ let parseWorkspace2() = let expectedWorkspace = let targetBuild = { TargetBlock.DependsOn = Set [ "^build" ] |> Some - TargetBlock.Rebuild = None } + TargetBlock.Rebuild = None + TargetBlock.Managed = None } let targetDist = { TargetBlock.DependsOn = Set [ "build" ] |> Some - TargetBlock.Rebuild = Expr.Bool true |> Some } + TargetBlock.Rebuild = Expr.Bool true |> Some + TargetBlock.Managed = None } let targetDummy = { TargetBlock.DependsOn = None - TargetBlock.Rebuild = None } + TargetBlock.Rebuild = None + TargetBlock.Managed = None } let extDotnet = { Container = Expr.String "mcr.microsoft.com/dotnet/sdk:8.0.101" |> Some diff --git a/src/Terrabuild.Configuration/AST/Workspace.fs b/src/Terrabuild.Configuration/AST/Workspace.fs index 2e926fc7..b8cffe3b 100644 --- a/src/Terrabuild.Configuration/AST/Workspace.fs +++ b/src/Terrabuild.Configuration/AST/Workspace.fs @@ -12,7 +12,8 @@ type WorkspaceBlock = [] type TargetBlock = { DependsOn: Set option - Rebuild: Expr option } + Rebuild: Expr option + Managed: Expr option } [] type WorkspaceFile = diff --git a/src/Terrabuild.Configuration/Transpiler/Workspace.fs b/src/Terrabuild.Configuration/Transpiler/Workspace.fs index f6c9d4fd..8ccddbd2 100644 --- a/src/Terrabuild.Configuration/Transpiler/Workspace.fs +++ b/src/Terrabuild.Configuration/Transpiler/Workspace.fs @@ -45,7 +45,7 @@ let toWorkspace (block: Block) = let toTarget (block: Block) = block - |> checkAllowedAttributes ["depends_on"; "rebuild"] + |> checkAllowedAttributes ["depends_on"; "rebuild"; "managed"] |> checkNoNestedBlocks |> ignore @@ -58,9 +58,11 @@ let toTarget (block: Block) = | String.Regex "^target\.(.*)$" [targetIdentifier] -> targetIdentifier | _ -> raiseInvalidArg $"Invalid target dependency '{dependency}'")) let rebuild = block |> tryFindAttribute "rebuild" + let managed = block |> tryFindAttribute "managed" { TargetBlock.DependsOn = dependsOn - TargetBlock.Rebuild = rebuild } + TargetBlock.Rebuild = rebuild + TargetBlock.Managed = managed } let toVariable (block: Block) = diff --git a/src/Terrabuild/Core/Configuration.fs b/src/Terrabuild/Core/Configuration.fs index 0c63b661..ef0950b0 100644 --- a/src/Terrabuild/Core/Configuration.fs +++ b/src/Terrabuild/Core/Configuration.fs @@ -241,8 +241,7 @@ let private loadProjectDef (options: ConfigOptions.Options) (workspaceConfig: AS let extensions = extensions |> Map.addMap projectConfig.Extensions let projectScripts = - projectConfig.Extensions - |> Map.map (fun _ ext -> + projectConfig.Extensions |> Map.map (fun _ ext -> ext.Script |> Option.bind (Eval.asStringOption << Eval.eval evaluationContext) |> Option.map (FS.workspaceRelative options.Workspace projectDir)) @@ -264,8 +263,7 @@ let private loadProjectDef (options: ConfigOptions.Options) (workspaceConfig: AS ProjectInfo.Includes = projectConfig.Project.Includes |> evalAsStringSet } let initProjectInfo = - projectConfig.Project.Initializers - |> Set.fold (fun projectInfo init -> + projectConfig.Project.Initializers |> Set.fold (fun projectInfo init -> let parseContext = let context = { Terrabuild.Extensibility.ExtensionContext.Debug = options.Debug Terrabuild.Extensibility.ExtensionContext.Directory = projectDir @@ -308,8 +306,8 @@ let private loadProjectDef (options: ConfigOptions.Options) (workspaceConfig: AS |> Set.map (fun dep -> FS.workspaceRelative options.Workspace projectDir dep) let projectTargets = - projectConfig.Targets - |> Map.map (fun targetName targetBlock -> + // apply target override + projectConfig.Targets |> Map.map (fun targetName targetBlock -> let workspaceTarget = workspaceConfig.Targets |> Map.tryFind targetName let rebuild = match targetBlock.Rebuild with @@ -319,10 +317,15 @@ let private loadProjectDef (options: ConfigOptions.Options) (workspaceConfig: AS match targetBlock.DependsOn with | Some dependsOn -> Some dependsOn | _ -> workspaceTarget |> Option.bind _.DependsOn + let managed = + match targetBlock.Managed with + | Some managed -> Some managed + | _ -> workspaceTarget |> Option.bind _.Managed { targetBlock with Rebuild = rebuild - DependsOn = dependsOn }) + DependsOn = dependsOn + Managed = managed }) let includes = projectScripts @@ -333,8 +336,7 @@ let private loadProjectDef (options: ConfigOptions.Options) (workspaceConfig: AS // enrich workspace locals with project locals // NOTE we are checking for duplicated fields as this is an error let locals = - workspaceConfig.Locals - |> Map.iter (fun name _ -> + workspaceConfig.Locals |> Map.iter (fun name _ -> if projectConfig.Locals |> Map.containsKey name then raiseParseError $"duplicated local '{name}'") workspaceConfig.Locals |> Map.addMap projectConfig.Locals @@ -389,8 +391,7 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj "terrabuild.version", Value.String projectHash ] let projectVars = - projectDependencies - |> Seq.choose (fun (KeyValue(_, project)) -> + projectDependencies |> Seq.choose (fun (KeyValue(_, project)) -> project.Id |> Option.map (fun id -> $"project.{id}", Value.Map (Map ["version", Value.String project.Hash]))) |> Map.ofSeq @@ -402,9 +403,7 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj |> Map.addMap projectVars } let projectSteps = - projectDef.Targets - |> Map.map (fun targetName target -> - + projectDef.Targets |> Map.map (fun targetName target -> let evaluationContext = let mutable evaluationContext = let terrabuildTargetVars = @@ -449,14 +448,13 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj // use value from project target // otherwise use workspace target // defaults to allow caching - let rebuild = + let targetRebuild = target.Rebuild |> Option.bind (Eval.asBoolOption << Eval.eval evaluationContext) |> Option.defaultValue false let targetOperations = - target.Steps - |> List.fold (fun actions step -> + target.Steps |> List.fold (fun actions step -> let extension = match projectDef.Extensions |> Map.tryFind step.Extension with | Some extension -> extension @@ -523,9 +521,13 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj actions ) [] - let dependsOn = target.DependsOn |> Option.defaultValue Set.empty + let targetDependsOn = target.DependsOn |> Option.defaultValue Set.empty - let outputs = + let targetManaged = + target.Managed + |> Option.bind (Eval.asBoolOption << Eval.eval evaluationContext) + + let targetOutputs = let targetOutputs = target.Outputs |> Option.bind (Eval.asStringSetOption << Eval.eval evaluationContext) @@ -533,11 +535,6 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj | Some outputs -> outputs | _ -> projectDef.Outputs - let hash = - targetOperations - |> List.map (fun ope -> ope.Hash) - |> Hash.sha256strings - let targetCache = let targetCache = target.Cache @@ -550,19 +547,19 @@ let private finalizeProject projectDir evaluationContext (projectDef: LoadedProj | None -> None | _ -> raiseParseError "invalid cache value" - let targetManaged = - target.Managed - |> Option.bind (Eval.asBoolOption << Eval.eval evaluationContext) + let targetHash = + targetOperations + |> List.map (fun ope -> ope.Hash) + |> Hash.sha256strings - let target = { - Target.Hash = hash - Target.Rebuild = rebuild - Target.DependsOn = dependsOn - Target.Cache = targetCache - Target.Managed = targetManaged - Target.Outputs = outputs - Target.Operations = targetOperations - } + let target = + { Target.Hash = targetHash + Target.Rebuild = targetRebuild + Target.DependsOn = targetDependsOn + Target.Cache = targetCache + Target.Managed = targetManaged + Target.Outputs = targetOutputs + Target.Operations = targetOperations } target )