@@ -54,14 +54,15 @@ func newHooksRunFlags(cmd *cobra.Command, global *internal.GlobalCommandOptions)
5454func newHooksRunCmd () * cobra.Command {
5555 return & cobra.Command {
5656 Use : "run <name>" ,
57- Short : "Runs the specified hook for the project and services" ,
57+ Short : "Runs the specified hook for the project, provisioning layers, and services" ,
5858 Args : cobra .ExactArgs (1 ),
5959 }
6060}
6161
6262type hooksRunFlags struct {
6363 internal.EnvFlag
6464 global * internal.GlobalCommandOptions
65+ layer string
6566 platform string
6667 service string
6768}
@@ -70,6 +71,7 @@ func (f *hooksRunFlags) Bind(local *pflag.FlagSet, global *internal.GlobalComman
7071 f .EnvFlag .Bind (local , global )
7172 f .global = global
7273
74+ local .StringVar (& f .layer , "layer" , "" , "Only runs hooks for the specified provisioning layer." )
7375 local .StringVar (& f .platform , "platform" , "" , "Forces hooks to run for the specified platform." )
7476 local .StringVar (& f .service , "service" , "" , "Only runs hooks for the specified service." )
7577}
@@ -114,6 +116,7 @@ type hookContextType string
114116
115117const (
116118 hookContextProject hookContextType = "command"
119+ hookContextLayer hookContextType = "layer"
117120 hookContextService hookContextType = "service"
118121)
119122
@@ -142,8 +145,20 @@ var knownHookNames = map[string]bool{
142145func (hra * hooksRunAction ) Run (ctx context.Context ) (* actions.ActionResult , error ) {
143146 hookName := hra .args [0 ]
144147
148+ if hra .flags .service != "" && hra .flags .layer != "" {
149+ return nil ,
150+
151+ & internal.ErrorWithSuggestion {
152+ Err : fmt .Errorf (
153+ "--service and --layer cannot be used together: %w" , internal .ErrInvalidFlagCombination ),
154+ Suggestion : "Choose either '--service' to run service hooks or '--layer' to run provisioning layer hooks." ,
155+ }
156+ }
157+
145158 hookType := "project"
146- if hra .flags .service != "" {
159+ if hra .flags .layer != "" {
160+ hookType = "layer"
161+ } else if hra .flags .service != "" {
147162 hookType = "service"
148163 }
149164
@@ -184,6 +199,12 @@ func (hra *hooksRunAction) Run(ctx context.Context) (*actions.ActionResult, erro
184199 }
185200 }
186201
202+ if hra .flags .layer != "" {
203+ if _ , err := hra .projectConfig .Infra .GetLayer (hra .flags .layer ); err != nil {
204+ return nil , err
205+ }
206+ }
207+
187208 // Project level hooks
188209 projectHooks := hra .projectConfig .Hooks [hookName ]
189210
@@ -204,6 +225,24 @@ func (hra *hooksRunAction) Run(ctx context.Context) (*actions.ActionResult, erro
204225 return nil , err
205226 }
206227
228+ for _ , layer := range hra .projectConfig .Infra .Layers {
229+ layerPath := layer .AbsolutePath (hra .projectConfig .Path )
230+
231+ skip := hra .flags .layer != "" && layer .Name != hra .flags .layer
232+
233+ hra .console .Message (ctx , "\n " + output .WithHighLightFormat (fmt .Sprintf ("Layer: %s" , layer .Name )))
234+ if err := hra .processHooks (
235+ ctx ,
236+ layerPath ,
237+ hookName ,
238+ layer .Hooks [hookName ],
239+ hookContextLayer ,
240+ skip ,
241+ ); err != nil {
242+ return nil , err
243+ }
244+ }
245+
207246 // Service level hooks
208247 for _ , service := range stableServices {
209248 serviceHooks := service .Hooks [hookName ]
@@ -212,7 +251,7 @@ func (hra *hooksRunAction) Run(ctx context.Context) (*actions.ActionResult, erro
212251 hra .console .Message (ctx , "\n " + output .WithHighLightFormat (service .Name ))
213252 if err := hra .processHooks (
214253 ctx ,
215- service .RelativePath ,
254+ service .Path () ,
216255 hookName ,
217256 serviceHooks ,
218257 hookContextService ,
@@ -246,7 +285,7 @@ func (hra *hooksRunAction) processHooks(
246285 // When skipping, show individual skip messages for each hook that would have run
247286 for i := range hooks {
248287 hra .console .MessageUxItem (ctx , & ux.SkippedMessage {
249- Message : fmt .Sprintf ("service hook %d/%d" , i + 1 , len (hooks )),
288+ Message : fmt .Sprintf ("%s hook %d/%d" , contextType , i + 1 , len (hooks )),
250289 })
251290 }
252291
@@ -312,37 +351,43 @@ func (hra *hooksRunAction) execHook(
312351
313352// Validates hooks and displays warnings for default shell usage and other issues
314353func (hra * hooksRunAction ) validateAndWarnHooks (ctx context.Context ) error {
315- // Collect all hooks from project and services
316- allHooks := make (map [string ][]* ext.HookConfig )
354+ warningKeys := map [string ]struct {}{}
355+ validateAndWarn := func (cwd string , hooks map [string ][]* ext.HookConfig ) {
356+ if len (hooks ) == 0 {
357+ return
358+ }
317359
318- // Add project hooks
319- for hookName , hookConfigs := range hra .projectConfig .Hooks {
320- allHooks [hookName ] = append (allHooks [hookName ], hookConfigs ... )
360+ hooksManager := ext .NewHooksManager (cwd , hra .commandRunner )
361+ validationResult := hooksManager .ValidateHooks (ctx , hooks )
362+
363+ for _ , warning := range validationResult .Warnings {
364+ key := warning .Message + "\x00 " + warning .Suggestion
365+ if _ , has := warningKeys [key ]; has {
366+ continue
367+ }
368+
369+ warningKeys [key ] = struct {}{}
370+ hra .console .MessageUxItem (ctx , & ux.WarningMessage {
371+ Description : warning .Message ,
372+ })
373+ if warning .Suggestion != "" {
374+ hra .console .Message (ctx , warning .Suggestion )
375+ }
376+ hra .console .Message (ctx , "" )
377+ }
321378 }
322379
323- // Add service hooks
380+ validateAndWarn (hra .projectConfig .Path , hra .projectConfig .Hooks )
381+
324382 stableServices , err := hra .importManager .ServiceStable (ctx , hra .projectConfig )
325383 if err == nil {
326384 for _ , service := range stableServices {
327- for hookName , hookConfigs := range service .Hooks {
328- allHooks [hookName ] = append (allHooks [hookName ], hookConfigs ... )
329- }
385+ validateAndWarn (service .Path (), service .Hooks )
330386 }
331387 }
332388
333- // Create hooks manager and validate
334- hooksManager := ext .NewHooksManager (hra .projectConfig .Path , hra .commandRunner )
335- validationResult := hooksManager .ValidateHooks (ctx , allHooks )
336-
337- // Display any warnings
338- for _ , warning := range validationResult .Warnings {
339- hra .console .MessageUxItem (ctx , & ux.WarningMessage {
340- Description : warning .Message ,
341- })
342- if warning .Suggestion != "" {
343- hra .console .Message (ctx , warning .Suggestion )
344- }
345- hra .console .Message (ctx , "" )
389+ for _ , layer := range hra .projectConfig .Infra .Layers {
390+ validateAndWarn (layer .AbsolutePath (hra .projectConfig .Path ), layer .Hooks )
346391 }
347392
348393 return nil
0 commit comments