Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion chain/evm/provider/ctf_anvil_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ import (
"fmt"
"math/big"
"net/http"
"os"
"path"
"slices"
"strconv"
"strings"
"sync"
Expand All @@ -217,9 +220,11 @@ import (
"github.com/avast/retry-go/v4"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/crypto"
"github.com/rs/zerolog"
chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink-testing-framework/framework"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
ctfdocker "github.com/smartcontractkit/chainlink-testing-framework/lib/docker"
"github.com/smartcontractkit/freeport"
"github.com/testcontainers/testcontainers-go"

Expand Down Expand Up @@ -516,7 +521,18 @@ func (p *CTFAnvilChainProvider) GetNodeHTTPURL() string {
// Returns an error if the container termination fails.
func (p *CTFAnvilChainProvider) Cleanup(ctx context.Context) error {
if p.container != nil {
err := p.container.Terminate(ctx)
shouldSave, path, err := shouldSaveCtfContainerLogs(os.Getenv(saveContainerLogsEnvVar))
if err != nil {
return fmt.Errorf("failed to check if we should save the container logs: %w", err)
}

if shouldSave {
zlogger := zerolog.New(os.Stdout)
ctfdocker.WriteAllContainersLogs(zlogger, path)
zlogger.Info().Msgf("container logs saved to %q", path)
}

err = p.container.Terminate(ctx)
if err != nil {
return fmt.Errorf("failed to terminate Anvil container: %w", err)
}
Expand Down Expand Up @@ -714,3 +730,41 @@ func (p *CTFAnvilChainProvider) waitForAnvilReady(ctx context.Context, httpURL s
retry.DelayType(retry.FixedDelay),
)
}

const saveContainerLogsEnvVar = "CLDF_CONTAINER_LOGS"

func shouldSaveCtfContainerLogs(envVarValue string) (bool, string, error) {
if envVarValue == "" {
return false, "", nil
}

if path.IsAbs(envVarValue) {
if isDirectory(envVarValue) {
return true, envVarValue, nil
}

err := os.MkdirAll(envVarValue, 0o700)
if err != nil {
return false, "", fmt.Errorf("failed to create container logs dir: %w", err)
}

return true, envVarValue, nil
}

trueValues := []string{"1", "true", "on", "enabled"}
if slices.Contains(trueValues, strings.ToLower(envVarValue)) {
tmpDirPath, err := os.MkdirTemp("", "cldf-container-logs-*")
if err != nil {
return false, "", fmt.Errorf("failed to create temporary dir: %w", err)
}

return true, tmpDirPath, nil
}

return false, "", fmt.Errorf("invalid value for %s variable: %v", saveContainerLogsEnvVar, envVarValue)
}

func isDirectory(path string) bool {
fileInfo, err := os.Stat(path)
return err == nil && fileInfo.IsDir()
}
34 changes: 31 additions & 3 deletions chain/evm/provider/ctf_anvil_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
"testing"
"time"

"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/provider/rpcclient"
"github.com/smartcontractkit/freeport"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/provider/rpcclient"
)

func TestCTFAnvilChainProvider_Initialize(t *testing.T) {
Expand Down Expand Up @@ -517,3 +516,32 @@
assert.Nil(t, provider.container, "Container reference should remain nil after second cleanup")
})
}

func Test_shouldSaveCtfContainerLogs(t *testing.T) {
tests := []struct {
name string
envvar string
wantShouldSave bool
wantPath string
assertion assert.ErrorAssertionFunc
}{
{
name: "environment variable not set",
envvar: "",
wantShouldSave: false,
wantPath: "",
assertion: assert.NoError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Setenv(saveContainerLogsEnvVar, tt.envvar)

gotShouldSave, gotPath, err := shouldSaveCtfContainerLogs()

Check failure on line 540 in chain/evm/provider/ctf_anvil_provider_test.go

View workflow job for this annotation

GitHub Actions / Provider Tests

not enough arguments in call to shouldSaveCtfContainerLogs

tt.assertion(t, err)
assert.Equal(t, tt.wantShouldSave, gotShouldSave)
assert.Equal(t, tt.wantPath, gotPath)
})
}
}
2 changes: 2 additions & 0 deletions engine/cld/environment/anvil.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ type RPCs struct {
type ChainConfig struct {
ChainID string // chain id as per EIP-155
HTTPRPCs []RPCs // http rpcs to connect to the chain
Provider *evmprov.CTFAnvilChainProvider
}

// AnvilChainsOutput represents the output of the newAnvilChains function.
Expand Down Expand Up @@ -287,6 +288,7 @@ func newAnvilChains(

chainConfigsBySelector[chainSelector] = ChainConfig{
ChainID: chainIDStr,
Provider: provider,
HTTPRPCs: []RPCs{
{
External: provider.GetNodeHTTPURL(),
Expand Down
7 changes: 7 additions & 0 deletions engine/cld/legacy/cli/mcmsv2/mcms_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,13 @@ func buildExecuteForkCommand(lggr logger.Logger, domain cldf_domain.Domain, prop
if err != nil {
return fmt.Errorf("error creating config: %w", err)
}
defer func() {
for _, chainConfig := range cfg.forkedEnv.ChainConfigs {
if chainConfig.Provider != nil {
chainConfig.Provider.Cleanup(cmd.Context())
}
}
}()

// get the chain URL, chain ID and MCM contract address
url := cfg.forkedEnv.ChainConfigs[cfg.chainSelector].HTTPRPCs[0].External
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0
github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4
github.com/smartcontractkit/chainlink-testing-framework/framework v0.11.3
github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.6
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.2
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335
github.com/smartcontractkit/freeport v0.1.2
Expand Down Expand Up @@ -227,7 +228,7 @@ require (
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/rs/zerolog v1.33.0
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/samber/lo v1.49.1 // indirect
Expand Down Expand Up @@ -284,7 +285,6 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
golang.org/x/net v0.43.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,8 @@ github.com/smartcontractkit/chainlink-sui v0.0.0-20251013155034-5f85c5f450ab h1:
github.com/smartcontractkit/chainlink-sui v0.0.0-20251013155034-5f85c5f450ab/go.mod h1:VlyZhVw+a93Sk8rVHOIH6tpiXrMzuWLZrjs1eTIExW8=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.11.3 h1:crYKFHTxxt1TNYuPOptjVyJdW4wO15aV5vVuEeLhICY=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.11.3/go.mod h1:ssfyl4ynbxSyASGztjuAxhsum5i6uZSHM7Dd0v2p8sc=
github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.6 h1:t1db5+sEbmw/26xQVDqyeY448V4RW8xtAl4eNGpd0uw=
github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.6/go.mod h1:dgwtcefGr+0i+C2S6V/Xgntzm7E5CPxXMyi2OnQvnHI=
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.2 h1:ZJ/8Jx6Be5//TyjPi1pS1uotnmcYq5vVkSyISIymSj8=
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.2/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0=
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335 h1:7bxYNrPpygn8PUSBiEKn8riMd7CXMi/4bjTy0fHhcrY=
Expand Down
Loading