diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 2e4a710ac97..1b0d0d091ed 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -110,6 +110,7 @@ jobs: echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY build-test-image: + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'schedule' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || contains(join(github.event.pull_request.labels.*.name, ' '), 'build-test-image') environment: integration permissions: id-token: write @@ -139,14 +140,36 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - eth-smoke-tests-matrix: + compare-tests: + needs: [changes] + runs-on: ubuntu-latest + name: Compare/Build Automation Test List + outputs: + matrix: ${{ env.MATRIX_JSON }} + steps: + - name: Checkout the repo + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - name: Compare Test Lists + run: | + cd ./integration-tests + ./scripts/compareTestList.sh ./smoke/automation_test.go + ./scripts/compareTestList.sh ./smoke/keeper_test.go + - name: Build Test Matrix Lists + id: build-test-matrix-list + run: | + cd ./integration-tests + MATRIX_JSON_AUTOMATION=$(./scripts/buildTestMatrixList.sh ./smoke/automation_test.go automation ubuntu20.04-8cores-32GB) + MATRIX_JSON_KEEPER=$(./scripts/buildTestMatrixList.sh ./smoke/keeper_test.go keeper ubuntu20.04-8cores-32GB) + COMBINED_ARRAY=$(jq -c -n "$MATRIX_JSON_AUTOMATION + $MATRIX_JSON_KEEPER") + echo "MATRIX_JSON=${COMBINED_ARRAY}" >> $GITHUB_ENV + eth-smoke-tests-matrix-automation: environment: integration permissions: checks: write pull-requests: write id-token: write contents: read - needs: [build-chainlink, changes, build-test-image] + needs: [build-chainlink, changes, compare-tests] env: SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 CHAINLINK_COMMIT_SHA: ${{ github.sha }} @@ -155,16 +178,7 @@ jobs: strategy: fail-fast: false matrix: - product: - - name: automation - nodes: 19 - os: ubuntu-latest - pyroscope_env: ci-smoke-automation-evm-simulated - # temporarily disabled - # - name: ocr2vrf - # nodes: 2 - # os: ubuntu-latest - # pyroscope_env: ci-smoke-ocr2vrf-evm-simulated + product: ${{fromJson(needs.compare-tests.outputs.matrix)}} runs-on: ${{ matrix.product.os }} name: ETH Smoke Tests ${{ matrix.product.name }} steps: @@ -172,23 +186,31 @@ jobs: uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Build Go Test Command + id: build-go-test-command + run: | + # if the matrix.product.run is set, use it for a different command + if [ "${{ matrix.product.run }}" != "" ]; then + echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" + else + echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" + fi ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12 env: - TESTCONTAINERS_RYUK_DISABLED: true PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: - test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ./smoke/${{ matrix.product.name }}_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt + test_command_to_run: make test_need_operator_assets && cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ github.sha }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_location: ./integration-tests/smoke/logs - publish_check_name: EVM Smoke Test Results ${{ matrix.product.name }} + publish_check_name: ${{ matrix.product.name }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} @@ -196,28 +218,6 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - ## Run this step when changes that do not need the test to run are made - - name: Run Setup - if: needs.changes.outputs.src == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@00c6214deb10a3f374c6d3430c32c5202015d463 # v2.2.12 - with: - test_download_vendor_packages_command: cd ./integration-tests && go mod download - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: 'true' - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - - name: Upload test log - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - if: failure() - with: - name: test-log-${{ matrix.product.name }} - path: /tmp/gotest.log - retention-days: 7 - continue-on-error: true - name: Collect Metrics if: always() id: collect-gha-metrics @@ -228,8 +228,7 @@ jobs: this-job-name: ETH Smoke Tests ${{ matrix.product.name }} test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' continue-on-error: true - - eth-smoke-tests-matrix-docker: + eth-smoke-tests-matrix: environment: integration permissions: checks: write @@ -286,98 +285,6 @@ jobs: nodes: 1 os: ubuntu20.04-8cores-32GB pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - - # Keeper tests split out to use minimal environments - - name: keeper-1 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperBasicSmoke$ - - name: keeper-2 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperBlockCountPerTurn/registry_1_1$ - - name: keeper-3 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperBlockCountPerTurn/registry_1_2$ - - name: keeper-4 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperBlockCountPerTurn/registry_1_3$ - - name: keeper-5 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperSimulation$ - - name: keeper-6 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperCheckPerformGasLimit/registry_1_2$ - - name: keeper-7 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperCheckPerformGasLimit/registry_1_3$ - - name: keeper-8 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperRegisterUpkeep$ - - name: keeper-9 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperAddFunds$ - - name: keeper-10 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperRemove$ - - name: keeper-11 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperPauseRegistry$ - - name: keeper-12 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperMigrateRegistry$ - - name: keeper-13 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperNodeDown/registry_1_1$ - - name: keeper-14 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperNodeDown/registry_1_2$ - - name: keeper-15 - nodes: 1 - os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-keeper-evm-simulated - file: keeper - run: -run ^TestKeeperNodeDown/registry_1_3$ runs-on: ${{ matrix.product.os }} name: ETH Smoke Tests ${{ matrix.product.name }} steps: @@ -409,7 +316,7 @@ jobs: cl_image_tag: ${{ github.sha }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_location: ./integration-tests/smoke/logs - publish_check_name: EVM Smoke Test Results ${{ matrix.product.name }} + publish_check_name: ${{ matrix.product.name }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} @@ -454,10 +361,10 @@ jobs: if: always() runs-on: ubuntu-latest name: ETH Smoke Tests - needs: [eth-smoke-tests-matrix,eth-smoke-tests-matrix-docker] + needs: [eth-smoke-tests-matrix, eth-smoke-tests-matrix-automation] steps: - name: Check smoke test matrix status - if: needs.eth-smoke-tests-matrix.result != 'success' || needs.eth-smoke-tests-matrix-docker.result != 'success' + if: needs.eth-smoke-tests-matrix.result != 'success' || needs.eth-smoke-tests-matrix-automation.result != 'success' run: exit 1 - name: Collect Metrics if: always() @@ -699,7 +606,7 @@ jobs: CONTRACT_ARTIFACTS_PATH: contracts/target/deploy steps: - name: Collect Metrics - if: needs.changes.outputs.src == 'true' + if: needs.changes.outputs.src == 'true' && needs.solana-test-image-exists.outputs.exists == 'false' id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@d2c2b7bdc9012651230b2608a1bcb0c48538b6ec with: @@ -708,6 +615,7 @@ jobs: this-job-name: Solana Build Test Image continue-on-error: true - name: Checkout the repo + if: needs.changes.outputs.src == 'true' && needs.solana-test-image-exists.outputs.exists == 'false' uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: repository: smartcontractkit/chainlink-solana @@ -721,6 +629,8 @@ jobs: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + - run: echo "this exists so we don't have to run anything else if the build is skipped" + if: needs.changes.outputs.src == 'false' || needs.solana-test-image-exists.outputs.exists == 'true' solana-smoke-tests: environment: integration diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go new file mode 100644 index 00000000000..d2e2fde3217 --- /dev/null +++ b/integration-tests/actions/actions_local.go @@ -0,0 +1,25 @@ +// Package actions enables common chainlink interactions +package actions + +import ( + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" +) + +// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment +// to apply the upgrades +func UpgradeChainlinkNodeVersionsLocal( + newImage, newVersion string, + nodes ...*test_env.ClNode, +) error { + if newImage == "" && newVersion == "" { + return errors.New("unable to upgrade node version, found empty image and version, must provide either a new image or a new version") + } + for _, node := range nodes { + if err := node.UpgradeVersion(node.NodeConfig, newImage, newVersion); err != nil { + return err + } + } + return nil +} diff --git a/integration-tests/actions/automation_ocr_helpers_local.go b/integration-tests/actions/automation_ocr_helpers_local.go new file mode 100644 index 00000000000..dce55e42275 --- /dev/null +++ b/integration-tests/actions/automation_ocr_helpers_local.go @@ -0,0 +1,258 @@ +package actions + +//revive:disable:dot-imports +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/lib/pq" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/require" + "gopkg.in/guregu/null.v4" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config" + ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config" + + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/store/models" +) + +func BuildAutoOCR2ConfigVarsLocal( + t *testing.T, + chainlinkNodes []*client.ChainlinkClient, + registryConfig contracts.KeeperRegistrySettings, + registrar string, + deltaStage time.Duration, +) (contracts.OCRv2Config, error) { + return BuildAutoOCR2ConfigVarsWithKeyIndexLocal(t, chainlinkNodes, registryConfig, registrar, deltaStage, 0) +} + +func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( + t *testing.T, + chainlinkNodes []*client.ChainlinkClient, + registryConfig contracts.KeeperRegistrySettings, + registrar string, + deltaStage time.Duration, + keyIndex int, +) (contracts.OCRv2Config, error) { + l := utils.GetTestLogger(t) + S, oracleIdentities, err := GetOracleIdentitiesWithKeyIndexLocal(chainlinkNodes, keyIndex) + if err != nil { + return contracts.OCRv2Config{}, err + } + + var offC []byte + var signerOnchainPublicKeys []types.OnchainPublicKey + var transmitterAccounts []types.Account + var f uint8 + var offchainConfigVersion uint64 + var offchainConfig []byte + + if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_1 { + offC, err = json.Marshal(ocr2keepers30config.OffchainConfig{ + TargetProbability: "0.999", + TargetInRounds: 1, + PerformLockoutWindow: 3600000, // Intentionally set to be higher than in prod for testing purpose + GasLimitPerReport: 5_300_000, + GasOverheadPerUpkeep: 300_000, + MinConfirmations: 0, + MaxUpkeepBatchSize: 1, + }) + if err != nil { + return contracts.OCRv2Config{}, err + } + + signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err = ocr3.ContractSetConfigArgsForTests( + 10*time.Second, // deltaProgress time.Duration, + 15*time.Second, // deltaResend time.Duration, + 500*time.Millisecond, // deltaInitial time.Duration, + 1000*time.Millisecond, // deltaRound time.Duration, + 200*time.Millisecond, // deltaGrace time.Duration, + 300*time.Millisecond, // deltaCertifiedCommitRequest time.Duration + deltaStage, // deltaStage time.Duration, + 24, // rMax uint64, + S, // s []int, + oracleIdentities, // oracles []OracleIdentityExtra, + offC, // reportingPluginConfig []byte, + 20*time.Millisecond, // maxDurationQuery time.Duration, + 20*time.Millisecond, // maxDurationObservation time.Duration, // good to here + 1200*time.Millisecond, // maxDurationShouldAcceptAttestedReport time.Duration, + 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, + 1, // f int, + nil, // onchainConfig []byte, + ) + if err != nil { + return contracts.OCRv2Config{}, err + } + } else { + offC, err = json.Marshal(ocr2keepers20config.OffchainConfig{ + TargetProbability: "0.999", + TargetInRounds: 1, + PerformLockoutWindow: 3600000, // Intentionally set to be higher than in prod for testing purpose + GasLimitPerReport: 5_300_000, + GasOverheadPerUpkeep: 300_000, + SamplingJobDuration: 3000, + MinConfirmations: 0, + MaxUpkeepBatchSize: 1, + }) + if err != nil { + return contracts.OCRv2Config{}, err + } + + signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err = ocr2.ContractSetConfigArgsForTests( + 10*time.Second, // deltaProgress time.Duration, + 15*time.Second, // deltaResend time.Duration, + 3000*time.Millisecond, // deltaRound time.Duration, + 200*time.Millisecond, // deltaGrace time.Duration, + deltaStage, // deltaStage time.Duration, + 24, // rMax uint8, + S, // s []int, + oracleIdentities, // oracles []OracleIdentityExtra, + offC, // reportingPluginConfig []byte, + 20*time.Millisecond, // maxDurationQuery time.Duration, + 20*time.Millisecond, // maxDurationObservation time.Duration, + 1200*time.Millisecond, // maxDurationReport time.Duration, + 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, + 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, + 1, // f int, + nil, // onchainConfig []byte, + ) + if err != nil { + return contracts.OCRv2Config{}, err + } + } + + var signers []common.Address + for _, signer := range signerOnchainPublicKeys { + require.Equal(t, 20, len(signer), "OnChainPublicKey '%v' has wrong length for address", signer) + signers = append(signers, common.BytesToAddress(signer)) + } + + var transmitters []common.Address + for _, transmitter := range transmitterAccounts { + require.True(t, common.IsHexAddress(string(transmitter)), "TransmitAccount '%s' is not a valid Ethereum address", string(transmitter)) + transmitters = append(transmitters, common.HexToAddress(string(transmitter))) + } + + onchainConfig, err := registryConfig.EncodeOnChainConfig(registrar) + if err != nil { + return contracts.OCRv2Config{}, err + } + + l.Info().Msg("Done building OCR config") + return contracts.OCRv2Config{ + Signers: signers, + Transmitters: transmitters, + F: f, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + }, nil +} + +// CreateOCRKeeperJobs bootstraps the first node and to the other nodes sends ocr jobs +func CreateOCRKeeperJobsLocal( + chainlinkNodes []*client.ChainlinkClient, + registryAddr string, + chainID int64, + keyIndex int, + registryVersion ethereum.KeeperRegistryVersion, +) error { + bootstrapNode := chainlinkNodes[0] + bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() + if err != nil { + log.Error().Err(err).Msg("Shouldn't fail reading P2P keys from bootstrap node") + return err + } + bootstrapP2PId := bootstrapP2PIds.Data[0].Attributes.PeerID + + var contractVersion string + if registryVersion == ethereum.RegistryVersion_2_1 { + contractVersion = "v2.1" + } else if registryVersion == ethereum.RegistryVersion_2_0 { + contractVersion = "v2.0" + } else { + return errors.New("v2.0 and v2.1 are the only supported versions") + } + + bootstrapSpec := &client.OCR2TaskJobSpec{ + Name: "ocr2 bootstrap node " + registryAddr, + JobType: "bootstrap", + OCR2OracleSpec: job.OCR2OracleSpec{ + ContractID: registryAddr, + Relay: "evm", + RelayConfig: map[string]interface{}{ + "chainID": int(chainID), + }, + ContractConfigTrackerPollInterval: *models.NewInterval(time.Second * 15), + }, + } + _, err = bootstrapNode.MustCreateJob(bootstrapSpec) + if err != nil { + log.Error().Err(err).Msg("Shouldn't fail creating bootstrap job on bootstrap node") + return err + } + + P2Pv2Bootstrapper := fmt.Sprintf("%s@%s:%d", bootstrapP2PId, bootstrapNode.InternalIP(), 6690) + for nodeIndex := 1; nodeIndex < len(chainlinkNodes); nodeIndex++ { + nodeTransmitterAddress, err := chainlinkNodes[nodeIndex].EthAddresses() + if err != nil { + log.Error().Err(err).Msgf("Shouldn't fail getting primary ETH address from OCR node %d", nodeIndex+1) + return err + } + nodeOCRKeys, err := chainlinkNodes[nodeIndex].MustReadOCR2Keys() + if err != nil { + log.Error().Err(err).Msgf("Shouldn't fail getting OCR keys from OCR node %d", nodeIndex+1) + return err + } + var nodeOCRKeyId []string + for _, key := range nodeOCRKeys.Data { + if key.Attributes.ChainType == string(chaintype.EVM) { + nodeOCRKeyId = append(nodeOCRKeyId, key.ID) + break + } + } + + autoOCR2JobSpec := client.OCR2TaskJobSpec{ + Name: "ocr2 " + registryAddr, + JobType: "offchainreporting2", + OCR2OracleSpec: job.OCR2OracleSpec{ + PluginType: "ocr2automation", + Relay: "evm", + RelayConfig: map[string]interface{}{ + "chainID": int(chainID), + }, + PluginConfig: map[string]interface{}{ + "mercuryCredentialName": "\"cred1\"", + "contractVersion": "\"" + contractVersion + "\"", + }, + ContractConfigTrackerPollInterval: *models.NewInterval(time.Second * 15), + ContractID: registryAddr, // registryAddr + OCRKeyBundleID: null.StringFrom(nodeOCRKeyId[0]), // get node ocr2config.ID + TransmitterID: null.StringFrom(nodeTransmitterAddress[keyIndex]), // node addr + P2PV2Bootstrappers: pq.StringArray{P2Pv2Bootstrapper}, // bootstrap node key and address @bootstrap:8000 + }, + } + + _, err = chainlinkNodes[nodeIndex].MustCreateJob(&autoOCR2JobSpec) + if err != nil { + log.Error().Err(err).Msgf("Shouldn't fail creating OCR Task job on OCR node %d err: %+v", nodeIndex+1, err) + return err + } + + } + log.Info().Msg("Done creating OCR automation jobs") + return nil +} diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index a78f9e52ad6..4c2213b03ee 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -46,6 +46,8 @@ type ClNode struct { NodeSecretsConfigTOML string PostgresDb *test_env.PostgresDb lw *logwatch.LogWatch + ContainerImage string + ContainerVersion string } type ClNodeOption = func(c *ClNode) @@ -101,6 +103,19 @@ func (n *ClNode) Restart(cfg *chainlink.Config) error { return n.StartContainer() } +// UpgradeVersion restarts the cl node with new image and version +func (n *ClNode) UpgradeVersion(cfg *chainlink.Config, newImage, newVersion string) error { + if newVersion == "" { + return fmt.Errorf("new version is empty") + } + if newImage == "" { + newImage = os.Getenv("CHAINLINK_IMAGE") + } + n.ContainerImage = newImage + n.ContainerVersion = newVersion + return n.Restart(n.NodeConfig) +} + func (n *ClNode) PrimaryETHAddress() (string, error) { return n.API.PrimaryEthAddress() } @@ -203,7 +218,6 @@ func (n *ClNode) Fund(evmClient blockchain.EVMClient, amount *big.Float) error { } return evmClient.Fund(toAddress, amount, gasEstimates) } - func (n *ClNode) StartContainer() error { err := n.PostgresDb.StartContainer() if err != nil { @@ -313,18 +327,24 @@ func (n *ClNode) getContainerRequest() ( adminCredsPath := "/home/admin-credentials.txt" apiCredsPath := "/home/api-credentials.txt" - image, ok := os.LookupEnv("CHAINLINK_IMAGE") - if !ok { - return nil, errors.New("CHAINLINK_IMAGE env must be set") + if n.ContainerImage == "" { + image, ok := os.LookupEnv("CHAINLINK_IMAGE") + if !ok { + return nil, errors.New("CHAINLINK_IMAGE env must be set") + } + n.ContainerImage = image } - tag, ok := os.LookupEnv("CHAINLINK_VERSION") - if !ok { - return nil, errors.New("CHAINLINK_VERSION env must be set") + if n.ContainerVersion == "" { + version, ok := os.LookupEnv("CHAINLINK_VERSION") + if !ok { + return nil, errors.New("CHAINLINK_VERSION env must be set") + } + n.ContainerVersion = version } return &tc.ContainerRequest{ Name: n.ContainerName, - Image: fmt.Sprintf("%s:%s", image, tag), + Image: fmt.Sprintf("%s:%s", n.ContainerImage, n.ContainerVersion), ExposedPorts: []string{"6688/tcp"}, Entrypoint: []string{"chainlink", "-c", configPath, diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 0874c743853..f485252941d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -20,7 +20,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-env v0.36.0 - github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c + github.com/smartcontractkit/chainlink-testing-framework v1.16.3-0.20230901233155-c2c6e9c075c2 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20230816220705-665e93233ae5 github.com/smartcontractkit/ocr2keepers v0.7.20 @@ -360,7 +360,7 @@ require ( github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/alertmanager v0.25.0 // indirect + github.com/prometheus/alertmanager v0.25.1 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c3a08560bda..029573053cf 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -2119,8 +2119,8 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k= -github.com/prometheus/alertmanager v0.25.0 h1:vbXKUR6PYRiZPRIKfmXaG+dmCKG52RtPL4Btl8hQGvg= -github.com/prometheus/alertmanager v0.25.0/go.mod h1:MEZ3rFVHqKZsw7IcNS/m4AWZeXThmJhumpiWR4eHU/w= +github.com/prometheus/alertmanager v0.25.1 h1:LGBNMspOfv8h7brb+LWj2wnwBCg2ZuuKWTh6CAVw2/Y= +github.com/prometheus/alertmanager v0.25.1/go.mod h1:MEZ3rFVHqKZsw7IcNS/m4AWZeXThmJhumpiWR4eHU/w= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -2258,8 +2258,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97ac github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97aca/go.mod h1:RIUJXn7EVp24TL2p4FW79dYjyno23x5mjt1nKN+5WEk= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918 h1:ByVauKFXphRlSNG47lNuxZ9aicu+r8AoNp933VRPpCw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918/go.mod h1:/yp/sqD8Iz5GU5fcercjrw0ivJF7HDcupYg+Gjr7EPg= -github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c h1:8/L+5JupikVsMga6z0WBElp1RgRO6BB5BF+QsBsSrOI= -github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c/go.mod h1:t6FJX3akEfAO31p96ru0ilNPfE9P2UshUlXTIkI58LM= +github.com/smartcontractkit/chainlink-testing-framework v1.16.3-0.20230901233155-c2c6e9c075c2 h1:llbIpJD17IXj0TPwE1r/bgB3X7Gkk9LKsxsXkTBmGe0= +github.com/smartcontractkit/chainlink-testing-framework v1.16.3-0.20230901233155-c2c6e9c075c2/go.mod h1:xtLIwNaVw/4zWSMnA7j8u1t9tKh0OykvIsYI4xZT3B4= github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472 h1:x3kNwgFlDmbE/n0gTSRMt9GBDfsfGrs4X9b9arPZtFI= github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/scripts/buildTestMatrixList.sh b/integration-tests/scripts/buildTestMatrixList.sh new file mode 100755 index 00000000000..25f72715095 --- /dev/null +++ b/integration-tests/scripts/buildTestMatrixList.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# requires a path to a test file to compare the test list against +# requires a matrix job name to be passed in, for example "automation" +# requires a node label to be passed in, for example "ubuntu-latest" + +set -e + +# get this scripts directory +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cd "$SCRIPT_DIR"/../ || exit 1 + +FILENAME=$1 +MATRIX_JOB_NAME=$2 +NODE_LABEL=$3 + +# Get list of test names from JSON file +JSONFILE="${FILENAME}_test_list.json" +COUNTER=1 + +# Build a JSON object in the format expected by our integration-tests workflow matrix +matrix_output() { + local counter=$1 + local job_name=$2 + local test_name=$3 + local node_label=$4 + local counter_out=$(printf "%02d\n" $counter) + echo -n "{\"name\": \"${job_name}-${counter_out}\", \"file\": \"${job_name}\",\"nodes\": 1, \"os\": \"${node_label}\", \"pyroscope_env\": \"ci-smoke-${job_name}-evm-simulated\", \"run\": \"-run '^${test_name}$'\"}" +} + +# Read the JSON file and loop through 'tests' and 'run' +jq -c '.tests[]' ${JSONFILE} | while read -r test; do + testName=$(echo ${test} | jq -r '.name') + subTests=$(echo ${test} | jq -r '.run[]?.name // empty') + output="" + + # Loop through subtests, if any, and print in the desired format + if [ -n "$subTests" ]; then + for subTest in $subTests; do + if [ $COUNTER -ne 1 ]; then + echo -n "," + fi + matrix_output $COUNTER $MATRIX_JOB_NAME "${testName}/${subTest}" ${NODE_LABEL} + ((COUNTER++)) + done + else + if [ $COUNTER -ne 1 ]; then + echo -n "," + fi + matrix_output $COUNTER $MATRIX_JOB_NAME "${testName}" ${NODE_LABEL} + ((COUNTER++)) + fi + +done > "./tmpout.json" +OUTPUT=$(cat ./tmpout.json) +echo "[${OUTPUT}]" +rm ./tmpout.json diff --git a/integration-tests/scripts/compareTestList.sh b/integration-tests/scripts/compareTestList.sh new file mode 100755 index 00000000000..8cc916c7d63 --- /dev/null +++ b/integration-tests/scripts/compareTestList.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# accepts a path to a test file to compare the test list against + +set -e + +# get this scripts directory +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cd "$SCRIPT_DIR"/../ || exit 1 + +FILENAME=$1 + +TESTLIST=$(cat ${FILENAME} | grep "func Test.*\(t \*testing.T\)" | grep -o 'Test[A-Za-z0-9_]*') + +# convert the test list from above into json in the form {"tests":[{"name":"TestName"}]} +TESTLISTJSON=$(echo $TESTLIST | jq -R -s -c '{tests: split(" ") | map({"name":.})}') + +# Get list of test names from JSON file +JSONFILE="${FILENAME}_test_list.json" +JSONTESTLIST=$(jq -r '.tests[].name' ${JSONFILE}) + +# Convert lists to arrays +TESTLIST_ARRAY=($(echo "$TESTLIST")) +JSONTESTLIST_ARRAY=($(echo "$JSONTESTLIST")) + +ERRORS_FOUND=false + +# Compare TESTLIST_ARRAY against JSONTESTLIST_ARRAY +for test in "${TESTLIST_ARRAY[@]}"; do + if [[ ! " ${JSONTESTLIST_ARRAY[@]} " =~ " ${test} " ]]; then + echo "$test exists only in ${FILENAME}." + ERRORS_FOUND=true + fi +done + +# Compare JSONTESTLIST_ARRAY against TESTLIST_ARRAY +for test in "${JSONTESTLIST_ARRAY[@]}"; do + if [[ ! " ${TESTLIST_ARRAY[@]} " =~ " ${test} " ]]; then + echo "$test exists only in ${JSONFILE}." + ERRORS_FOUND=true + fi +done + +if [ "$ERRORS_FOUND" = true ] ; then + echo "Test lists do not match. Please update ${JSONFILE} with the updated tests to run in CI." + exit 1 +fi diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 57ca733b594..109f681ea81 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -6,19 +6,13 @@ import ( "math/big" "os" "strconv" - "strings" "testing" "time" "github.com/onsi/gomega" - "github.com/rs/zerolog/log" "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-env/environment" "github.com/smartcontractkit/chainlink-env/logging" - "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink" - eth "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils" @@ -26,7 +20,11 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/networks" + "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" + "github.com/smartcontractkit/chainlink/v2/core/store/models" ) const ( @@ -38,25 +36,6 @@ const ( ) var ( - automationBaseTOML = `[Feature] -LogPoller = true - -[OCR2] -Enabled = true - -[Keeper] -TurnLookBack = 0 - -[Keeper.Registry] -SyncInterval = '5m' -PerformGasOverhead = 150_000 - -[P2P] -[P2P.V2] -Enabled = true -AnnounceAddresses = ["0.0.0.0:6690"] -ListenAddresses = ["0.0.0.0:6690"]` - defaultOCRRegistryConfig = contracts.KeeperRegistrySettings{ PaymentPremiumPPB: uint32(200000000), FlatFeeMicroLINK: uint32(0), @@ -128,12 +107,9 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { require.NoError(t, err, "Error getting upgrade version") testName = "node-upgrade" } - chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, onlyStartRunner, testEnv := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupAutomationTestDocker( t, testName, registryVersion, defaultOCRRegistryConfig, nodeUpgrade, ) - if onlyStartRunner { - return - } // Use the name to determine if this is a log trigger or not isLogTrigger := name == "registry_2_1_logtrigger" @@ -181,7 +157,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { expect := 5 // Upgrade the nodes one at a time and check that the upkeeps are still being performed for i := 0; i < 5; i++ { - actions.UpgradeChainlinkNodeVersions(testEnv, upgradeImage, upgradeVersion, chainlinkNodes[i]) + actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, testEnv.CLNodes[i]) time.Sleep(time.Second * 10) expect = expect + 5 gom.Eventually(func(g gomega.Gomega) { @@ -242,13 +218,9 @@ func TestAutomationAddFunds(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "add-funds", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(1), automationDefaultUpkeepGasLimit, false) @@ -298,13 +270,9 @@ func TestAutomationPauseUnPause(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "pause-unpause", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) @@ -386,13 +354,9 @@ func TestAutomationRegisterUpkeep(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "register-upkeep", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) @@ -462,12 +426,9 @@ func TestAutomationPauseRegistry(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "pause-registry", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) gom := gomega.NewGomegaWithT(t) @@ -524,13 +485,9 @@ func TestAutomationKeeperNodesDown(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "keeper-nodes-down", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) gom := gomega.NewGomegaWithT(t) @@ -614,13 +571,9 @@ func TestAutomationPerformSimulation(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "perform-simulation", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumersPerformance, _ := actions.DeployPerformanceConsumers( t, @@ -683,13 +636,9 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "gas-limit", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers( t, @@ -767,7 +716,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { highCheckGasLimit := automationDefaultRegistryConfig highCheckGasLimit.CheckGasLimit = uint32(5000000) highCheckGasLimit.RegistryVersion = registryVersion - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 30*time.Second) + ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(t, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 30*time.Second) require.NoError(t, err, "Error building OCR config") err = registry.SetConfig(highCheckGasLimit, ocrConfig) @@ -801,13 +750,9 @@ func TestUpdateCheckData(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - - chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( + chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( t, "update-check-data", registryVersion, defaultOCRRegistryConfig, false, ) - if onlyStartRunner { - return - } performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers( t, @@ -865,103 +810,78 @@ func TestUpdateCheckData(t *testing.T) { } } -func setupAutomationTest( +func setupAutomationTestDocker( t *testing.T, testName string, registryVersion ethereum.KeeperRegistryVersion, registryConfig contracts.KeeperRegistrySettings, statefulDb bool, ) ( - chainClient blockchain.EVMClient, - chainlinkNodes []*client.ChainlinkK8sClient, - contractDeployer contracts.ContractDeployer, - linkToken contracts.LinkToken, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - onlyStartRunner bool, - testEnvironment *environment.Environment, + blockchain.EVMClient, + []*client.ChainlinkClient, + contracts.ContractDeployer, + contracts.LinkToken, + contracts.KeeperRegistry, + contracts.KeeperRegistrar, + *test_env.CLClusterTestEnv, ) { // Add registry version to config registryConfig.RegistryVersion = registryVersion - network := networks.SelectedNetwork - evmConfig := eth.New(nil) - if !network.Simulated { - evmConfig = eth.New(ð.Props{ - NetworkName: network.Name, - Simulated: network.Simulated, - WsURLs: network.URLs, - }) - } - chainlinkProps := map[string]any{ - "toml": client.AddNetworksConfig(automationBaseTOML, network), - "secretsToml": client.AddSecretTomlConfig("https://google.com", "username1", "password1"), - "db": map[string]any{ - "stateful": statefulDb, - }, - } - - cd, err := chainlink.NewDeployment(5, chainlinkProps) - require.NoError(t, err, "Failed to create chainlink deployment") - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("smoke-automation-%s-%s", testName, strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), - Test: t, - }). - AddHelm(evmConfig). - AddHelmCharts(cd) - err = testEnvironment.Run() - - require.NoError(t, err, "Error setting up test environment") - - onlyStartRunner = testEnvironment.WillUseRemoteRunner() - if !onlyStartRunner { - chainClient, err = blockchain.NewEVMClient(network, testEnvironment) - require.NoError(t, err, "Error connecting to blockchain") - contractDeployer, err = contracts.NewContractDeployer(chainClient) - require.NoError(t, err, "Error building contract deployer") - chainlinkNodes, err = client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Error connecting to Chainlink nodes") - t.Cleanup(func() { - if err := actions.ReturnFunds(chainlinkNodes, chainClient); err != nil { - log.Error().Err(err).Msg("Error returning funds") - } - }) - chainClient.ParallelTransactions(true) - - txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) - require.NoError(t, err, "Error funding Chainlink nodes") - - linkToken, err = contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Error deploying LINK token") - - registry, registrar = actions.DeployAutoOCRRegistryAndRegistrar( - t, - registryVersion, - registryConfig, - linkToken, - contractDeployer, - chainClient, - ) - - // Fund the registry with LINK - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(defaultAmountOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, registryVersion) - nodesWithoutBootstrap := chainlinkNodes[1:] - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, registryConfig, registrar.Address(), 30*time.Second) - require.NoError(t, err, "Error building OCR config vars") - err = registry.SetConfig(automationDefaultRegistryConfig, ocrConfig) - require.NoError(t, err, "Registry config should be set successfully") - require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") - // Register cleanup for any test - t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient) - require.NoError(t, err, "Error tearing down environment") - }) - } - return chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, onlyStartRunner, testEnvironment + // build the node config + clNodeConfig := node.NewConfig(node.BaseConf) + syncInterval := models.MustMakeDuration(5 * time.Minute) + clNodeConfig.Feature.LogPoller = it_utils.Ptr[bool](true) + clNodeConfig.OCR2.Enabled = it_utils.Ptr[bool](true) + clNodeConfig.Keeper.TurnLookBack = it_utils.Ptr[int64](int64(0)) + clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval + clNodeConfig.Keeper.Registry.PerformGasOverhead = it_utils.Ptr[uint32](uint32(150000)) + clNodeConfig.P2P.V2.Enabled = it_utils.Ptr[bool](true) + clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"} + clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"} + + // launch the environment + env, err := test_env.NewCLTestEnvBuilder(). + WithGeth(). + WithMockServer(1). + WithCLNodes(5). + WithCLNodeConfig(clNodeConfig). + WithFunding(big.NewFloat(.5)). + Build() + require.NoError(t, err, "Error deploying test environment") + env.ParallelTransactions(true) + + txCost, err := env.EVMClient.EstimateCostForChainlinkOperations(1000) + require.NoError(t, err, "Error estimating cost for Chainlink Operations") + nodeClients := env.GetAPIs() + workerNodes := nodeClients[1:] + err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, txCost) + require.NoError(t, err, "Error funding Chainlink nodes") + + linkToken, err := env.ContractDeployer.DeployLinkTokenContract() + require.NoError(t, err, "Error deploying LINK token") + + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( + t, + registryVersion, + registryConfig, + linkToken, + env.ContractDeployer, + env.EVMClient, + ) + + // Fund the registry with LINK + err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(defaultAmountOfUpkeeps)))) + require.NoError(t, err, "Funding keeper registry contract shouldn't fail") + + err = actions.CreateOCRKeeperJobsLocal(nodeClients, registry.Address(), network.ChainID, 0, registryVersion) + require.NoError(t, err, "Error creating OCR Keeper Jobs") + ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(t, workerNodes, registryConfig, registrar.Address(), 30*time.Second) + require.NoError(t, err, "Error building OCR config vars") + err = registry.SetConfig(automationDefaultRegistryConfig, ocrConfig) + require.NoError(t, err, "Registry config should be set successfully") + require.NoError(t, env.EVMClient.WaitForEvents(), "Waiting for config to be set") + + return env.EVMClient, nodeClients, env.ContractDeployer, linkToken, registry, registrar, env } diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json new file mode 100644 index 00000000000..badb7d6b3eb --- /dev/null +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -0,0 +1,106 @@ +{ + "tests": [ + { + "name": "TestAutomationBasic", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1_conditional" + }, + { + "name": "registry_2_1_logtrigger" + } + ] + }, + { + "name": "TestAutomationAddFunds", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationPauseUnPause", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationRegisterUpkeep", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationPauseRegistry", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationKeeperNodesDown", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationPerformSimulation", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestAutomationCheckPerformGasLimit", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + }, + { + "name": "TestUpdateCheckData", + "run": [ + { + "name": "registry_2_0" + }, + { + "name": "registry_2_1" + } + ] + } + ] +} diff --git a/integration-tests/smoke/keeper_test.go_test_list.json b/integration-tests/smoke/keeper_test.go_test_list.json new file mode 100644 index 00000000000..864dbfdb1cf --- /dev/null +++ b/integration-tests/smoke/keeper_test.go_test_list.json @@ -0,0 +1,70 @@ +{ + "tests": [ + { + "name": "TestKeeperBasicSmoke" + }, + { + "name": "TestKeeperBlockCountPerTurn", + "run": [ + { + "name": "registry_1_1" + }, + { + "name": "registry_1_2" + }, + { + "name": "registry_1_3" + } + ] + }, + { + "name": "TestKeeperSimulation" + }, + { + "name": "TestKeeperCheckPerformGasLimit", + "run": [ + { + "name": "registry_1_2" + }, + { + "name": "registry_1_3" + } + ] + }, + { + "name": "TestKeeperRegisterUpkeep" + }, + { + "name": "TestKeeperAddFunds" + }, + { + "name": "TestKeeperRemove" + }, + { + "name": "TestKeeperPauseRegistry" + }, + { + "name": "TestKeeperMigrateRegistry" + }, + { + "name": "TestKeeperNodeDown", + "run": [ + { + "name": "registry_1_1" + }, + { + "name": "registry_1_2" + }, + { + "name": "registry_1_3" + } + ] + }, + { + "name": "TestKeeperPauseUnPauseUpkeep" + }, + { + "name": "TestKeeperUpdateCheckData" + } + ] +}