This commit is contained in:
Smaug123
2023-12-21 21:06:27 +00:00
parent 46d9ac111a
commit 04552cb995
2 changed files with 34 additions and 25 deletions

View File

@@ -30,15 +30,15 @@ type PipelineModifier<'Agent> =
agent + envVars + workingDir
type AgentIsSet =
type NewAgent =
private
| AgentIsSet of image : string Comp
| NewAgent of image : string Comp
override this.ToString () =
match this with
| AgentIsSet comp -> "Image: " + Comp.force comp
| NewAgent comp -> "Image: " + Comp.force comp
type AgentUnset =
private | AgentUnset
type SameAgent =
private | SameAgent
override this.ToString () =
"<no image specified>"
@@ -47,7 +47,8 @@ type Pipeline<'Agent> =
| ShellScript of script : string * andThen : Pipeline<'Agent>
| ShellScriptBind of script : string * consumeStdout : (Stdout -> Pipeline<'Agent>)
| WithModifier of Pipeline<'Agent> * PipelineModifier<'Agent>
| Sequence of first : Pipeline<AgentUnset> * second : Pipeline<'Agent>
| Sequence of first : Pipeline<SameAgent> * second : Pipeline<'Agent>
| ChangeAgent of first : Pipeline<NewAgent> * second : Pipeline<NewAgent>
[<RequireQualifiedAccess>]
module Pipeline =
@@ -67,11 +68,11 @@ module Pipeline =
[<RequireQualifiedAccess>]
module private PipelineModifier =
let empty : PipelineModifier<AgentUnset> =
let empty : PipelineModifier<SameAgent> =
{
EnvVars = []
WorkingDir = None
Agent = AgentUnset
Agent = SameAgent
}
[<Sealed ; Class>]
@@ -88,7 +89,7 @@ type PipelineBuilder<'plat, 'agentFinal> () =
[<CustomOperation "withEnv">]
member _.WithEnv
(() : unit, (key : string, value : string Comp))
: PipelineModifier<AgentUnset>
: PipelineModifier<SameAgent>
=
{ PipelineModifier.empty with
EnvVars = [key, value]
@@ -106,7 +107,7 @@ type PipelineBuilder<'plat, 'agentFinal> () =
[<CustomOperation "workingDir">]
member _.WorkingDir
(() : unit, dir : DirectoryInfo Comp)
: PipelineModifier<AgentUnset>
: PipelineModifier<SameAgent>
=
{ PipelineModifier.empty with
WorkingDir = Some dir
@@ -115,26 +116,26 @@ type PipelineBuilder<'plat, 'agentFinal> () =
[<CustomOperation "remote">]
member _.Remote
(() : unit, image : string Comp)
: PipelineModifier<AgentIsSet>
: PipelineModifier<NewAgent>
=
{
EnvVars = []
WorkingDir = None
Agent = AgentIsSet image
Agent = NewAgent image
}
[<CustomOperation "remote">]
member _.Remote
(mods : PipelineModifier<AgentUnset>, image : string Comp)
: PipelineModifier<AgentIsSet>
(mods : PipelineModifier<SameAgent>, image : string Comp)
: PipelineModifier<NewAgent>
=
{
EnvVars = mods.EnvVars
WorkingDir = mods.WorkingDir
Agent = AgentIsSet image
Agent = NewAgent image
}
member _.Return (() : unit) = Pipeline.Empty
member _.Return<'Agent> (() : unit) = Pipeline<'Agent>.Empty
/// For running a script, capturing stdout
member _.Bind (toRun : string, cont : Stdout -> Pipeline<'Agent>) : Pipeline<'Agent> =
@@ -142,34 +143,40 @@ type PipelineBuilder<'plat, 'agentFinal> () =
/// For running a script, without capturing stdout
member _.Bind (toRun : string, cont : unit -> Pipeline<'Agent>) : Pipeline<'Agent> =
Pipeline.ShellScript (toRun, cont ())
/// We can bind any pipeline which doesn't say where it's going to run; the interpretation is that it'll
/// run wherever the parent runs.
member _.Bind (p : Pipeline<AgentUnset>, cont : unit -> Pipeline<'Agent>) : Pipeline<'Agent> =
/// We can bind any pipeline which runs on the "same agent".
member _.Bind (p : Pipeline<SameAgent>, cont : unit -> Pipeline<'Agent>) : Pipeline<'Agent> =
Pipeline.Sequence (p, cont ())
// TODO: we could allow binding in running on the same agent as the parent, interpreting that as "run on the parent",
// or binding in running on a different agent from the parent, interpreting that as "run in a new agent".
// Seems a bit magic.
/// We can also bind in any pipeline to run on a different agent.
member _.Bind (p : Pipeline<NewAgent>, cont : unit -> Pipeline<NewAgent>) : Pipeline<'Agent> =
Pipeline.ChangeAgent (p, cont ())
member _.Yield (() : unit) : unit = ()
member _.For (expr : PipelineModifier<'Agent>, cont : unit -> Pipeline<'Agent>) : Pipeline<'Agent> =
Pipeline.WithModifier (cont (), expr)
[<AutoOpen>]
module PipelineBuilder =
let pipeline<'plat, 'agent> = PipelineBuilder<'plat, 'agent> ()
let pipeline<'agent> = PipelineBuilder<unit, 'agent> ()
let toStepDag<'Agent> (p : Pipeline<'Agent>) : SealedStepDag<unit, unit> = failwith $"TODO\n%s{Pipeline.toString p}"
let foo () : SealedStepDag<unit, unit> =
pipeline {
remote (Comp.make "some-image")
withEnv ("hi", Comp.make "bye")
workingDir (Comp.make (DirectoryInfo "code root here"))
withEnv ("foo", Comp.make "bar")
withEnv ("hi", Comp.make "bye")
let! (Stdout stdout) = "sh script here"
do! pipeline {
// type annotation is not necessary here but makes the location explicit
do! pipeline<SameAgent> {
withEnv ("foo", stdout)
do! "git config --foo"
return ()
}
// again, type annotation is not necessary here but makes it explicit that this is running somewhere
// else
do! pipeline {
// remote (Comp.make "another-image")
return ()
}
do! "a shell script"
return ()
}