Skip to content

Commit a8928d5

Browse files
authored
fix: avoid loading proposal ctx when proposal ctx provider is nil (#660)
This pull request introduces a deprecation warning system for legacy `mcmsv2` CLI commands and improves error handling when loading proposal contexts. The main goal is to inform users about the migration to the new `mcms-tools` repository and to prevent unnecessary loading of proposal contexts when the provider is nil. Deprecation warning system: * Added a visible deprecation banner and runtime warning to most `mcmsv2` CLI commands, indicating their migration to the `mcms-tools` repository and possible removal in future releases (`engine/cld/legacy/cli/mcmsv2/mcms_v2.go`). [[1]](diffhunk://#diff-726dd799d05204c24b69b8bda1f4ede5393c5955b360b076db8d11bc01f56a1bR62-R76) [[2]](diffhunk://#diff-726dd799d05204c24b69b8bda1f4ede5393c5955b360b076db8d11bc01f56a1bR98-R137) [[3]](diffhunk://#diff-726dd799d05204c24b69b8bda1f4ede5393c5955b360b076db8d11bc01f56a1bL118-R195) * Excluded certain commands from deprecation warnings (such as proposal analysis and fork testing) since they remain supported for now (`engine/cld/legacy/cli/mcmsv2/mcms_v2.go`). Error handling improvements: * Modified proposal context initialization to avoid loading it if the provider is nil, preventing possible runtime errors (`engine/cld/legacy/cli/mcmsv2/mcms_v2.go`). [[1]](diffhunk://#diff-726dd799d05204c24b69b8bda1f4ede5393c5955b360b076db8d11bc01f56a1bR1286-R1292) [[2]](diffhunk://#diff-ae98e02a8b3da4252b397f33fcee411841037b39531e36277434eb0bbc96c71eR1-R6) Other: * Added a patch-level changeset documenting the fixes and deprecation warning addition (`.changeset/afraid-parks-rush.md`).
1 parent 504cfaa commit a8928d5

File tree

2 files changed

+88
-21
lines changed

2 files changed

+88
-21
lines changed

.changeset/afraid-parks-rush.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"chainlink-deployments-framework": patch
3+
---
4+
5+
fix: avoid loading proposal ctx if the provider is nil
6+
chore: add deprecation warning to mcmsv2 commands

engine/cld/legacy/cli/mcmsv2/mcms_v2.go

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ const (
6464
defaultProposalValidity = 72 * time.Hour
6565
)
6666

67+
const mcmsv2DeprecatedWarning = `
68+
============================== WARNING ==============================
69+
The legacy "mcmsv2" CLI commands are being DEPRECATED.
70+
71+
Most functionality has moved to the "mcms-tools" repository:
72+
https://github.com/smartcontractkit/mcms-tools
73+
74+
This command may be removed in a future release. Please migrate.
75+
=======================================================================`
76+
77+
const (
78+
ansiYellow = "\x1b[33m"
79+
ansiReset = "\x1b[0m"
80+
)
81+
6782
type commonFlagsv2 struct {
6883
proposalPath string
6984
proposalKindStr string
@@ -85,6 +100,47 @@ type cfgv2 struct {
85100
proposalCtx analyzer.ProposalContext
86101
}
87102

103+
// addMCMSv2DeprecationWarning decorates a command to:
104+
// - show a large deprecation banner in help output
105+
// - print the same banner to stderr at runtime before execution
106+
//
107+
// NOTE: Certain mcmsv2 commands are intentionally excluded from this warning
108+
// like proposal analysis and fork testing because they remain supported for now due to dependencies on domain code.
109+
func addMCMSv2DeprecationWarning(cmd *cobra.Command) *cobra.Command {
110+
if cmd == nil {
111+
return cmd
112+
}
113+
114+
// Prepend banner to help text.
115+
banner := strings.TrimSpace(mcmsv2DeprecatedWarning)
116+
if !strings.HasPrefix(strings.TrimSpace(cmd.Long), banner) {
117+
cmd.Long = banner + "\n\n" + cmd.Long
118+
}
119+
120+
if cmd.Short != "" && !strings.HasPrefix(cmd.Short, "DEPRECATED:") {
121+
cmd.Short = "DEPRECATED: " + cmd.Short
122+
}
123+
124+
printBanner := func(c *cobra.Command) {
125+
_, _ = fmt.Fprintln(c.ErrOrStderr(), ansiYellow+banner+ansiReset)
126+
_, _ = fmt.Fprintln(c.ErrOrStderr())
127+
}
128+
129+
// Wrap RunE to print banner at runtime (start + end).
130+
if cmd.RunE != nil {
131+
origRunE := cmd.RunE
132+
cmd.RunE = func(c *cobra.Command, args []string) error {
133+
printBanner(c)
134+
err := origRunE(c, args)
135+
printBanner(c)
136+
137+
return err
138+
}
139+
}
140+
141+
return cmd
142+
}
143+
88144
func BuildMCMSv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, proposalContextProvider analyzer.ProposalContextProvider) *cobra.Command {
89145
var (
90146
proposalPath string
@@ -120,27 +176,29 @@ func BuildMCMSv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, proposalConte
120176
panicErr(cmd.MarkPersistentFlagRequired(environmentFlag))
121177
panicErr(cmd.MarkPersistentFlagRequired(chainSelectorFlag))
122178

123-
cmd.AddCommand(buildMCMSCheckQuorumv2Cmd(lggr, domain))
124-
cmd.AddCommand(buildExecuteChainv2Cmd(lggr, domain, proposalContextProvider))
125-
cmd.AddCommand(buildExecuteOperationv2Cmd(lggr, domain, proposalContextProvider))
126-
cmd.AddCommand(buildSetRootv2Cmd(lggr, domain, proposalContextProvider))
127-
cmd.AddCommand(buildGetOpCountV2Cmd(lggr, domain, proposalContextProvider))
128-
cmd.AddCommand(buildMCMSErrorDecode(lggr, domain, proposalContextProvider))
129-
cmd.AddCommand(buildRunTimelockIsPendingV2Cmd(lggr, domain))
130-
cmd.AddCommand(buildRunTimelockIsReadyToExecuteV2Cmd(lggr, domain))
131-
cmd.AddCommand(buildRunTimelockIsDoneV2Cmd(lggr, domain, proposalContextProvider))
132-
cmd.AddCommand(buildRunTimelockIsOperationPendingV2Cmd(lggr, domain))
133-
cmd.AddCommand(buildRunTimelockIsOperationReadyToExecuteV2Cmd(lggr, domain))
134-
cmd.AddCommand(buildRunTimelockIsOperationDoneV2Cmd(lggr, domain))
135-
cmd.AddCommand(buildTimelockExecuteChainV2Cmd(lggr, domain, proposalContextProvider))
136-
cmd.AddCommand(buildTimelockExecuteOperationV2Cmd(lggr, domain, proposalContextProvider))
137-
cmd.AddCommand(buildMCMSv2AnalyzeProposalCmd(stdErrLogger, domain, proposalContextProvider))
138-
cmd.AddCommand(buildMCMSv2ConvertUpf(stdErrLogger, domain, proposalContextProvider))
139-
cmd.AddCommand(buildMCMSv2ResetProposalCmd(stdErrLogger, domain, proposalContextProvider))
179+
// Everything under mcmsv2 is being deprecated, except a small set of commands
180+
// that remain supported for now.
181+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildMCMSCheckQuorumv2Cmd(lggr, domain)))
182+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildExecuteChainv2Cmd(lggr, domain, proposalContextProvider)))
183+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildExecuteOperationv2Cmd(lggr, domain, proposalContextProvider)))
184+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildSetRootv2Cmd(lggr, domain, proposalContextProvider)))
185+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildGetOpCountV2Cmd(lggr, domain, proposalContextProvider)))
186+
cmd.AddCommand(buildMCMSErrorDecode(lggr, domain, proposalContextProvider)) // not deprecated (yet)
187+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsPendingV2Cmd(lggr, domain)))
188+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsReadyToExecuteV2Cmd(lggr, domain)))
189+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsDoneV2Cmd(lggr, domain, proposalContextProvider)))
190+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsOperationPendingV2Cmd(lggr, domain)))
191+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsOperationReadyToExecuteV2Cmd(lggr, domain)))
192+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildRunTimelockIsOperationDoneV2Cmd(lggr, domain)))
193+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildTimelockExecuteChainV2Cmd(lggr, domain, proposalContextProvider)))
194+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildTimelockExecuteOperationV2Cmd(lggr, domain, proposalContextProvider)))
195+
cmd.AddCommand(buildMCMSv2AnalyzeProposalCmd(stdErrLogger, domain, proposalContextProvider)) // not deprecated (yet)
196+
cmd.AddCommand(buildMCMSv2ConvertUpf(stdErrLogger, domain, proposalContextProvider)) // not deprecated (yet)
197+
cmd.AddCommand(addMCMSv2DeprecationWarning(buildMCMSv2ResetProposalCmd(stdErrLogger, domain, proposalContextProvider)))
140198

