diff --git a/.github/workflows/e2e_custom_cl.yml b/.github/workflows/e2e_custom_cl.yml index f515e1706..55e8dc316 100644 --- a/.github/workflows/e2e_custom_cl.yml +++ b/.github/workflows/e2e_custom_cl.yml @@ -301,7 +301,6 @@ jobs: run: | # https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md cat << EOF > config.toml [ChainlinkImage] - image="${{ env.CL_ECR }}" version="solana.${{ env.CUSTOM_CORE_REF || github.event.inputs.cl_branch_ref || github.sha }}" [Common] user="${{ github.actor }}" @@ -315,10 +314,11 @@ jobs: # shellcheck disable=SC2086 echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@00c164251be2a7c5b2b23a6e5f7014982f232c14 # v2.3.31 with: test_command_to_run: cd ./integration-tests && go test -timeout 24h -count=1 -run TestSolanaOCRV2Smoke -json $(args) ./smoke 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci=true -singlepackage=true -hidepassingtests=false -hidepassinglogs=false test_download_vendor_packages_command: cd ./integration-tests && go mod download + test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} download_contract_artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} go_mod_path: ./integration-tests/go.mod cl_repo: ${{ env.CL_ECR }} @@ -332,6 +332,9 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} cache_key_id: solana-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "false" + env: + E2E_TEST_CHAINLINK_IMAGE: ${{ env.CL_ECR }} + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret e2e_program_upgrade_tests: name: E2E Program Upgrade Tests @@ -394,10 +397,11 @@ jobs: # shellcheck disable=SC2086 echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Upgrade Test - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@00c164251be2a7c5b2b23a6e5f7014982f232c14 # v2.3.31 with: test_command_to_run: cd ./integration-tests && go test -timeout 24h -count=1 -run TestSolanaOCRV2UpgradeSmoke -json $(args) ./smoke 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci=true -singlepackage=true -hidepassingtests=false -hidepassinglogs=false test_download_vendor_packages_command: cd ./integration-tests && go mod download + test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} download_contract_artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} go_mod_path: ./integration-tests/go.mod cl_repo: ${{ env.CL_ECR }} @@ -411,3 +415,7 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} cache_key_id: solana-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "false" + env: + E2E_TEST_CHAINLINK_IMAGE: ${{ env.CL_ECR }} + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret + diff --git a/.github/workflows/e2e_testnet_daily.yml b/.github/workflows/e2e_testnet_daily.yml index 8a6b572d4..918737aca 100644 --- a/.github/workflows/e2e_testnet_daily.yml +++ b/.github/workflows/e2e_testnet_daily.yml @@ -7,20 +7,10 @@ on: required: true default: develop type: string - RPC_URL: - description: RPC URL for the tests - required: true - default: https://api.devnet.solana.com - type: string - WS_URL: - description: WS URL for the tests - required: true - default: wss://api.devnet.solana.com/ - type: string - PRIVATE_KEY: - description: Private key in byte format [12, 12 ...] - required: true - type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets like ws url, rpc url, private key, etc.' + required: false + type: string schedule: - cron: '0 6 * * *' # Only run 1 of this workflow at a time per PR @@ -147,15 +137,11 @@ jobs: run: | # https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md cat << EOF > config.toml [ChainlinkImage] - image="${{ env.CL_ECR }}" version="solana.${{ env.CUSTOM_CORE_REF || github.event.inputs.cl_branch_ref || github.sha }}" [Common] user="${{ github.actor }}" network="devnet" - private_key="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.PRIVATE_KEY || secrets.PRIVATE_KEY }}" internal_docker_repo = "${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com" - rpc_url = "${{ github.event_name == 'workflow_dispatch' && github.event.inputs.RPC_URL || 'https://api.devnet.solana.com' }}" - ws_url = "${{ github.event_name == 'workflow_dispatch' && github.event.inputs.RPC_URL || 'https://api.devnet.solana.com' }}" EOF # shellcheck disable=SC2002 @@ -165,10 +151,12 @@ jobs: # shellcheck disable=SC2086 echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fdaf56b1df7248d18e30ad09982d03ec67d6b71c # v2.3.29 with: test_command_to_run: cd ./integration-tests && go test -timeout 24h -count=1 -run TestSolanaOCRV2Smoke/embedded -json $(args) ./smoke 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage test_download_vendor_packages_command: cd ./integration-tests && go mod download + test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} + test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} download_contract_artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} go_mod_path: ./integration-tests/go.mod cl_repo: ${{ env.CL_ECR }} @@ -182,3 +170,9 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} cache_key_id: solana-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "false" + DEFAULT_CHAINLINK_IMAGE: ${{ env.CL_ECR }} + env: + E2E_TEST_COMMON_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} # default private key + E2E_TEST_COMMON_RPC_URL: https://api.devnet.solana.com # default url + E2E_TEST_COMMON_WS_URL: https://api.devnet.solana.com # default url + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret \ No newline at end of file diff --git a/.github/workflows/soak.yml b/.github/workflows/soak.yml index 0f053a17b..da9c1f93c 100644 --- a/.github/workflows/soak.yml +++ b/.github/workflows/soak.yml @@ -3,8 +3,12 @@ on: workflow_dispatch: inputs: base64_config: - description: Your .toml file as base64 + description: Your .toml file as base64 (must NOT contain test secrets) required: true + test_secrets_override_key: + description: 'Key to run tests with custom test secrets like ws url, rpc url, private key, etc.' + required: false + type: string cl_image_tag: description: Core image tag required: true @@ -92,10 +96,12 @@ jobs: echo "::add-mask::$BASE64_CONFIG_OVERRIDE" echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> "$GITHUB_ENV" - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fdaf56b1df7248d18e30ad09982d03ec67d6b71c # v2.3.29 with: test_command_to_run: cd ./integration-tests && go test -timeout 24h -count=1 -run TestSolanaOCRV2Soak/embedded -json $(args) ./soak 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage test_download_vendor_packages_command: cd ./integration-tests && go mod download + test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} + test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} download_contract_artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} go_mod_path: ./integration-tests/go.mod cl_repo: ${{ env.CL_ECR }} @@ -109,3 +115,5 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} cache_key_id: solana-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "false" + env: + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret \ No newline at end of file diff --git a/docs/RunningE2eTests.md b/docs/RunningE2eTests.md index 5c44dbcfa..22688adac 100644 --- a/docs/RunningE2eTests.md +++ b/docs/RunningE2eTests.md @@ -15,7 +15,7 @@ Devnet requires previously deployed programs that are owned by the person runnin - `Common.network` needs to be set to `devnet` which will instruct the tests to run against devnet - `ocr2_program_id`, `access_controller_program_id`, `store_program_id`, `link_token_address`, `vault_address` need to be set so the tests know what programs to use so we avoid deploying each time. -- `rpc_url` and `ws_url` need to be set +- `E2E_TEST_COMMON_RPC_URL` and `E2E_TEST_COMMON_WS_URL` need to be set **Localnet** Setting localnet will instruct the tests to run in localnet, the program ID's are not taken from the TOML in this scenario, but rather defined in the `integration-tests/config/config.go`. diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 44ffac433..300469d41 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -31,11 +31,8 @@ access_controller_program_id = "9xi644bRR8birboDGdTiwBq3C7VEeR7VuamRYYXCubUW" store_program_id = "HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny" link_token_address = "7CF1GrsZsny5j9JESPj98MdYVZK38RE8ZpmTEMwECK4c" vault_address = "FdM4dnhVpFQfjPqNG6LEfzArhuGhUjtidYu89qtGwJCS" -secret="thisisatestingonlysecret" [Common] -rpc_url = "https://api.devnet.solana.com" -ws_url = "wss://api.devnet.solana.com/" internal_docker_repo = "public.ecr.aws/chainlink" inside_k8 = false network = "localnet" diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index cdf5615b3..fcd79eb7a 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -3,13 +3,14 @@ package testconfig import ( "embed" "encoding/base64" - "errors" "fmt" "log" "os" "strings" "time" + "errors" + "github.com/barkimedes/go-deepcopy" "github.com/google/uuid" "github.com/pelletier/go-toml/v2" @@ -46,6 +47,186 @@ type TestConfig struct { GetURL func() string } +const ( + E2E_TEST_COMMON_RPC_URL_ENV = "E2E_TEST_COMMON_RPC_URL" // revive:disable-line:var-naming + E2E_TEST_COMMON_WS_URL_ENV = "E2E_TEST_COMMON_WS_URL" // revive:disable-line:var-naming + // Private key in byte format [12, 12 ...] + E2E_TEST_COMMON_PRIVATE_KEY_ENV = "E2E_TEST_COMMON_PRIVATE_KEY" // revive:disable-line:var-naming + E2E_TEST_SOLANA_SECRET = "E2E_TEST_SOLANA_SECRET" // revive:disable-line:var-naming +) + +// Read config values from environment variables +func (c *TestConfig) ReadFromEnvVar() error { + logger := logging.GetTestLogger(nil) + + lokiTenantID := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_LOKI_TENANT_ID_ENV) + if lokiTenantID != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Loki == nil { + c.Logging.Loki = &ctf_config.LokiConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Loki.TenantId", ctf_config.E2E_TEST_LOKI_TENANT_ID_ENV) + c.Logging.Loki.TenantId = &lokiTenantID + } + + lokiEndpoint := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_LOKI_ENDPOINT_ENV) + if lokiEndpoint != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Loki == nil { + c.Logging.Loki = &ctf_config.LokiConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Loki.Endpoint", ctf_config.E2E_TEST_LOKI_ENDPOINT_ENV) + c.Logging.Loki.Endpoint = &lokiEndpoint + } + + lokiBasicAuth := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_LOKI_BASIC_AUTH_ENV) + if lokiBasicAuth != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Loki == nil { + c.Logging.Loki = &ctf_config.LokiConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Loki.BasicAuth", ctf_config.E2E_TEST_LOKI_BASIC_AUTH_ENV) + c.Logging.Loki.BasicAuth = &lokiBasicAuth + } + + lokiBearerToken := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + if lokiBearerToken != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Loki == nil { + c.Logging.Loki = &ctf_config.LokiConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Loki.BearerToken", ctf_config.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + c.Logging.Loki.BearerToken = &lokiBearerToken + } + + grafanaBaseURL := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_GRAFANA_BASE_URL_ENV) + if grafanaBaseURL != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Grafana == nil { + c.Logging.Grafana = &ctf_config.GrafanaConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Grafana.BaseUrl", ctf_config.E2E_TEST_GRAFANA_BASE_URL_ENV) + c.Logging.Grafana.BaseUrl = &grafanaBaseURL + } + + grafanaDashboardURL := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + if grafanaDashboardURL != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Grafana == nil { + c.Logging.Grafana = &ctf_config.GrafanaConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Grafana.DashboardUrl", ctf_config.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + c.Logging.Grafana.DashboardUrl = &grafanaDashboardURL + } + + grafanaBearerToken := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + if grafanaBearerToken != "" { + if c.Logging == nil { + c.Logging = &ctf_config.LoggingConfig{} + } + if c.Logging.Grafana == nil { + c.Logging.Grafana = &ctf_config.GrafanaConfig{} + } + logger.Info().Msgf("Using %s env var to override Logging.Grafana.BearerToken", ctf_config.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + c.Logging.Grafana.BearerToken = &grafanaBearerToken + } + + chainlinkImage := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_CHAINLINK_IMAGE_ENV) + if chainlinkImage != "" { + if c.ChainlinkImage == nil { + c.ChainlinkImage = &ctf_config.ChainlinkImageConfig{} + } + logger.Info().Msgf("Using %s env var to override ChainlinkImage.Image", ctf_config.E2E_TEST_CHAINLINK_IMAGE_ENV) + c.ChainlinkImage.Image = &chainlinkImage + } + + chainlinkUpgradeImage := ctf_config.MustReadEnvVar_String(ctf_config.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + if chainlinkUpgradeImage != "" { + if c.ChainlinkUpgradeImage == nil { + c.ChainlinkUpgradeImage = &ctf_config.ChainlinkImageConfig{} + } + logger.Info().Msgf("Using %s env var to override ChainlinkUpgradeImage.Image", ctf_config.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + c.ChainlinkUpgradeImage.Image = &chainlinkUpgradeImage + } + + walletKeys := ctf_config.ReadEnvVarGroupedMap(ctf_config.E2E_TEST_WALLET_KEY_ENV, ctf_config.E2E_TEST_WALLET_KEYS_ENV) + if len(walletKeys) > 0 { + if c.Network == nil { + c.Network = &ctf_config.NetworkConfig{} + } + logger.Info().Msgf("Using %s and/or %s env vars to override Network.WalletKeys", ctf_config.E2E_TEST_WALLET_KEY_ENV, ctf_config.E2E_TEST_WALLET_KEYS_ENV) + c.Network.WalletKeys = walletKeys + } + + rpcHTTPUrls := ctf_config.ReadEnvVarGroupedMap(ctf_config.E2E_TEST_RPC_HTTP_URL_ENV, ctf_config.E2E_TEST_RPC_HTTP_URLS_ENV) + if len(rpcHTTPUrls) > 0 { + if c.Network == nil { + c.Network = &ctf_config.NetworkConfig{} + } + logger.Info().Msgf("Using %s and/or %s env vars to override Network.RpcHttpUrls", ctf_config.E2E_TEST_RPC_HTTP_URL_ENV, ctf_config.E2E_TEST_RPC_HTTP_URLS_ENV) + c.Network.RpcHttpUrls = rpcHTTPUrls + } + + rpcWsUrls := ctf_config.ReadEnvVarGroupedMap(ctf_config.E2E_TEST_RPC_WS_URL_ENV, ctf_config.E2E_TEST_RPC_WS_URLS_ENV) + if len(rpcWsUrls) > 0 { + if c.Network == nil { + c.Network = &ctf_config.NetworkConfig{} + } + logger.Info().Msgf("Using %s and/or %s env vars to override Network.RpcWsUrls", ctf_config.E2E_TEST_RPC_WS_URL_ENV, ctf_config.E2E_TEST_RPC_WS_URLS_ENV) + c.Network.RpcWsUrls = rpcWsUrls + } + + commonRPCURL := ctf_config.MustReadEnvVar_String(E2E_TEST_COMMON_RPC_URL_ENV) + if commonRPCURL != "" { + if c.Common == nil { + c.Common = &Common{} + } + logger.Info().Msgf("Using %s env var to override Common.RPCURL", E2E_TEST_COMMON_RPC_URL_ENV) + c.Common.RPCURL = &commonRPCURL + } + + commonWSURL := ctf_config.MustReadEnvVar_String(E2E_TEST_COMMON_WS_URL_ENV) + if commonWSURL != "" { + if c.Common == nil { + c.Common = &Common{} + } + logger.Info().Msgf("Using %s env var to override Common.WsURL", E2E_TEST_COMMON_WS_URL_ENV) + c.Common.WsURL = &commonWSURL + } + + commonPrivateKey := ctf_config.MustReadEnvVar_String(E2E_TEST_COMMON_PRIVATE_KEY_ENV) + if commonPrivateKey != "" { + if c.Common == nil { + c.Common = &Common{} + } + logger.Info().Msgf("Using %s env var to override Common.PrivateKey", E2E_TEST_COMMON_PRIVATE_KEY_ENV) + c.Common.PrivateKey = &commonPrivateKey + } + + solanaSecret := ctf_config.MustReadEnvVar_String(E2E_TEST_SOLANA_SECRET) + if solanaSecret != "" { + if c.SolanaConfig == nil { + c.SolanaConfig = &SolanaConfig{} + } + logger.Info().Msgf("Using %s env var to override SolanaConfig.Secret", E2E_TEST_SOLANA_SECRET) + c.SolanaConfig.Secret = &solanaSecret + } + + return nil +} + func (c *TestConfig) GetLoggingConfig() *ctf_config.LoggingConfig { return c.Logging } @@ -176,16 +357,16 @@ type Common struct { InsideK8s *bool `toml:"inside_k8"` User *string `toml:"user"` // if rpc requires api key to be passed as an HTTP header - RPCURL *string `toml:"rpc_url"` - WsURL *string `toml:"ws_url"` - PrivateKey *string `toml:"private_key"` + RPCURL *string `toml:"-"` + WsURL *string `toml:"-"` + PrivateKey *string `toml:"-"` Stateful *bool `toml:"stateful_db"` InternalDockerRepo *string `toml:"internal_docker_repo"` DevnetImage *string `toml:"devnet_image"` } type SolanaConfig struct { - Secret *string `toml:"secret"` + Secret *string `toml:"-"` OCR2ProgramID *string `toml:"ocr2_program_id"` AccessControllerProgramID *string `toml:"access_controller_program_id"` StoreProgramID *string `toml:"store_program_id"` @@ -378,6 +559,18 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, fmt.Errorf("error reading network config: %w", err) } + logger.Info().Msg("Loading config values from default ~/.testsecrets env file") + err = ctf_config.LoadSecretEnvsFromFiles() + if err != nil { + return TestConfig{}, fmt.Errorf("error reading test config values from ~/.testsecrets file: %w", err) + } + + logger.Info().Msg("Reading values from environment variables") + err = testConfig.ReadFromEnvVar() + if err != nil { + return TestConfig{}, fmt.Errorf("error reading test config values from env vars: %w", err) + } + logger.Debug().Msg("Validating test config") err = testConfig.Validate() if err != nil {