Skip to content

Commit a06e7ee

Browse files
Add hook types and executeHook helper for pre/post changeset hooks (#780)
## Summary - Adds core types for pre/post changeset execution hooks: `PreHookParams`, `PostHookParams`, `PreHookFunc`/`PostHookFunc`, `FailurePolicy`, `HookDefinition`, `PreHook`, `PostHook` - Implements `ExecuteHook` helper that derives context from `env.GetContext()`, enforces timeouts (default 30s), and applies failure policies (`Abort` returns error, `Warn` logs and swallows) - All new code lives in `engine/cld/changeset/hooks.go`; no existing code is modified ## Test plan - [x] Package compiles cleanly (`go build`) - [x] 0 lint issues (`golangci-lint`) - [x] All existing changeset tests pass unchanged Unit tests for `ExecuteHook` and types coming in a follow-up story
1 parent 7aed8ee commit a06e7ee

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

.changeset/eight-jobs-wish.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
Add pre/post changeset execution hook types and executeHook helper

engine/cld/changeset/hooks.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package changeset
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
fdeployment "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
9+
"github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
10+
)
11+
12+
// DefaultHookTimeout is applied when a HookDefinition has a zero Timeout.
13+
const DefaultHookTimeout = 30 * time.Second
14+
15+
// FailurePolicy determines how a hook error affects the pipeline.
16+
type FailurePolicy int
17+
18+
const (
19+
// Abort causes a hook error to fail the pipeline.
20+
Abort FailurePolicy = iota
21+
// Warn causes a hook error to be logged while the pipeline continues.
22+
Warn
23+
)
24+
25+
// String returns the string representation of a FailurePolicy.
26+
func (fp FailurePolicy) String() string {
27+
switch fp {
28+
case Abort:
29+
return "Abort"
30+
case Warn:
31+
return "Warn"
32+
default:
33+
return fmt.Sprintf("FailurePolicy(%d)", int(fp))
34+
}
35+
}
36+
37+
// HookEnv is the restricted environment surface exposed to hooks.
38+
// Additional fields may be added in future versions as needs arise.
39+
type HookEnv struct {
40+
Name string
41+
Logger logger.Logger
42+
}
43+
44+
// PreHookParams is passed to pre-hooks.
45+
// All fields must be treated as read-only.
46+
type PreHookParams struct {
47+
Env HookEnv
48+
ChangesetKey string
49+
Config any
50+
}
51+
52+
// PostHookParams is passed to post-hooks.
53+
// All fields must be treated as read-only.
54+
type PostHookParams struct {
55+
Env HookEnv
56+
ChangesetKey string
57+
Config any
58+
Output fdeployment.ChangesetOutput
59+
Err error
60+
}
61+
62+
// PreHookFunc is the signature for functions that run before changeset Apply.
63+
// The context is derived from env.GetContext() with the hook's timeout applied.
64+
type PreHookFunc func(ctx context.Context, params PreHookParams) error
65+
66+
// PostHookFunc is the signature for functions that run after changeset Apply.
67+
// The context is derived from env.GetContext() with the hook's timeout applied.
68+
type PostHookFunc func(ctx context.Context, params PostHookParams) error
69+
70+
// HookDefinition holds the metadata common to all hooks.
71+
type HookDefinition struct {
72+
Name string
73+
FailurePolicy FailurePolicy
74+
Timeout time.Duration // zero means DefaultHookTimeout (30s)
75+
}
76+
77+
// PreHook pairs a HookDefinition with a PreHookFunc.
78+
type PreHook struct {
79+
HookDefinition
80+
Func PreHookFunc
81+
}
82+
83+
// PostHook pairs a HookDefinition with a PostHookFunc.
84+
type PostHook struct {
85+
HookDefinition
86+
Func PostHookFunc
87+
}
88+
89+
// ExecuteHook runs a hook function with the configured timeout and failure
90+
// policy. The parent context is derived from env.GetContext(); each hook
91+
// receives a child context with its timeout applied.
92+
//
93+
// Returns nil when the hook succeeds or when the hook fails but the
94+
// FailurePolicy is Warn. Returns the hook error only when the policy is Abort.
95+
func ExecuteHook(
96+
env fdeployment.Environment,
97+
def HookDefinition,
98+
fn func(ctx context.Context) error,
99+
) error {
100+
timeout := def.Timeout
101+
if timeout == 0 {
102+
timeout = DefaultHookTimeout
103+
}
104+
105+
ctx, cancel := context.WithTimeout(env.GetContext(), timeout)
106+
defer cancel()
107+
108+
start := time.Now()
109+
err := fn(ctx)
110+
duration := time.Since(start)
111+
112+
if err != nil {
113+
env.Logger.Warnw("hook failed",
114+
"hook", def.Name,
115+
"duration", duration,
116+
"policy", def.FailurePolicy.String(),
117+
"error", err,
118+
)
119+
} else {
120+
env.Logger.Infow("hook completed",
121+
"hook", def.Name,
122+
"duration", duration,
123+
)
124+
}
125+
126+
if err != nil && def.FailurePolicy == Warn {
127+
return nil
128+
}
129+
130+
return err
131+
}

0 commit comments

Comments
 (0)