141199
// fork flag is only used internally by buildExecuteForkCommand
142200
cmd.PersistentFlags().BoolP(forkFlag, "f", false, "Run the command on forked environment (EVM)")
143-
cmd.AddCommand(buildExecuteForkCommand(lggr, domain, proposalContextProvider))
201+
cmd.AddCommand(buildExecuteForkCommand(lggr, domain, proposalContextProvider)) // not deprecated (yet)
144202

145203
return &cmd
146204
}
@@ -1241,9 +1299,12 @@ func newCfgv2(lggr logger.Logger, cmd *cobra.Command, domain cldf_domain.Domain,
12411299
if err != nil {
12421300
return nil, fmt.Errorf("error loading environment: %w", err)
12431301
}
1244-
cfg.proposalCtx, err = proposalCtxProvider(cfg.env)
1245-
if err != nil {
1246-
return nil, fmt.Errorf("failed to provide proposal analysis context: %w", err)
1302+
1303+
if proposalCtxProvider != nil {
1304+
cfg.proposalCtx, err = proposalCtxProvider(cfg.env)
1305+
if err != nil {
1306+
return nil, fmt.Errorf("failed to provide proposal analysis context: %w", err)
1307+
}
12471308
}
12481309

12491310
if flags.fork {

0 commit comments

Comments
 (0)