diff --git a/cre/changesets/workflow_deploy_test.go b/cre/changesets/workflow_deploy_test.go index 504b721..3c1e982 100644 --- a/cre/changesets/workflow_deploy_test.go +++ b/cre/changesets/workflow_deploy_test.go @@ -200,6 +200,28 @@ func TestCREWorkflowDeployChangeset_Apply(t *testing.T) { require.NoError(t, err) require.Len(t, out.Reports, 1) }) + + t.Run("APIKeyName propagates through changeset to selected CLI", func(t *testing.T) { //nolint:paralleltest + inner := cremocks.NewMockCLIRunner(t) + inner.EXPECT().ContextRegistries().Return([]fcre.ContextRegistryEntry{ + {ID: "private", Type: "off-chain"}, + }).Once() + inner.EXPECT(). + Run(mock.Anything, (map[string]string)(nil), matchCLIArgs("workflow", "deploy")). + Return(&fcre.CallResult{ExitCode: 0, Stdout: []byte("ok")}, nil). + Once() + + outer := cremocks.NewMockCLIRunner(t) + outer.EXPECT().WithNamedAPIKey("prod-1").Return(inner, nil).Once() + + env := newTestEnv(t, testenv.WithCRERunner(fcre.NewRunner(fcre.WithCLI(outer)))) + + namedInput := input + namedInput.APIKeyName = "prod-1" + out, err := cs.Apply(*env, namedInput) + require.NoError(t, err) + require.Len(t, out.Reports, 1) + }) } func matchCLIArgs(wantArgs ...string) any { diff --git a/cre/operations/workflow_deploy.go b/cre/operations/workflow_deploy.go index b445dd6..13ccf08 100644 --- a/cre/operations/workflow_deploy.go +++ b/cre/operations/workflow_deploy.go @@ -59,6 +59,10 @@ type CREWorkflowDeployInput struct { // Optional - TargetName is the CRE CLI target key that must match a top-level key // in project.yaml. Defaults to CREDeployTargetName ("cld-deploy") when empty. TargetName string `json:"targetName,omitempty" yaml:"targetName,omitempty"` + // Optional - APIKeyName selects which CRE API key to use when the runner is + // configured with multiple named keys (e.g. CRE_API_KEY={"prod":"...","stg":"..."}). + // Leave empty when the runner is configured with a single key. + APIKeyName string `json:"apiKeyName,omitempty" yaml:"apiKeyName,omitempty"` } // resolveTargetName returns the user-specified target name, falling back to [CREDeployTargetName]. @@ -71,10 +75,31 @@ func (in CREWorkflowDeployInput) resolveTargetName() string { return CREDeployTargetName } +// usesNamedAPIKeys reports whether apiKeyRaw matches the CRE CLI multi-key layout used when +// CRE_API_KEY is a JSON object of {name: secret} entries (see chainlink-deployments-framework/cre/cli +// named-keys parsing). In that mode the CLI runner requires WithNamedAPIKey before Run, so workflow +// deploy input must set apiKeyName when this returns true. +func usesNamedAPIKeys(apiKeyRaw string) bool { + var m map[string]string + if err := json.Unmarshal([]byte(apiKeyRaw), &m); err != nil { + return false + } + if len(m) == 0 { + return false + } + for name, value := range m { + if name == "" || value == "" { + return false + } + } + + return true +} + // CREWorkflowDeployOp deploys a workflow via the CRE CLI (single side effect: CLI invocation). var CREWorkflowDeployOp = fwops.NewOperation( "cre-workflow-deploy", - semver.MustParse("1.0.0"), + semver.MustParse("1.1.0"), "Deploys a CRE workflow via the CRE CLI subprocess", func(b fwops.Bundle, deps CREDeployDeps, input CREWorkflowDeployInput) (CREWorkflowDeployOutput, error) { ctx := b.GetContext() @@ -82,6 +107,19 @@ var CREWorkflowDeployOp = fwops.NewOperation( return CREWorkflowDeployOutput{}, errors.New("cre CLIRunner is nil") } + if usesNamedAPIKeys(deps.CRECfg.Auth.APIKey) && strings.TrimSpace(input.APIKeyName) == "" { + return CREWorkflowDeployOutput{}, errors.New("cre workflow deploy: apiKeyName is required when CRE_API_KEY is configured as a JSON object of named API keys") + } + + cli := deps.CLI + if input.APIKeyName != "" { + selected, err := deps.CLI.WithNamedAPIKey(input.APIKeyName) + if err != nil { + return CREWorkflowDeployOutput{}, fmt.Errorf("select cre api key %q: %w", input.APIKeyName, err) + } + cli = selected + } + workDir, err := os.MkdirTemp("", "cre-workflow-artifacts-*") if err != nil { return CREWorkflowDeployOutput{}, fmt.Errorf("mkdir temp workflow artifacts: %w", err) @@ -136,7 +174,7 @@ var CREWorkflowDeployOp = fwops.NewOperation( return CREWorkflowDeployOutput{}, fmt.Errorf("write workflow.yaml: %w", err) } - ctxCfg, err := crecli.BuildContextConfig(input.DonFamily, input.Context, deps.CRECfg, deps.CLI.ContextRegistries()) + ctxCfg, err := crecli.BuildContextConfig(input.DonFamily, input.Context, deps.CRECfg, cli.ContextRegistries()) if err != nil { return CREWorkflowDeployOutput{}, err } @@ -163,7 +201,7 @@ var CREWorkflowDeployOp = fwops.NewOperation( "CRE_ETH_PRIVATE_KEY": deps.EVMDeployerKey, } } - res, runErr := deps.CLI.Run(ctx, runEnv, args...) + res, runErr := cli.Run(ctx, runEnv, args...) if runErr != nil { var exitErr *fcre.ExitError if errors.As(runErr, &exitErr) { diff --git a/cre/operations/workflow_deploy_test.go b/cre/operations/workflow_deploy_test.go index 51b03bd..d1ac081 100644 --- a/cre/operations/workflow_deploy_test.go +++ b/cre/operations/workflow_deploy_test.go @@ -2,6 +2,7 @@ package operations import ( "context" + "errors" "os" "path/filepath" "testing" @@ -36,6 +37,7 @@ func TestCREWorkflowDeployOp(t *testing.T) { name string input func(t *testing.T) CREWorkflowDeployInput setupCLI func(t *testing.T) *cremocks.MockCLIRunner + creCfg cfgenv.CREConfig assert func(t *testing.T, out fwops.Report[CREWorkflowDeployInput, CREWorkflowDeployOutput], err error) }{ { @@ -165,6 +167,103 @@ func TestCREWorkflowDeployOp(t *testing.T) { require.Equal(t, "err", out.Output.Stderr) }, }, + { + name: "APIKeyName selects cli before run", + input: func(t *testing.T) CREWorkflowDeployInput { + t.Helper() + + return CREWorkflowDeployInput{ + WorkflowBundle: creartifacts.WorkflowBundle{ + WorkflowName: "wf", + Binary: creartifacts.NewBinarySourceLocal(writeFile(t, "x.wasm", []byte("wasm"))), + Config: creartifacts.NewConfigSourceLocal(writeFile(t, "cfg.json", []byte(`{}`))), + DonFamily: "feeds-zone-a", + DeploymentRegistry: "private", + }, + Project: creartifacts.NewConfigSourceLocal(writeFile(t, "project.yaml", []byte("cld-deploy: {}\n"))), + APIKeyName: "prod-1", + } + }, + setupCLI: func(t *testing.T) *cremocks.MockCLIRunner { + t.Helper() + inner := cremocks.NewMockCLIRunner(t) + inner.EXPECT().ContextRegistries().Return(testRegistries()).Once() + inner.EXPECT().Run(mock.Anything, mock.Anything, matchCLIArgs("workflow", "deploy")).Return( + &fcre.CallResult{ExitCode: 0, Stdout: []byte("ok")}, nil, + ).Once() + + outer := cremocks.NewMockCLIRunner(t) + outer.EXPECT().WithNamedAPIKey("prod-1").Return(inner, nil).Once() + + return outer + }, + assert: func(t *testing.T, _ fwops.Report[CREWorkflowDeployInput, CREWorkflowDeployOutput], err error) { + t.Helper() + require.NoError(t, err) + }, + }, + { + name: "unknown APIKeyName short-circuits before CLI work", + input: func(t *testing.T) CREWorkflowDeployInput { + t.Helper() + + return CREWorkflowDeployInput{ + WorkflowBundle: creartifacts.WorkflowBundle{ + WorkflowName: "wf", + Binary: creartifacts.NewBinarySourceLocal(writeFile(t, "x.wasm", []byte("wasm"))), + Config: creartifacts.NewConfigSourceLocal(writeFile(t, "cfg.json", []byte(`{}`))), + DonFamily: "feeds-zone-a", + DeploymentRegistry: "private", + }, + Project: creartifacts.NewConfigSourceLocal(writeFile(t, "project.yaml", []byte("cld-deploy: {}\n"))), + APIKeyName: "missing", + } + }, + setupCLI: func(t *testing.T) *cremocks.MockCLIRunner { + t.Helper() + outer := cremocks.NewMockCLIRunner(t) + outer.EXPECT().WithNamedAPIKey("missing").Return(nil, errors.New(`API key "missing" not configured`)).Once() + + return outer + }, + assert: func(t *testing.T, _ fwops.Report[CREWorkflowDeployInput, CREWorkflowDeployOutput], err error) { + t.Helper() + require.ErrorContains(t, err, `select cre api key "missing"`) + require.ErrorContains(t, err, "not configured") + }, + }, + { + name: "named API keys in CRE config without apiKeyName errors before resolver work", + input: func(t *testing.T) CREWorkflowDeployInput { + t.Helper() + + return CREWorkflowDeployInput{ + WorkflowBundle: creartifacts.WorkflowBundle{ + WorkflowName: "wf", + Binary: creartifacts.NewBinarySourceLocal(writeFile(t, "x.wasm", []byte("wasm"))), + Config: creartifacts.NewConfigSourceLocal(writeFile(t, "cfg.json", []byte(`{}`))), + DonFamily: "feeds-zone-a", + DeploymentRegistry: "private", + }, + Project: creartifacts.NewConfigSourceLocal(writeFile(t, "project.yaml", []byte("cld-deploy: {}\n"))), + } + }, + setupCLI: func(t *testing.T) *cremocks.MockCLIRunner { + t.Helper() + + return cremocks.NewMockCLIRunner(t) + }, + creCfg: cfgenv.CREConfig{ + Auth: cfgenv.CREAuthConfig{ + APIKey: `{"prod-1":"k1","prod-2":"k2"}`, + }, + }, + assert: func(t *testing.T, _ fwops.Report[CREWorkflowDeployInput, CREWorkflowDeployOutput], err error) { + t.Helper() + require.ErrorContains(t, err, "apiKeyName is required") + require.ErrorContains(t, err, "named API keys") + }, + }, } for _, tc := range tests { @@ -175,7 +274,7 @@ func TestCREWorkflowDeployOp(t *testing.T) { bundle := fwops.NewBundle(func() context.Context { return t.Context() }, logger.Test(t), fwops.NewMemoryReporter()) deps := CREDeployDeps{ CLI: mockCLI, - CRECfg: cfgenv.CREConfig{}, + CRECfg: tc.creCfg, } out, err := fwops.ExecuteOperation[CREWorkflowDeployInput, CREWorkflowDeployOutput, CREDeployDeps]( @@ -222,6 +321,32 @@ func TestResolveTargetName(t *testing.T) { } } +func TestCREAuthUsesNamedAPIKeys(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + raw string + want bool + }{ + {name: "empty", raw: "", want: false}, + {name: "plain secret", raw: "not-json", want: false}, + {name: "json string", raw: `"x"`, want: false}, + {name: "json array", raw: `["a"]`, want: false}, + {name: "empty object", raw: `{}`, want: false}, + {name: "empty key", raw: `{"":"v"}`, want: false}, + {name: "empty value", raw: `{"a":""}`, want: false}, + {name: "single named entry", raw: `{"prod":"secret"}`, want: true}, + {name: "multiple named entries", raw: `{"a":"1","b":"2"}`, want: true}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + require.Equal(t, tc.want, usesNamedAPIKeys(tc.raw)) + }) + } +} + // --------------------------------------------------------------------------- // BuildWorkflowDeployArgs // --------------------------------------------------------------------------- diff --git a/go.mod b/go.mod index 1d4ec05..b9d2189 100644 --- a/go.mod +++ b/go.mod @@ -16,12 +16,11 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-common v0.11.2-0.20260429111145-3667714e0b37 - github.com/smartcontractkit/chainlink-deployments-framework v0.101.0 + github.com/smartcontractkit/chainlink-deployments-framework v0.102.0 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 - github.com/smartcontractkit/chainlink-ton/deployment v0.0.0-20260430134932-681b7a7fe426 - github.com/smartcontractkit/mcms v0.41.1 + github.com/smartcontractkit/mcms v0.42.0 github.com/smartcontractkit/quarantine v0.0.0-20251203215908-fd0551c6adf9 github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 github.com/spf13/cast v1.10.0 @@ -97,13 +96,11 @@ require ( github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect github.com/creachadair/jrpc2 v1.2.0 // indirect github.com/creachadair/mds v0.13.4 // indirect - github.com/creack/pty v1.1.24 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dchest/siphash v1.2.3 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/digital-asset/dazl-client/v8 v8.9.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.5.3-0.20260325154711-31a1689cb0a1+incompatible // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.10.0 // indirect @@ -191,7 +188,9 @@ require ( github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.2.0 // indirect - github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/moby/api v1.54.1 // indirect + github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/patternmatcher v0.6.1 // indirect github.com/moby/spdystream v0.5.1 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/user v0.4.0 // indirect @@ -200,7 +199,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/montanaflynn/stats v0.7.1 // indirect - github.com/morikuni/aec v1.1.0 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -231,7 +229,7 @@ require ( github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/segmentio/ksuid v1.0.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v4 v4.26.2 // indirect + github.com/shirou/gopsutil/v4 v4.26.3 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect github.com/sirupsen/logrus v1.9.4 // indirect @@ -244,7 +242,7 @@ require ( github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785 // indirect github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4 // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260428231901-a394dd724761 // indirect - github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.19 // indirect + github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 // indirect github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260430134932-681b7a7fe426 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20260408092456-3c6369888d4a // indirect @@ -259,12 +257,12 @@ require ( github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 // indirect github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect - github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/objx v0.5.3 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.16 // indirect github.com/suzuki-shunsuke/go-convmap v0.2.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/testcontainers/testcontainers-go v0.41.0 // indirect + github.com/testcontainers/testcontainers-go v0.42.0 // indirect github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect diff --git a/go.sum b/go.sum index c449231..dcf8ac0 100644 --- a/go.sum +++ b/go.sum @@ -270,8 +270,6 @@ github.com/digital-asset/dazl-client/v8 v8.9.0 h1:F2qTUWtHAjhGyRGV+xTim+VAFwM99F github.com/digital-asset/dazl-client/v8 v8.9.0/go.mod h1:q1KevCJ8FpH8je2MnnjN8/QUfhstB4fKpyKyqDtqFh0= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.5.3-0.20260325154711-31a1689cb0a1+incompatible h1:f51eIlZsZqGKXyNeCHs5oVo/xQiR9zh+pDYMfnu3VPQ= -github.com/docker/docker v28.5.3-0.20260325154711-31a1689cb0a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -678,12 +676,14 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= +github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= +github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= +github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y= github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= @@ -701,8 +701,6 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ= -github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -833,8 +831,8 @@ github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI= -github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= +github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= @@ -862,8 +860,8 @@ github.com/smartcontractkit/chainlink-common/keystore v1.1.0 h1:2wzySccgk2fpWusP github.com/smartcontractkit/chainlink-common/keystore v1.1.0/go.mod h1:6JexOOhPhknQ0QMuppFIlOpm6wCp54yZMxai+tWugwY= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= -github.com/smartcontractkit/chainlink-deployments-framework v0.101.0 h1:bTPDvJSLlMAibGuuewKK8hgVO3jBcyn/jaAiK2Agj98= -github.com/smartcontractkit/chainlink-deployments-framework v0.101.0/go.mod h1:d3twE7zrOtc0iuLs4EhBuaJAtAYOPZr+39nrXv4trw0= +github.com/smartcontractkit/chainlink-deployments-framework v0.102.0 h1:tAVJS+4/9q2V1avBfuJ71Mbpi7UmwbzRiCbzPL1rlmY= +github.com/smartcontractkit/chainlink-deployments-framework v0.102.0/go.mod h1:ByaFUBMTFqwibn96pn+OwujJ8gLOQByXf/PorM2KeiQ= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171 h1:HY+Ekr4+E3xokyNZ0oOj0gjO7B065uqTxa6wcXJfJto= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -880,8 +878,8 @@ github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4 h1:AEnxv4HM3WD1Rb github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4/go.mod h1:PjZD54vr6rIKEKQj6HNA4hllvYI/QpT+Zefj3tqkFAs= github.com/smartcontractkit/chainlink-sui v0.0.0-20260428231901-a394dd724761 h1:YwdUzW6/xCEa2Y5tGlLVlg+FICQPIKx1tIg1MHPFNOk= github.com/smartcontractkit/chainlink-sui v0.0.0-20260428231901-a394dd724761/go.mod h1:xJ1UT4DKu1znbsm4ehkrfr92rgn8Hxgcp3Z9rgfXRjM= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.19 h1:inTH0/PrEaVv4iLdGsdcrP/rX7KMrq/Roosr5nIA8io= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.19/go.mod h1:BALK9cj8sk12e15UF6uDhifHgIApa+6N11TcQfInEro= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.0 h1:Py3ZY0opZSK7a6zcuOsq0EYkQjUASv9UHb5Q7aiz+Ug= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.0/go.mod h1:8NnRD5t7yljxFC3ffIloVKkhWlul4a3oQ63FL7AZc6s= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 h1:RwZXxdIAOyjp6cwc9Quxgr38k8r7ACz+Lxh9o/A6oH0= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0= github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260430134932-681b7a7fe426 h1:DeQpkYzNYqAXfXnMwXmh5LfF86jDgvbvtB+zCgtovWA= @@ -898,8 +896,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12i github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20260403184524-b6409238958d h1:PvXor5Fjer7FIONSqYXbpd1LkA14hWrlAyxXzOrC9t8= github.com/smartcontractkit/libocr v0.0.0-20260403184524-b6409238958d/go.mod h1:PLdNK6GlqfxIWXzziPkU7dCAVlVFeYkyyW7AQY0R+4Q= -github.com/smartcontractkit/mcms v0.41.1 h1:rK5X7if29gRhL6yqpUwxwaLYV0CqgwSJivdDqEJGFv4= -github.com/smartcontractkit/mcms v0.41.1/go.mod h1:9AJhwHSVwV2mETizHBNfEF9CemL/Fmf0yPxNGdTtL/0= +github.com/smartcontractkit/mcms v0.42.0 h1:zzs+auX6BL6sRIVpgVbLUviwrvWi8Fxo5dOP+9Wx/gk= +github.com/smartcontractkit/mcms v0.42.0/go.mod h1:39OxzRApGN7HG+JGbjxdCxyo5lvV0H0REUPyh3CzDGU= github.com/smartcontractkit/quarantine v0.0.0-20251203215908-fd0551c6adf9 h1:MOEuXYogv+RStASb8dWsyescu/xkigSi/Sv45NEjV7A= github.com/smartcontractkit/quarantine v0.0.0-20251203215908-fd0551c6adf9/go.mod h1:iwy4yWFuK+1JeoIRTaSOA9pl+8Kf//26zezxEXrAQEQ= github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 h1:zxcODLrFytOKmAd8ty8S/XK6WcIEJEgRBaL7sY/7l4Y= @@ -938,8 +936,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -967,8 +965,8 @@ github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzg github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= -github.com/testcontainers/testcontainers-go v0.41.0 h1:mfpsD0D36YgkxGj2LrIyxuwQ9i2wCKAD+ESsYM1wais= -github.com/testcontainers/testcontainers-go v0.41.0/go.mod h1:pdFrEIfaPl24zmBjerWTTYaY0M6UHsqA1YSvsoU40MI= +github.com/testcontainers/testcontainers-go v0.42.0 h1:He3IhTzTZOygSXLJPMX7n44XtK+qhjat1nI9cneBbUY= +github.com/testcontainers/testcontainers-go v0.42.0/go.mod h1:vZjdY1YmUA1qEForxOIOazfsrdyORJAbhi0bp8plN30= github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 h1:AOtFXssrDlLm84A2sTTR/AhvJiYbrIuCO59d+Ro9Tb0= github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0/go.mod h1:k2a09UKhgSp6vNpliIY0QSgm4Hi7GXVTzWvWgUemu/8= github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -1517,6 +1515,8 @@ k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUy k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=