@@ -21,7 +21,7 @@ import (
2121 boatstackruntime "github.com/operatorstack/boatstack/boatstack/internal/runtime"
2222)
2323
24- const flowCompilerVersion = "control-program.compiler.1 "
24+ const flowCompilerVersion = "control-program.compiler.2 "
2525
2626type flowCommandOptions struct {
2727 repository string
@@ -33,7 +33,7 @@ type flowCommandOptions struct {
3333
3434func runFlowCommand (arguments []string ) error {
3535 if len (arguments ) == 0 {
36- return fmt .Errorf ("usage: boatstack flow <compile|check|authorize|revoke|run> [flags]" )
36+ return fmt .Errorf ("usage: boatstack flow <compile|check|authorize|revoke|run|work > [flags]" )
3737 }
3838 action := arguments [0 ]
3939 if action == "authorize" {
@@ -45,6 +45,9 @@ func runFlowCommand(arguments []string) error {
4545 if action == "run" {
4646 return runFlowContinuation (arguments [1 :])
4747 }
48+ if action == "work" {
49+ return runFlowWork (arguments [1 :])
50+ }
4851 flags := flag .NewFlagSet ("flow " + action , flag .ContinueOnError )
4952 flags .SetOutput (os .Stderr )
5053 options := flowCommandOptions {}
@@ -116,7 +119,7 @@ func compileFlow(ctx context.Context, options flowCommandOptions) error {
116119 if err != nil {
117120 return err
118121 }
119- compiled , err := controlprogram .Load (bytes .NewReader (rawIR ), resolver )
122+ compiled , err := controlprogram .LoadWithAssets (bytes .NewReader (rawIR ), resolver , controlprogram. RepositoryAssetResolver { Repository : options . repository } )
120123 if err != nil {
121124 return err
122125 }
@@ -162,13 +165,29 @@ func compileFlow(ctx context.Context, options flowCommandOptions) error {
162165 writes = append (writes , boatstackruntime.ProjectionWrite {
163166 Path : artifactPath , Content : artifactRaw , Mode : 0o644 , ExpectedPreviousSHA256 : artifactPrevious , PublishLast : true ,
164167 })
165- if err := rejectProjectionInputOverlap (lockPath , writes , removals ); err != nil {
166- return err
167- }
168168 expectations := []boatstackruntime.ProjectionExpectation {
169169 {Path : source , Exists : true , ExpectedSHA256 : fileDigest (sourceRaw )},
170170 {Path : lockPath , Exists : true , ExpectedSHA256 : fileDigest (lockRaw )},
171171 }
172+ compileInputs := []string {source , lockPath }
173+ assetPaths := make ([]string , 0 , len (artifact .Assets ))
174+ for relative := range artifact .Assets {
175+ assetPaths = append (assetPaths , relative )
176+ }
177+ sort .Strings (assetPaths )
178+ for _ , relative := range assetPaths {
179+ absolute , pathErr := exactRepositoryPath (options .repository , relative )
180+ if pathErr != nil {
181+ return pathErr
182+ }
183+ compileInputs = append (compileInputs , absolute )
184+ expectations = append (expectations , boatstackruntime.ProjectionExpectation {
185+ Path : absolute , Exists : true , ExpectedSHA256 : artifact .Assets [relative ],
186+ })
187+ }
188+ if err := rejectProjectionInputOverlap (compileInputs , writes , removals ); err != nil {
189+ return err
190+ }
172191 artifactRelative , _ := filepath .Rel (options .repository , artifactPath )
173192 nextOwnership := boatstackruntime .NewFlowProjectionOwnership (filepath .ToSlash (sourceRelative ), filepath .ToSlash (artifactRelative ), artifactRaw , skills )
174193 if err := boatstackruntime .ApplyOwnedFlowProjection (options .repository , writes , removals , expectations , ownership , nextOwnership ); err != nil {
@@ -177,16 +196,19 @@ func compileFlow(ctx context.Context, options flowCommandOptions) error {
177196 return renderFlowResult ("compiled" , artifactPath , artifact )
178197}
179198
180- func rejectProjectionInputOverlap (lockPath string , writes []boatstackruntime.ProjectionWrite , removals []boatstackruntime.ProjectionRemoval ) error {
181- lockPath = filepath .Clean (lockPath )
199+ func rejectProjectionInputOverlap (inputs []string , writes []boatstackruntime.ProjectionWrite , removals []boatstackruntime.ProjectionRemoval ) error {
200+ bound := make (map [string ]bool , len (inputs ))
201+ for _ , input := range inputs {
202+ bound [filepath .Clean (input )] = true
203+ }
182204 for _ , write := range writes {
183- if filepath .Clean (write .Path ) == lockPath {
184- return fmt .Errorf ("FLOW_COMPILE_INPUT_OVERLAP: dependency lock is a projection output" )
205+ if bound [ filepath .Clean (write .Path )] {
206+ return fmt .Errorf ("FLOW_COMPILE_INPUT_OVERLAP: compile input %s is a projection output" , write . Path )
185207 }
186208 }
187209 for _ , removal := range removals {
188- if filepath .Clean (removal .Path ) == lockPath {
189- return fmt .Errorf ("FLOW_COMPILE_INPUT_OVERLAP: dependency lock is a retired projection output" )
210+ if bound [ filepath .Clean (removal .Path )] {
211+ return fmt .Errorf ("FLOW_COMPILE_INPUT_OVERLAP: compile input %s is a retired projection output" , removal . Path )
190212 }
191213 }
192214 return nil
0 commit comments