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  }