diff --git a/.buildkite/node_sync_tests.yml b/.buildkite/node_sync_tests.yml index 6ebed36bc..2359515d3 100644 --- a/.buildkite/node_sync_tests.yml +++ b/.buildkite/node_sync_tests.yml @@ -1,12 +1,12 @@ steps: - - label: 'run the cardano node sync test on Mainnet using a Linux machine' + - label: ':drum_with_drumsticks: Run the cardano node sync test on Mainnet using a Linux machine' commands: - './.buildkite/node_sync_tests.sh $env $build_mode $node_rev1 $node_rev2 $tag_no1 $tag_no2 $node_topology1 $node_topology2 $node_start_arguments1 $node_start_arguments2' - timeout_in_minutes: 5000 + timeout_in_minutes: 3000 agents: system: x86_64-linux queue: core-tech-bench artifact_paths: - 'logfile.log' - - 'logfile_copy.log' + - 'node.log' - 'sync_results.json' diff --git a/.github/workflows/node_sync_test.yaml b/.github/workflows/node_sync_test.yaml index 3131a64df..125cf6612 100644 --- a/.github/workflows/node_sync_test.yaml +++ b/.github/workflows/node_sync_test.yaml @@ -1,65 +1,67 @@ -name: node_sync_tests +name: Node sync tests on: workflow_dispatch: branches: - - artur/sync_tests_update + - node_sync_tests inputs: environment: - description: Environment on which Buildkite agent will run tests + description: Environment on which Buildkite agent will run tests. type: choice options: - mainnet - preprod - preview - - shelley-qa default: mainnet build_mode: - description: Currently only nix is supported, there are no prebuilt CI binaries available anymore. Windows agents can only build with cabal - nix is not supported. + description: Currently only nix is supported. Windows agents can only build with cabal - nix is not supported. type: choice options: - nix default: nix tag_no1: - description: rev_label in db/visuals (1.33.0-rc2 (tag number) or 1.33.0 (release number) or 1.33.0_PR2124 (for not released and not tagged runs with a specific node PR/version)) + description: rev_label in Microsoft BI visuals - it is label used to distinct graphs for various sync tests runs. required: true - default: "8.0.0-legacy" + default: "9.2.1-bootstrap-peers" node_rev1: - description: Desired cardano-node revision (used for initial sync) - cardano-node (tags/1.33.0-rc2) tag or branch + description: Desired cardano-node revision (used for initial sync) - (tags/1.33.0-rc2) tag or branch. required: true - default: "tags/8.0.0" + default: "tags/9.2.1" node_topology1: - description: Desired cardano-node topology type (used for initial sync) - legacy, p2p + description: Desired cardano-node topology type (used for initial sync). type: choice options: - legacy - - p2p - default: legacy + - non-bootstrap-peers + - bootstrap-peers + default: bootstrap-peers node_start_arguments1: - description: Extra arguments to be used when starting the node using tag_no1 (--a1 --a2 21) + description: Extra arguments to be used when starting the node using tag_no1 (--a1 --a2 21). required: false default: "None" tag_no2: - description: rev_label in db/visuals (1.33.0-rc2 (tag number) or 1.33.0 (release number) or 1.33.0_PR2124 (for not released and not tagged runs with a specific node PR/version)) + description: rev_label in Microsoft BI visuals - (1.33.0-rc2 (tag number) or 1.33.0 (release number) or 1.33.0_PR2124 (for not released and not tagged runs with a specific node PR/version)). required: true default: "None" node_rev2: - description: Desired cardano-node revision (used for final sync) - cardano-node (tags/1.33.0-rc2) tag or branch + description: Desired cardano-node revision (used for final sync for upgrade test) - cardano-node (tags/1.33.0-rc2) tag or branch. required: true default: "None" node_topology2: - description: Desired cardano-node topology type (used for final sync) - legacy, p2p + description: Desired cardano-node topology type (used for final sync). type: choice options: - legacy - - p2p - default: legacy + - non-bootstrap-peers + - bootstrap-peers + default: bootstrap-peers node_start_arguments2: - description: Extra arguments to be used when starting the node using tag_no2 (--a1 --a2 21) + description: Extra arguments to be used when starting the node using tag_no2 (--a1 --a2 21). required: false default: "None" + jobs: - node_sync_test_mainnet: + node_sync_test_buildkite_mainnet: runs-on: ubuntu-latest steps: - name: trigger the Buildkite pipeline - run sync tests on Mainnet @@ -67,7 +69,7 @@ jobs: env: BUILDKITE_API_ACCESS_TOKEN: ${{ secrets.BUILDKITE_API_ACCESS_TOKEN }} PIPELINE: 'input-output-hk/qa-sync-tests' - BRANCH: 'sync_tests' + BRANCH: 'node_sync_tests' MESSAGE: ':github: Triggered by GitHub Action' AWS_DB_USERNAME: ${{ secrets.AWS_DB_USERNAME }} AWS_DB_PASS: ${{ secrets.AWS_DB_PASS }} @@ -92,86 +94,64 @@ jobs: "AWS_DB_NAME":"${{ secrets.AWS_DB_NAME }}", "AWS_DB_HOSTNAME":"${{ secrets.AWS_DB_HOSTNAME }}" }' + node_sync_test: strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - env: [preview, preprod] - cabal: ["3.8.1.0"] - ghc: ["8.10.7"] + env: [preprod, preview] + ghc: ["9.6"] + cabal: ["3.12.1.0"] + sys: + - { os: windows-latest, shell: 'C:/msys64/usr/bin/bash.exe -e {0}' } + - { os: ubuntu-latest, shell: bash } + - { os: macos-latest, shell: bash } branch: - - artur/sync_tests_update + - node_sync_tests fail-fast: false - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.sys.os }} timeout-minutes: 600 env: - # Modify this value to "invalidate" the cabal cache. - CABAL_CACHE_VERSION: "2023-06-01" - - # Modify this value to "invalidate" the secp cache. - SECP_CACHE_VERSION: "2022-12-30" - # current ref from: 27.02.2022 - SECP256K1_REF: ac83be33d0956faf6b7f61a60ab524ef7d6a473a + MSYS2_PATH_TYPE: inherit + MSYSTEM: MINGW64 steps: - name: Install Haskell - if: matrix.os == 'windows-latest' - uses: input-output-hk/setup-haskell@v1 + if: matrix.sys.os == 'windows-latest' + uses: input-output-hk/actions/haskell@latest id: setup-haskell with: ghc-version: ${{ matrix.ghc }} cabal-version: ${{ matrix.cabal }} - pacman-packages: > - mingw-w64-x86_64-pkg-config - mingw-w64-x86_64-libsodium - mingw-w64-x86_64-openssl - base-devel - autoconf-wrapper - autoconf - automake - libtool - make - - - name: Update Windows path with executables locations - if: runner.os == 'Windows' - shell: pwsh - run: | - $env:PATH+="D:\a\cardano-node-tests\cardano-node-tests\cardano_node_tests" - git config --system core.longpaths true - - - name: Install secp256k1 - if: matrix.os == 'windows-latest' - uses: input-output-hk/setup-secp256k1@v1 + + - name: Install system dependencies + if: matrix.sys.os == 'windows-latest' + uses: input-output-hk/actions/base@latest with: - git-ref: ${{ env.SECP256K1_REF }} - cache-version: ${{ env.SECP_CACHE_VERSION }} + use-sodium-vrf: true - - uses: actions/checkout@v3 - - name: "[PowerShell] Add build script path" - if: runner.os == 'Windows' - shell: pwsh - run: Add-Content $env:GITHUB_PATH "$(pwd)/.github/bin" - - name: Checkout cardano-node-tests repo - uses: actions/checkout@v3 + - name: Checkout cardano-node-tests repository + uses: actions/checkout@v4 with: path: cardano_node_tests - ref: artur/sync_tests_update + ref: node_sync_tests + - - uses: cachix/install-nix-action@v22 - if: matrix.os != 'windows-latest' + - name: Install nix + uses: cachix/install-nix-action@v27 + if: matrix.sys.os != 'windows-latest' with: extra_nix_config: | - trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= - substituters = https://cache.nixos.org https://cache.iog.io https://iohk.cachix.org + trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + substituters = https://cache.nixos.org https://cache.iog.io allow-import-from-derivation = true - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' @@ -185,11 +165,19 @@ jobs: pip install GitPython pip install colorama + + - name: "[Windows] Update environment variables" + if: runner.os == 'Windows' + shell: pwsh + run: | + "PATH=C:\\msys64\\mingw64\\opt\\cardano\\bin;C:\\msys64\\mingw64\\bin;{0}" -f $env:PATH >> $env:GITHUB_ENV + "PKG_CONFIG_PATH=C:\\msys64\\mingw64\\opt\\cardano\\lib\\pkgconfig;C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig;C:\\msys64\\usr\\lib\\pkgconfig;C:\\msys64\\usr\\share\\pkgconfig;{0}" -f $env:PKG_CONFIG_PATH >> $env:GITHUB_ENV + + - name: Run sync test env: BLOCKFROST_API_KEY: ${{ secrets.BLOCKFROST_API_KEY }} run: | - ${{ (runner.os == 'Windows' && '$env:PATH=("C:\msys64\mingw64\bin;{0}" -f $env:PATH)') || '' }} cd cardano_node_tests echo "current branch: $(git branch --show-current)" python sync_tests/node_sync_test.py -e ${{ matrix.env }} -b ${{ github.event.inputs.build_mode }} -t1 "${{ github.event.inputs.tag_no1 }}" -t2 "${{ github.event.inputs.tag_no2 }}" -r1 "${{ github.event.inputs.node_rev1 }}" -r2 "${{ github.event.inputs.node_rev2 }}" -n1 "${{ github.event.inputs.node_topology1 }}" -n2 "${{ github.event.inputs.node_topology2 }}" -a1="${{ github.event.inputs.node_start_arguments1 }}" -a2="${{ github.event.inputs.node_start_arguments2 }}" @@ -205,14 +193,22 @@ jobs: cd cardano_node_tests echo "current branch: $(git branch --show-current)" python sync_tests/node_write_sync_values_to_db.py -e ${{ matrix.env }} + + - name: Prepare node logs + if: always() + run: | + cd cardano_node_tests + cp logfile.log node.log + + - name: Generate artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: - name: node_logs_${{ matrix.env }}_${{ matrix.os }} + name: node_logs_${{ matrix.env }}_${{ matrix.sys.os }} path: | - cardano_node_tests/logfile_copy.log + cardano_node_tests/node.log cardano_node_tests/sync_results.json cardano_node_tests/config.json cardano_node_tests/topology.json diff --git a/sync_tests/cabal.project.local b/sync_tests/cabal.project.local index 38219c3bc..410c8f904 100644 --- a/sync_tests/cabal.project.local +++ b/sync_tests/cabal.project.local @@ -1,2 +1,5 @@ +package HsOpenSSL + flags: +use-pkg-config + package cardano-crypto-praos flags: -external-libsodium-vrf diff --git a/sync_tests/node_sync_test.py b/sync_tests/node_sync_test.py index 8042ecc6f..fe6c10da2 100644 --- a/sync_tests/node_sync_test.py +++ b/sync_tests/node_sync_test.py @@ -26,13 +26,14 @@ import utils from utils import print_info, print_ok, print_warn, print_info_warn, print_error, seconds_to_time, date_diff_in_seconds, get_no_of_cpu_cores, \ get_current_date_time, get_os_type, get_directory_size, get_total_ram_in_GB, delete_file, is_dir, \ - list_absolute_file_paths + list_absolute_file_paths, print_file_content +CONFIGS_BASE_URL = "https://book.play.dev.cardano.org/environments" NODE = './cardano-node' CLI = './cardano-cli' ROOT_TEST_PATH = '' NODE_LOG_FILE = 'logfile.log' -NODE_LOG_FILE_ARTIFACT = 'logfile_copy.log' +NODE_LOG_FILE_ARTIFACT = 'node.log' RESULTS_FILE_NAME = r'sync_results.json' ONE_MINUTE = 60 @@ -93,44 +94,37 @@ def delete_node_files(): p.unlink(missing_ok=True) -def create_mainnet_p2p_topology_file(filename): - data = '''{ - "localRoots": [ - { "accessPoints": [], - "advertise": false, - "valency": 1 - } - ], - "publicRoots": [ - { "accessPoints": [ - { - "address": "relays-new.cardano-mainnet.iohk.io", - "port": 3001 - } - ], - "advertise": false - } - ], - "useLedgerAfterSlot": 29691317 - }''' - - with open(filename, "w") as text_file: - text_file.write(data) - - -def enable_p2p_node_config_file(node_config_filepath): +def update_config(file_name: str, updates: dict) -> None: + # Load the current configuration from the JSON file + with open(file_name, 'r') as file: + config = json.load(file) + + # Update the config with the new values + for key, value in updates.items(): + if key in config: + print(f"Updating '{key}' from '{config[key]}' to '{value}'") + config[key] = value + else: + print(f"Key '{key}' not found in the config, adding new key-value pair") + config[key] = value + + # Write the updated configuration back to the JSON file + with open(file_name, 'w') as file: + json.dump(config, file, indent=4) + print("Configuration updated successfully.") + + +def disable_p2p_node_config(): os.chdir(Path(ROOT_TEST_PATH)) current_directory = Path.cwd() print(f"current_directory: {current_directory}") print(f" - listdir current_directory: {os.listdir(current_directory)}") - with open(node_config_filepath, 'r') as json_file: - node_config_json = json.load(json_file) - - node_config_json['EnableP2P'] = True - - with open(node_config_filepath, 'w') as json_file: - json.dump(node_config_json, json_file, indent=2) + updates = { + "EnableP2P": False, + "PeerSharing": False + } + update_config('config.json', updates) def rm_node_config_files() -> None: @@ -142,11 +136,11 @@ def rm_node_config_files() -> None: Path(f).unlink(missing_ok=True) -def download_config_file(env: str, file_name: str) -> None: - if Path(file_name).exists(): - return - print(f"Downloading {file_name} file...") - urllib.request.urlretrieve(f"https://book.play.dev.cardano.org/environments/{env}/{file_name}", file_name,) +def download_config_file(env: str, file_name: str, save_as: str = None) -> None: + save_as = save_as or file_name + url = f"{CONFIGS_BASE_URL}/{env}/{file_name}" + print(f"Downloading {file_name} from {url} and saving as {save_as}...") + urllib.request.urlretrieve(url, save_as) def get_node_config_files(env, node_topology_type): @@ -159,13 +153,18 @@ def get_node_config_files(env, node_topology_type): download_config_file(env, 'alonzo-genesis.json') download_config_file(env, 'conway-genesis.json') - if env == 'mainnet' and node_topology_type == 'p2p': - print('Creating the topology.json file...') - create_mainnet_p2p_topology_file('topology.json') - enable_p2p_node_config_file('config.json') + if env == 'mainnet' and node_topology_type == 'non-bootstrap-peers': + download_config_file(env, 'topology-non-bootstrap-peers.json', save_as='topology.json') + elif env == 'mainnet' and node_topology_type == 'legacy': + download_config_file(env, 'topology-legacy.json', save_as='topology.json') + disable_p2p_node_config() else: download_config_file(env, 'topology.json') print(f" - listdir current_directory: {os.listdir(current_directory)}") + print_info_warn(" Config File Content: ") + print_file_content('config.json') + print_info_warn(" Topology File Content: ") + print_file_content('topology.json') def enable_cardano_node_resources_monitoring(node_config_filepath): @@ -465,6 +464,7 @@ def wait_for_node_to_sync(env): time.sleep(5) count += 1 actual_epoch, actual_block, actual_hash, actual_slot, actual_era, syncProgress = get_current_tip() + else: while actual_slot <= last_slot_no: if count % 60 == 0: @@ -632,13 +632,13 @@ def get_data_from_logs(log_file): return logs_details_dict -def get_node_cabal_build_files(): +def get_cabal_build_files(): node_build_files = list_absolute_file_paths('dist-newstyle/build') return node_build_files def get_node_executable_path_built_with_cabal(): - for f in get_node_cabal_build_files(): + for f in get_cabal_build_files(): if "\\x\\cardano-node\\build\\" in f and 'cardano-node-tmp' not in f and 'autogen' not in f: print_info(f"Found node executable: {f}") global NODE @@ -647,7 +647,7 @@ def get_node_executable_path_built_with_cabal(): def get_cli_executable_path_built_with_cabal(): - for f in get_node_cabal_build_files(): + for f in get_cabal_build_files(): if "\\x\\cardano-cli\\build\\" in f and 'cardano-cli-tmp' not in f and 'autogen' not in f: print_info(f"Found node-cli executable: {f}") global CLI @@ -691,12 +691,11 @@ def copy_node_executables(src_location, dst_location, build_mode): shutil.copy2(node_binary_location, Path(dst_location) / 'cardano-node') except Exception as e: print_error(f" !!! ERROR - could not copy the cardano-cli file - {e}") - exit(1) + try: shutil.copy2(cli_binary_location, Path(dst_location) / 'cardano-cli') except Exception as e: print_error(f" !!! ERROR - could not copy the cardano-cli file - {e}") - exit(1) time.sleep(5) @@ -706,31 +705,56 @@ def get_node_files(node_rev, repository=None, build_tool='nix'): print_info(f"test_directory: {test_directory}") print(f" - listdir test_directory: {os.listdir(test_directory)}") - repo_name = 'cardano-node' - repo_dir = test_directory / 'cardano_node_dir' + node_repo_name = 'cardano-node' + node_repo_dir = test_directory / 'cardano_node_dir' - if is_dir(repo_dir): + cli_rev = 'e7e5a86' + cli_repo_name = 'cardano-cli' + cli_repo_dir = test_directory / 'cardano_cli_dir' + + if is_dir(node_repo_dir): repo = git_checkout(repository, node_rev) else: - repo = git_clone_iohk_repo(repo_name, repo_dir, node_rev) + repo = git_clone_iohk_repo(node_repo_name, node_repo_dir, node_rev) + + if is_dir(cli_repo_dir): + git_checkout(repository, cli_rev) + else: + git_clone_iohk_repo(cli_repo_name, cli_repo_dir, cli_rev) if build_tool == 'nix': - os.chdir(repo_dir) + os.chdir(node_repo_dir) Path('cardano-node-bin').unlink(missing_ok=True) Path('cardano-cli-bin').unlink(missing_ok=True) execute_command("nix build -v .#cardano-node -o cardano-node-bin") execute_command("nix build -v .#cardano-cli -o cardano-cli-bin") - copy_node_executables(repo_dir, test_directory, "nix") + copy_node_executables(node_repo_dir, test_directory, "nix") + elif build_tool == 'cabal': cabal_local_file = Path(test_directory) / 'sync_tests' / 'cabal.project.local' - shutil.copy2(cabal_local_file, repo_dir) - os.chdir(repo_dir) + + # Build cli + os.chdir(cli_repo_dir) + shutil.copy2(cabal_local_file, cli_repo_dir) + print(f" - listdir cli_repo_dir: {os.listdir(cli_repo_dir)}") + shutil.rmtree('dist-newstyle', ignore_errors=True) + for line in fileinput.input("cabal.project", inplace=True): + print(line.replace("tests: True", "tests: False"), end="") + execute_command("cabal update") + execute_command("cabal build cardano-cli") + copy_node_executables(cli_repo_dir, test_directory, "cabal") + git_checkout(repo, 'cabal.project') + + # Build node + os.chdir(node_repo_dir) + shutil.copy2(cabal_local_file, node_repo_dir) + print(f" - listdir node_repo_dir: {os.listdir(node_repo_dir)}") shutil.rmtree('dist-newstyle', ignore_errors=True) for line in fileinput.input("cabal.project", inplace=True): print(line.replace("tests: True", "tests: False"), end="") execute_command("cabal update") - execute_command("cabal build cardano-node cardano-cli") - copy_node_executables(repo_dir, test_directory, "cabal") + execute_command("cabal build cardano-node") + copy_node_executables(node_repo_dir, test_directory, "cabal") git_checkout(repo, 'cabal.project') os.chdir(test_directory) @@ -972,10 +996,10 @@ def main(): "-t2", "--tag_no2", help="tag_no2 label as it will be shown in the db/visuals", ) parser.add_argument( - "-n1", "--node_topology1", help="type of node topology used for the initial sync - legacy, p2p" + "-n1", "--node_topology1", help="type of node topology used for the initial sync - legacy, non-bootstrap-peers, bootstrap-peers" ) parser.add_argument( - "-n2", "--node_topology2", help="type of node topology used for final sync (after restart) - legacy, p2p" + "-n2", "--node_topology2", help="type of node topology used for final sync (after restart) - legacy, non-bootstrap-peers, bootstrap-peers" ) parser.add_argument( "-a1", "--node_start_arguments1", nargs='+', type=str, diff --git a/sync_tests/utils.py b/sync_tests/utils.py index 74c9af979..fb7c9f4b4 100644 --- a/sync_tests/utils.py +++ b/sync_tests/utils.py @@ -159,6 +159,17 @@ def get_file_creation_date(path_to_file): return time.ctime(os.path.getmtime(path_to_file)) +def print_file_content(file_name: str) -> None: + try: + with open(file_name, 'r') as file: + content = file.read() + print(content) + except FileNotFoundError: + print(f"File '{file_name}' not found.") + except Exception as e: + print(f"An error occurred while reading the file: {e}") + + def is_dir(dir): return os.path.isdir(dir) @@ -200,4 +211,4 @@ def delete_file(file_path): try: file_path.unlink() except OSError as e: - print_error(f"Error: {file_path} : {e.strerror}") \ No newline at end of file + print_error(f"Error: {file_path} : {e.strerror}")