github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/kontrol/scripts/common.sh (about) 1 #!/bin/bash 2 # Common functions and variables for run-kontrol.sh and make-summary-deployment.sh 3 4 notif() { echo "== $0: $*" >&2 ; } 5 6 # usage function for the run-kontrol.sh script 7 usage_run_kontrol() { 8 echo "Usage: $0 [-h|--help] [container|local|dev] [script|tests]" 1>&2 9 echo "" 1>&2 10 echo " -h, --help Display this help message." 1>&2 11 echo "" 1>&2 12 echo "Execution modes:" 13 echo " container Run in docker container. Reproduce CI execution. (Default)" 1>&2 14 echo " local Run locally, enforces registered versions.json version for better reproducibility. (Recommended)" 1>&2 15 echo " dev Run locally, does NOT enforce registered version. (Useful for developing with new versions and features)" 1>&2 16 echo "" 1>&2 17 echo "Tests executed:" 18 echo " script Execute the tests recorded in run-kontrol.sh" 1>&2 19 echo " tests Execute the tests provided as arguments" 1>&2 20 exit 0 21 } 22 23 # usage function for the make-summary-deployment.sh script 24 usage_make_summary() { 25 echo "Usage: $0 [-h|--help] [container|local|dev]" 1>&2 26 echo "" 1>&2 27 echo " -h, --help Display this help message." 1>&2 28 echo "" 1>&2 29 echo "Execution modes:" 30 echo " container Run in docker container. Reproduce CI execution. (Default)" 1>&2 31 echo " local Run locally, enforces registered versions.json version for better reproducibility. (Recommended)" 1>&2 32 echo " dev Run locally, does NOT enforce registered version. (Useful for developing with new versions and features)" 1>&2 33 exit 0 34 } 35 36 # Set Run Directory <root>/packages/contracts-bedrock 37 WORKSPACE_DIR=$( cd "$SCRIPT_HOME/../../.." >/dev/null 2>&1 && pwd ) 38 39 # Variables 40 export CONTAINER_NAME=kontrol-tests 41 KONTROLRC=$(jq -r .kontrol < "$WORKSPACE_DIR/../../versions.json") 42 export KONTROL_RELEASE=$KONTROLRC 43 export LOCAL=false 44 export SCRIPT_TESTS=false 45 SCRIPT_OPTION=false 46 export CUSTOM_TESTS=0 # Store the position where custom tests start, interpreting 0 as no tests 47 CUSTOM_OPTION=0 48 export RUN_KONTROL=false # true if any functions are called from run-kontrol.sh 49 50 # General usage function, which discerns from which script is being called and displays the appropriate message 51 usage() { 52 if [ "$RUN_KONTROL" = "true" ]; then 53 usage_run_kontrol 54 else 55 usage_make_summary 56 fi 57 } 58 59 60 # Argument Parsing 61 # The logic behind argument parsing is the following (in order): 62 # - Execution mode argument: container (or empty), local, dev 63 # - Tests arguments (first if execution mode empty): script, specific test names 64 parse_args() { 65 if [ $# -eq 0 ]; then 66 export LOCAL=false 67 export SCRIPT_TESTS=false 68 export CUSTOM_TESTS=0 69 # `script` argument caps the total possible arguments to its position 70 elif { [ $# -gt 1 ] && [ "$1" == "script" ]; } || { [ $# -gt 2 ] && [ "$2" == "script" ]; }; then 71 usage 72 elif [ $# -eq 1 ]; then 73 SCRIPT_OPTION=false 74 CUSTOM_OPTION=0 75 parse_first_arg "$1" 76 elif [ $# -eq 2 ] && [ "$2" == "script" ]; then 77 if [ "$1" != "container" ] && [ "$1" != "local" ] && [ "$1" != "dev" ]; then 78 notif "Invalid first argument. Must be \`container\`, \`local\` or \`dev\`" 79 exit 1 80 fi 81 SCRIPT_OPTION=true 82 CUSTOM_OPTION=0 83 parse_first_arg "$1" 84 else 85 SCRIPT_OPTION=false 86 CUSTOM_OPTION=2 87 parse_first_arg "$1" 88 fi 89 } 90 91 # Parse the first argument passed to `run-kontrol.sh` 92 parse_first_arg() { 93 if [ "$1" == "container" ]; then 94 notif "Running in docker container (DEFAULT)" 95 export LOCAL=false 96 export SCRIPT_TESTS=$SCRIPT_OPTION 97 export CUSTOM_TESTS=$CUSTOM_OPTION 98 elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then 99 usage 100 elif [ "$1" == "local" ]; then 101 notif "Running with LOCAL install, .kontrolrc CI version ENFORCED" 102 export SCRIPT_TESTS=$SCRIPT_OPTION 103 export CUSTOM_TESTS=$CUSTOM_OPTION 104 check_kontrol_version 105 elif [ "$1" == "dev" ]; then 106 notif "Running with LOCAL install, IGNORING .kontrolrc version" 107 export LOCAL=true 108 export SCRIPT_TESTS=$SCRIPT_OPTION 109 export CUSTOM_TESTS=$CUSTOM_OPTION 110 pushd "$WORKSPACE_DIR" > /dev/null || exit 111 elif [ "$1" == "script" ]; then 112 notif "Running in docker container (DEFAULT)" 113 export LOCAL=false 114 NEGATED_SCRIPT_TESTS=$([[ "${SCRIPT_OPTION}" == "true" ]] && echo false || echo true) 115 export SCRIPT_TESTS=$NEGATED_SCRIPT_TESTS 116 export CUSTOM_TESTS=$CUSTOM_OPTION 117 else 118 notif "Running in docker container (DEFAULT)" 119 export LOCAL=false 120 export SCRIPT_TESTS=$SCRIPT_OPTION 121 export CUSTOM_TESTS=1 # Store the position where custom tests start 122 fi 123 } 124 125 check_kontrol_version() { 126 if [ "$(kontrol version | awk -F': ' '{print$2}')" == "$KONTROLRC" ]; then 127 notif "Kontrol version matches $KONTROLRC" 128 export LOCAL=true 129 pushd "$WORKSPACE_DIR" > /dev/null || exit 130 else 131 notif "Kontrol version does NOT match $KONTROLRC" 132 notif "Please run 'kup install kontrol --version v$KONTROLRC'" 133 exit 1 134 fi 135 } 136 137 conditionally_start_docker() { 138 if [ "$LOCAL" == false ]; then 139 # Is old docker container running? 140 if [ "$(docker ps -q -f name="$CONTAINER_NAME")" ]; then 141 # Stop old docker container 142 notif "Stopping old docker container" 143 clean_docker 144 fi 145 start_docker 146 fi 147 } 148 149 start_docker () { 150 docker run \ 151 --name "$CONTAINER_NAME" \ 152 --rm \ 153 --interactive \ 154 --detach \ 155 --env FOUNDRY_PROFILE="$FOUNDRY_PROFILE" \ 156 --workdir /home/user/workspace \ 157 runtimeverificationinc/kontrol:ubuntu-jammy-"$KONTROL_RELEASE" 158 159 copy_to_docker 160 } 161 162 copy_to_docker() { 163 # Copy test content to container. We need to avoid copying node_modules because 164 # it results in the below error, so we copy the workspace to a temp directory 165 # and then copy it to the container. 166 # Error response from daemon: invalid symlink "/home/user/workspace/node_modules/@typescript-eslint/eslint-plugin" -> "../../../../node_modules/.pnpm/@typescript-eslint+eslint-plugin@6.19.1_@typescript-eslint+parser@6.19.1_eslint@8.56.0_typescript@5.3.3/node_modules/@typescript-eslint/eslint-plugin" 167 # Even though we use a bind mount, we still need to copy the files to the 168 # container because we are running Docker on a remote host. 169 if [ "$LOCAL" == false ]; then 170 TMP_DIR=$(mktemp -d) 171 cp -r "$WORKSPACE_DIR/." "$TMP_DIR" 172 rm -rf "$TMP_DIR/node_modules" 173 docker cp --follow-link "$TMP_DIR/." $CONTAINER_NAME:/home/user/workspace 174 rm -rf "$TMP_DIR" 175 176 docker exec --user root "$CONTAINER_NAME" chown -R user:user /home/user 177 fi 178 } 179 180 clean_docker(){ 181 notif "Stopping Docker Container" 182 docker stop "$CONTAINER_NAME" 183 } 184 185 186 docker_exec () { 187 docker exec --user user --workdir /home/user/workspace $CONTAINER_NAME "${@}" 188 } 189 190 run () { 191 if [ "$LOCAL" = true ]; then 192 notif "Running local" 193 # shellcheck disable=SC2086 194 "${@}" 195 else 196 notif "Running in docker" 197 docker_exec "${@}" 198 fi 199 }