Skip to content

Commit dc2c113

Browse files
fix: make config files & evm/tron chain load optional (#530)
Fixes issue where users needed dummy config files with evm deployer key to analyze MCMS proposals locally. Context: https://chainlink-core.slack.com/archives/C08QF1BEW4T/p1761128244593229 Changes: - Config files now optional, falls back to environment variables - EVM and Tron chains only load when credentials provided (key or KMS) - Added tests for optional config and credential scenarios Users can now analyze proposals without credentials. No breaking changes.
1 parent aa38817 commit dc2c113

File tree

5 files changed

+132
-8
lines changed

5 files changed

+132
-8
lines changed

.changeset/some-plants-doubt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": patch
3+
---
4+
5+
fix: make config files and chain credentials optional

engine/cld/chains/chains.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,20 @@ func LoadChains(
168168
func newChainLoaders(
169169
lggr logger.Logger, networks *cfgnet.Config, cfg cfgenv.OnchainConfig,
170170
) map[string]ChainLoader {
171-
// EVM chains are always loaded.
172-
loaders := map[string]ChainLoader{
173-
chainsel.FamilyEVM: newChainLoaderEVM(networks, cfg, lggr),
174-
chainsel.FamilyTron: newChainLoaderTron(networks, cfg),
171+
loaders := map[string]ChainLoader{}
172+
173+
// EVM chains are loaded if either KMS or deployer key is configured.
174+
if useKMS(cfg.KMS) || cfg.EVM.DeployerKey != "" {
175+
loaders[chainsel.FamilyEVM] = newChainLoaderEVM(networks, cfg, lggr)
176+
} else {
177+
lggr.Warn("Skipping EVM chains, no private key or KMS config found in secrets")
178+
}
179+
180+
// Tron chains are loaded if either KMS or deployer key is configured.
181+
if useKMS(cfg.KMS) || cfg.Tron.DeployerKey != "" {
182+
loaders[chainsel.FamilyTron] = newChainLoaderTron(networks, cfg)
183+
} else {
184+
lggr.Warn("Skipping Tron chains, no private key or KMS config found in secrets")
175185
}
176186

177187
if cfg.Solana.ProgramsDirPath != "" && cfg.Solana.WalletKey != "" {

engine/cld/chains/chains_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,114 @@ import (
2121
cfgnet "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/config/network"
2222
)
2323

24+
func Test_newChainLoaders(t *testing.T) {
25+
t.Parallel()
26+
27+
lggr := logger.Test(t)
28+
networks := &cfgnet.Config{}
29+
30+
tests := []struct {
31+
name string
32+
onchainConfig cfgenv.OnchainConfig
33+
wantLoaders []string // Expected chain families with loaders
34+
}{
35+
{
36+
name: "All credentials provided",
37+
onchainConfig: cfgenv.OnchainConfig{
38+
EVM: cfgenv.EVMConfig{
39+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
40+
},
41+
Tron: cfgenv.TronConfig{
42+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
43+
},
44+
Solana: cfgenv.SolanaConfig{
45+
WalletKey: "test-key",
46+
ProgramsDirPath: "/tmp/programs",
47+
},
48+
Aptos: cfgenv.AptosConfig{
49+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
50+
},
51+
Sui: cfgenv.SuiConfig{
52+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
53+
},
54+
Ton: cfgenv.TonConfig{
55+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
56+
},
57+
},
58+
wantLoaders: []string{
59+
chainsel.FamilyEVM,
60+
chainsel.FamilyTron,
61+
chainsel.FamilySolana,
62+
chainsel.FamilyAptos,
63+
chainsel.FamilySui,
64+
chainsel.FamilyTon,
65+
},
66+
},
67+
{
68+
name: "No EVM credentials - EVM skipped",
69+
onchainConfig: cfgenv.OnchainConfig{
70+
Tron: cfgenv.TronConfig{
71+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
72+
},
73+
},
74+
wantLoaders: []string{
75+
chainsel.FamilyTron,
76+
},
77+
},
78+
{
79+
name: "KMS configured - EVM and Tron loaded",
80+
onchainConfig: cfgenv.OnchainConfig{
81+
KMS: cfgenv.KMSConfig{
82+
KeyID: "test-key-id",
83+
KeyRegion: "us-west-2",
84+
},
85+
},
86+
wantLoaders: []string{
87+
chainsel.FamilyEVM,
88+
chainsel.FamilyTron,
89+
},
90+
},
91+
{
92+
name: "No credentials - all chains skipped",
93+
onchainConfig: cfgenv.OnchainConfig{},
94+
wantLoaders: []string{},
95+
},
96+
{
97+
name: "Only EVM deployer key",
98+
onchainConfig: cfgenv.OnchainConfig{
99+
EVM: cfgenv.EVMConfig{
100+
DeployerKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
101+
},
102+
},
103+
wantLoaders: []string{
104+
chainsel.FamilyEVM,
105+
},
106+
},
107+
}
108+
109+
for _, tt := range tests {
110+
t.Run(tt.name, func(t *testing.T) {
111+
t.Parallel()
112+
113+
loaders := newChainLoaders(lggr, networks, tt.onchainConfig)
114+
115+
// Check that we got the expected number of loaders
116+
assert.Len(t, loaders, len(tt.wantLoaders),
117+
"Expected %d loaders but got %d", len(tt.wantLoaders), len(loaders))
118+
119+
// Check that each expected family has a loader
120+
for _, family := range tt.wantLoaders {
121+
assert.Contains(t, loaders, family, "Expected loader for family %s", family)
122+
}
123+
124+
// Check that we don't have unexpected loaders
125+
for family := range loaders {
126+
assert.Contains(t, tt.wantLoaders, family, "Unexpected loader for family %s", family)
127+
}
128+
})
129+
}
130+
}
131+
24132
func Test_LoadChains(t *testing.T) {
25133
t.Parallel()
26134

engine/cld/config/config_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ func Test_Load(t *testing.T) {
3838
wantErr: "failed to load networks",
3939
},
4040
{
41-
name: "fails to load env config",
41+
name: "loads config without local config file (falls back to env vars)",
4242
beforeFunc: func(t *testing.T, dom fdomain.Domain, envKey string) {
4343
t.Helper()
4444

4545
writeConfigNetworksFile(t, dom, "networks.yaml", "networks-testnet.yaml")
4646
writeConfigDomainFile(t, dom, "domain.yaml")
47+
// Note: not creating a local config file - it should fall back to env vars
4748
},
48-
wantErr: "failed to load env config",
4949
},
5050
}
5151

engine/cld/config/env.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ func LoadDatastoreType(dom fdomain.Domain, env string) (cfgdomain.DatastoreType,
3030
//
3131
// Loading strategy:
3232
// - In CI environments: Loads configuration exclusively from environment variables set by the CI pipeline.
33-
// - In local development: Loads configuration from a local config file specific to the domain and environment.
33+
// - In local development: Loads configuration from a local config file if it exists, otherwise falls back
34+
// to environment variables. Environment variables can override file values when both are present.
3435
func LoadEnvConfig(dom fdomain.Domain, env string) (*cfgenv.Config, error) {
3536
if isCI() {
3637
cfg, err := cfgenv.LoadEnv()
@@ -43,5 +44,5 @@ func LoadEnvConfig(dom fdomain.Domain, env string) (*cfgenv.Config, error) {
4344

4445
fp := filepath.Join(dom.ConfigLocalFilePath(env))
4546

46-
return cfgenv.LoadFile(fp)
47+
return cfgenv.Load(fp)
4748
}

0 commit comments

Comments
 (0)