From 4981fa816fd5133a4df190684ffc52adfe59d3b6 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Fri, 21 Sep 2018 13:57:03 -0600 Subject: [PATCH 1/6] circleci: Refactor to make more modular Factored out reusable steps into references, taking inspiration from https://github.com/circleci/frontend/blob/master/.circleci/config.yml This is a prelude for adding test coverage rather than copy/pasting each job in their entirety. --- .circleci/config.yml | 460 ++++++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 229 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5a84f724fcf8..66cf4bf05497 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,9 @@ -default_env_vars: &default_env_vars +--- +# yamllint disable rule:line-length +version: 2.0 + +references: + default_env_vars: &default_env_vars JAVA_HOME: /usr/local/openjdk8u154-cassandra-b02 ANT_HOME: /usr/local/apache-ant-1.10.1 LANG: en_US.UTF-8 @@ -11,24 +16,194 @@ default_env_vars: &default_env_vars PYTHONUNBUFFERED: true CASS_DRIVER_NO_EXTENSIONS: true CASS_DRIVER_NO_CYTHON: true -# For environments with xlarge instances, use more memory -high_capacity_env_vars: &high_capacity_env_vars + TEST_SUCCESS_OVERRIDE: /bin/false # Used to make coverage tests pass + + # Settings for users who do not have a paid CircleCI account + default_env_settings: &default_env_settings + resource_class: medium + parallelism: 4 + # Settings for users with high-capacity, paid CircleCI account + high_capacity_env_settings: &high_capacity_env_settings + resource_class: xlarge + parallelism: 100 + + # For environments with xlarge instances, use more memory + high_capacity_env_vars: &high_capacity_env_vars <<: *default_env_vars CCM_MAX_HEAP_SIZE: 2048M CCM_HEAP_NEWSIZE: 512M -# For environments with limited memory (e.g the free OSS CircleCI Tier) -resource_constrained_env_vars: &resource_constrained_env_vars + # For environments with limited memory (e.g the free OSS CircleCI Tier) + resource_constrained_env_vars: &resource_constrained_env_vars <<: *default_env_vars CCM_MAX_HEAP_SIZE: 1024M CCM_HEAP_NEWSIZE: 256M -# Settings for users who do not have a paid CircleCI account -default_env_settings: &default_env_settings - resource_class: medium - parallelism: 4 -# Settings for users with high-capacity, paid CircleCI account -high_capacity_env_settings: &high_capacity_env_settings - resource_class: xlarge - parallelism: 100 + + env_settings: &env_settings + <<: *default_env_settings + # <<: *high_capacity_env_settings + + env_vars: &env_vars + <<: *resource_constrained_env_vars + # <<: *high_capacity_env_vars + + container_config: &container_config + docker: + - image: kjellman/cassandra-test:0.4.3 + environment: + <<: *env_vars + working_directory: ~/ + + workspace_root: &workspace_root + /home/cassandra + + ### Reusable job steps + attach_workspace: &attach_workspace + attach_workspace: + at: *workspace_root + + log_environment: &log_environment + run: + name: Log Environment Information + command: | + echo '*** id ***' + id + echo '*** cat /proc/cpuinfo ***' + cat /proc/cpuinfo + echo '*** free -m ***' + free -m + echo '*** df -m ***' + df -m + echo '*** ifconfig -a ***' + ifconfig -a + echo '*** uname -a ***' + uname -a + echo '*** mount ***' + mount + echo '*** env ***' + env + echo '*** cat $BASH_ENV ***' + cat $BASH_ENV + + clone_cassandra: &clone_cassandra + run: + name: Clone Cassandra Repository (via git) + command: | + git clone --single-branch --depth 1 --branch $CIRCLE_BRANCH git://github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME.git ~/cassandra + cd ~/cassandra + git remote show origin + echo "Cassandra Commit: $(git rev-parse HEAD) describe $(git describe --tags --long)" + git shortlog --max-count 5 + + clone_dtest: &clone_dtest + run: + name: Clone Cassandra dtest Repository (via git) + command: | + git clone --single-branch --branch master --depth 1 git://github.com/apache/cassandra-dtest.git ~/cassandra-dtest + cd ~/cassandra-dtest + git remote show origin + echo "DTest Commit: $(git rev-parse HEAD) describe $(git describe --tags --long)" + git shortlog --max-count 5 + + configure_java: &configure_java + run: + name: Configure Java environment + command: | + # BASH_ENV is sourced for each step (see https://circleci.com/docs/2.0/env-vars/), + # and lives in /tmp so configure steps should be run once per job (which translates to per + # container instance) + echo 'export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin' >> $BASH_ENV + + configure_dtest_python: &configure_dtest_python + run: + name: Configure virtualenv and python Dependencies + command: | + # note, this should be super quick as all dependencies should be pre-installed in the docker image + # if additional dependencies were added to requirments.txt and the docker image hasn't been updated + # we'd have to install it here at runtime -- which will make things slow, so do yourself a favor and + # rebuild the docker image! (it automatically pulls the latest requirements.txt on build) + source ~/env/bin/activate + export CASS_DRIVER_NO_EXTENSIONS=true + export CASS_DRIVER_NO_CYTHON=true + pip3 install --exists-action w -r ~/cassandra-dtest/requirements.txt + pip3 freeze + # Persist activating virtualenv for other build steps - see configure_java for explanation + echo 'source ~/env/bin/activate' >> $BASH_ENV + + determine_parallel_unit_tests_to_run: &determine_parallel_unit_tests_to_run + run: + name: Determine Tests to Run + no_output_timeout: 15m + command: | + # reminder: this code (along with all the steps) is independently executed on every circle container + # so the goal here is to get the circleci script to return the tests *this* container will run + # which we do via the `circleci` cli tool. + + rm -fr ~/cassandra-dtest/upgrade_tests + echo "***java tests***" + + # get all of our unit test filenames + set -eo pipefail && circleci tests glob "$HOME/cassandra/test/unit/**/*.java" > /tmp/all_java_unit_tests.txt + + # split up the unit tests into groups based on the number of containers we have + set -eo pipefail && circleci tests split --split-by=timings --timings-type=filename --index=${CIRCLE_NODE_INDEX} --total=${CIRCLE_NODE_TOTAL} /tmp/all_java_unit_tests.txt > /tmp/java_tests_${CIRCLE_NODE_INDEX}.txt + set -eo pipefail && cat /tmp/java_tests_${CIRCLE_NODE_INDEX}.txt | cut -c 37-1000000 | grep "Test\.java$" > /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt + echo "** /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt" + cat /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt + + run_parallel_unit_tests: &run_parallel_unit_tests + run: + name: Run Unit Tests + no_output_timeout: 15m + command: | + #Skip all syncing to disk to avoid performance issues in flaky CI environments + export CASSANDRA_SKIP_SYNC=true + + time cp -rp ~/cassandra /tmp + cd /tmp/cassandra + ant testclasslist -Dtest.classlistfile=/tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt || $TEST_SUCCESS_OVERRIDE + + # Determine which tests to run on this node + # Requires environment variables set for the job + # DTEST_TESTS arguments for selecting dtests to run + # DTEST_SUFFIX suffix to add to dtest result files to disambiguate with_vnodes/no_vnodes + determine_parallel_dtests_to_run: &determine_parallel_dtests_to_run + run: + name: Determine Tests to Run + no_output_timeout: 5m + command: | + # reminder: this code (along with all the steps) is independently executed on every circle container + # so the goal here is to get the circleci script to return the tests *this* container will run + # which we do via the `circleci` cli tool. + + cd cassandra-dtest + + echo "***Collected DTests (with vnodes)***" + set -eo pipefail && ./run_dtests.py ${DTEST_TESTS} --dtest-print-tests-only --skip-resource-intensive-tests --dtest-print-tests-output=/tmp/all_dtest_tests_${DTEST_SUFFIX} + set -eo pipefail && circleci tests split --split-by=timings --timings-type=classname /tmp/all_dtest_tests_${DTEST_SUFFIX} > /tmp/split_dtest_tests_${DTEST_SUFFIX}.txt + cat /tmp/split_dtest_tests_${DTEST_SUFFIX}.txt | tr '\n' ' ' > /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt + cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt + + # Run parallel tests, requires same environment variables as determine_parallel_dtests_to_run + run_parallel_dtests: &run_parallel_dtests + run: + name: Run dtests + no_output_timeout: 15m + command: | + echo "cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt" + cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt + + cd ~/cassandra-dtest + mkdir -p /tmp/dtest + + echo "env: $(env)" + echo "** done env" + mkdir -p /tmp/results/dtests + # we need the "set -o pipefail" here so that the exit code that circleci will actually use is from pytest and not the exit code from tee + export SPLIT_TESTS=`cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt` + #Skip all syncing to disk to avoid performance issues in flaky CI environments + export CASSANDRA_SKIP_SYNC=true + set -o pipefail && cd ~/cassandra-dtest && (pytest --log-level="INFO" ${DTEST_TESTS} --junit-xml=/tmp/results/dtests/pytest_result_${DTEST_SUFFIX}.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir $SPLIT_TESTS 2>&1 || $TEST_SUCCESS_OVERRIDE) | tee /tmp/dtest/stdout.txt + default_jobs: &default_jobs jobs: - build @@ -56,62 +231,31 @@ with_dtest_jobs_only: &with_dtest_jobs_only - dtests-no-vnodes: requires: - build -# Set env_settings, env_vars, and workflows/build_and_run_tests based on environment -env_settings: &env_settings - <<: *default_env_settings - #<<: *high_capacity_env_settings -env_vars: &env_vars - <<: *resource_constrained_env_vars - #<<: *high_capacity_env_vars + workflows: version: 2 build_and_run_tests: *default_jobs #build_and_run_tests: *with_dtest_jobs_only #build_and_run_tests: *with_dtest_jobs -docker_image: &docker_image kjellman/cassandra-test:0.4.3 -version: 2 + #build_and_run_tests: *unittest-test-coverage + #build_and_run_tests: *with_dtest_jobs_only-test-coverage + #build_and_run_tests: *with_dtest_jobs-test-coverage + jobs: build: <<: *env_settings - parallelism: 1 # This job doesn't benefit from parallelism - working_directory: ~/ + parallelism: 1 # This job doesn't benefit from parallelism + <<: *container_config shell: /bin/bash -eo pipefail -l - docker: - - image: *docker_image - environment: - <<: *env_vars steps: - - run: - name: Log Environment Information - command: | - echo '*** id ***' - id - echo '*** cat /proc/cpuinfo ***' - cat /proc/cpuinfo - echo '*** free -m ***' - free -m - echo '*** df -m ***' - df -m - echo '*** ifconfig -a ***' - ifconfig -a - echo '*** uname -a ***' - uname -a - echo '*** mount ***' - mount - echo '*** env ***' - env - - run: - name: Clone Cassandra Repository (via git) - command: | - export LANG=en_US.UTF-8 - git clone --single-branch --depth 1 --branch $CIRCLE_BRANCH git://github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME.git ~/cassandra + - *clone_cassandra + - *configure_java + - *log_environment - run: name: Build Cassandra command: | - export LANG=en_US.UTF-8 - export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin cd ~/cassandra + export JAVA_TOOL_OPTIONS=""-Dfile.encoding=UTF8"" # Loop to prevent failure due to maven-ant-tasks not downloading a jar.. for x in $(seq 1 3); do ${ANT_HOME}/bin/ant clean jar @@ -129,10 +273,8 @@ jobs: - run: name: Run eclipse-warnings command: | - export LANG=en_US.UTF-8 - export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin cd ~/cassandra + export JAVA_TOOL_OPTIONS=""-Dfile.encoding=UTF8"" ant eclipse-warnings - persist_to_workspace: root: /home/cassandra @@ -141,126 +283,38 @@ jobs: - .m2 unit_tests: <<: *env_settings - working_directory: ~/ + <<: *container_config shell: /bin/bash -eo pipefail -l - docker: - - image: *docker_image - environment: - <<: *env_vars steps: - - attach_workspace: - at: /home/cassandra - - run: - name: Determine Tests to Run - no_output_timeout: 15m - command: | - # reminder: this code (along with all the steps) is independently executed on every circle container - # so the goal here is to get the circleci script to return the tests *this* container will run - # which we do via the `circleci` cli tool. - - export LANG=en_US.UTF-8 - rm -fr ~/cassandra-dtest/upgrade_tests - echo "***java tests***" - - # get all of our unit test filenames - set -eo pipefail && circleci tests glob "$HOME/cassandra/test/unit/**/*.java" > /tmp/all_java_unit_tests.txt - - # split up the unit tests into groups based on the number of containers we have - set -eo pipefail && circleci tests split --split-by=timings --timings-type=filename --index=${CIRCLE_NODE_INDEX} --total=${CIRCLE_NODE_TOTAL} /tmp/all_java_unit_tests.txt > /tmp/java_tests_${CIRCLE_NODE_INDEX}.txt - set -eo pipefail && cat /tmp/java_tests_${CIRCLE_NODE_INDEX}.txt | cut -c 37-1000000 | grep "Test\.java$" > /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt - echo "** /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt" - cat /tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt - - run: - name: Run Unit Tests - command: | - export LANG=en_US.UTF-8 - export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - #Skip all syncing to disk to avoid performance issues in flaky CI environments - export CASSANDRA_SKIP_SYNC=true - - time mv ~/cassandra /tmp - cd /tmp/cassandra - ant testclasslist -Dtest.classlistfile=/tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt - no_output_timeout: 15m + - *attach_workspace + - *configure_java + - *log_environment + - *determine_parallel_unit_tests_to_run + - *run_parallel_unit_tests - store_test_results: - path: /tmp/cassandra/build/test/output/ + path: /tmp/cassandra/build/test/output/ - store_artifacts: path: /tmp/cassandra/build/test/output destination: junitxml - store_artifacts: path: /tmp/cassandra/build/test/logs destination: logs + dtests-with-vnodes: <<: *env_settings - working_directory: ~/ + <<: *container_config + environment: + DTEST_TESTS: --use-vnodes --num-tokens=32 + DTEST_SUFFIX: with_vnodes shell: /bin/bash -eo pipefail -l - docker: - - image: *docker_image - environment: - <<: *env_vars steps: - - attach_workspace: - at: /home/cassandra - - run: - name: Clone Cassandra dtest Repository (via git) - command: | - export LANG=en_US.UTF-8 - git clone --single-branch --branch master --depth 1 git://github.com/apache/cassandra-dtest.git ~/cassandra-dtest - - run: - name: Configure virtualenv and python Dependencies - command: | - # note, this should be super quick as all dependencies should be pre-installed in the docker image - # if additional dependencies were added to requirmeents.txt and the docker image hasn't been updated - # we'd have to install it here at runtime -- which will make things slow, so do yourself a favor and - # rebuild the docker image! (it automatically pulls the latest requirements.txt on build) - export LANG=en_US.UTF-8 - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - export CASS_DRIVER_NO_EXTENSIONS=true - export CASS_DRIVER_NO_CYTHON=true - pip3 install --exists-action w -r ~/cassandra-dtest/requirements.txt - pip3 freeze - - run: - name: Determine Tests to Run - no_output_timeout: 5m - command: | - # reminder: this code (along with all the steps) is independently executed on every circle container - # so the goal here is to get the circleci script to return the tests *this* container will run - # which we do via the `circleci` cli tool. - - export LANG=en_US.UTF-8 - cd cassandra-dtest - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - - echo "***Collected DTests (with vnodes)***" - set -eo pipefail && ./run_dtests.py --use-vnodes --dtest-print-tests-only --skip-resource-intensive-tests --dtest-print-tests-output=/tmp/all_dtest_tests_with_vnodes - set -eo pipefail && circleci tests split --split-by=timings --timings-type=classname /tmp/all_dtest_tests_with_vnodes > /tmp/split_dtest_tests_with_vnodes.txt - cat /tmp/split_dtest_tests_with_vnodes.txt | tr '\n' ' ' > /tmp/split_dtest_tests_with_vnodes_final.txt - # cat /tmp/split_dtest_tests_with_vnodes.txt - cat /tmp/split_dtest_tests_with_vnodes_final.txt - - run: - name: Run dtests (with vnodes) - no_output_timeout: 15m - command: | - echo "cat /tmp/split_dtest_tests_with_vnodes_final.txt" - cat /tmp/split_dtest_tests_with_vnodes_final.txt - - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - - cd ~/cassandra-dtest - mkdir -p /tmp/dtest - - echo "env: $(env)" - echo "** done env" - mkdir -p /tmp/results/dtests - # we need the "set -o pipefail" here so that the exit code that circleci will actually use is from pytest and not the exit code from tee - export SPLIT_TESTS=`cat /tmp/split_dtest_tests_with_vnodes_final.txt` - #Skip all syncing to disk to avoid performance issues in flaky CI environments - export CASSANDRA_SKIP_SYNC=true - set -o pipefail && cd ~/cassandra-dtest && pytest --log-level="INFO" --use-vnodes --num-tokens=32 --junit-xml=/tmp/results/dtests/pytest_result_with_vnodes.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir $SPLIT_TESTS 2>&1 | tee /tmp/dtest/stdout.txt + - *attach_workspace + - *clone_dtest + - *configure_java + - *configure_dtest_python + - *log_environment + - *determine_parallel_dtests_to_run + - *run_parallel_dtests - store_test_results: path: /tmp/results - store_artifacts: @@ -269,74 +323,22 @@ jobs: - store_artifacts: path: ~/cassandra-dtest/logs destination: dtest_with_vnodes_logs + dtests-no-vnodes: <<: *env_settings - working_directory: ~/ + <<: *container_config + environment: + DTEST_TESTS: "" # default is test with no vnodes + DTEST_SUFFIX: without_vnodes shell: /bin/bash -eo pipefail -l - docker: - - image: *docker_image - environment: - <<: *env_vars steps: - - attach_workspace: - at: /home/cassandra - - run: - name: Clone Cassandra dtest Repository (via git) - command: | - export LANG=en_US.UTF-8 - git clone --single-branch --branch master --depth 1 git://github.com/apache/cassandra-dtest.git ~/cassandra-dtest - - run: - name: Configure virtualenv and python Dependencies - command: | - # note, this should be super quick as all dependencies should be pre-installed in the docker image - # if additional dependencies were added to requirmeents.txt and the docker image hasn't been updated - # we'd have to install it here at runtime -- which will make things slow, so do yourself a favor and - # rebuild the docker image! (it automatically pulls the latest requirements.txt on build) - export LANG=en_US.UTF-8 - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - export CASS_DRIVER_NO_EXTENSIONS=true - export CASS_DRIVER_NO_CYTHON=true - pip3 install --exists-action w -r ~/cassandra-dtest/requirements.txt - pip3 freeze - - run: - name: Determine Tests to Run - no_output_timeout: 5m - command: | - # reminder: this code (along with all the steps) is independently executed on every circle container - # so the goal here is to get the circleci script to return the tests *this* container will run - # which we do via the `circleci` cli tool. - - export LANG=en_US.UTF-8 - cd cassandra-dtest - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - - echo "***Collected DTests (without vnodes)***" - ./run_dtests.py --dtest-print-tests-only --skip-resource-intensive-tests --dtest-print-tests-output=/tmp/all_dtest_tests_without_vnodes - set -eo pipefail && circleci tests split --split-by=timings --timings-type=classname /tmp/all_dtest_tests_without_vnodes > /tmp/split_dtest_tests_without_vnodes.txt - cat /tmp/split_dtest_tests_without_vnodes.txt | tr '\n' ' ' > /tmp/split_dtest_tests_without_vnodes_final.txt - # cat /tmp/split_dtest_tests_without_vnodes.txt - cat /tmp/split_dtest_tests_without_vnodes_final.txt - - run: - name: Run dtests (without vnodes) - no_output_timeout: 15m - command: | - # for now require at least 50 circleci containers to run the dtests (with less resources the tests won't produce reliable results or will fail to complete) - if [ $CIRCLE_NODE_TOTAL -gt 0 ]; then - source ~/env/bin/activate - export PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin - - cd ~/cassandra-dtest - mkdir -p /tmp/dtest - - mkdir -p /tmp/results/dtests - # we need the "set -o pipefail" here so that the exit code that circleci will actually use is from pytest and not the exit code from tee - export SPLIT_TESTS=`cat /tmp/split_dtest_tests_without_vnodes_final.txt` - #Skip all syncing to disk to avoid performance issues in flaky CI environments - export CASSANDRA_SKIP_SYNC=true - set -o pipefail && cd ~/cassandra-dtest && pytest --log-level="INFO" --junit-xml=/tmp/results/dtests/pytest_result_novnodes.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir $SPLIT_TESTS 2>&1 | tee /tmp/dtest/stdout-novnodes.txt - fi + - *attach_workspace + - *clone_dtest + - *configure_java + - *configure_dtest_python + - *log_environment + - *determine_parallel_dtests_to_run + - *run_parallel_dtests - store_test_results: path: /tmp/results - store_artifacts: From d2d7e3c2f3f134d32c1a08357117dddf8c47515f Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Fri, 21 Sep 2018 14:01:08 -0600 Subject: [PATCH 2/6] circecli: clean whitespace to satisfy yamllint warnings --- .circleci/config.yml | 70 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 66cf4bf05497..da4943789160 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -205,41 +205,41 @@ references: set -o pipefail && cd ~/cassandra-dtest && (pytest --log-level="INFO" ${DTEST_TESTS} --junit-xml=/tmp/results/dtests/pytest_result_${DTEST_SUFFIX}.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir $SPLIT_TESTS 2>&1 || $TEST_SUCCESS_OVERRIDE) | tee /tmp/dtest/stdout.txt default_jobs: &default_jobs - jobs: - - build - - unit_tests: - requires: - - build + jobs: + - build + - unit_tests: + requires: + - build with_dtests_jobs: &with_dtest_jobs - jobs: - - build - - unit_tests: - requires: - - build - - dtests-with-vnodes: - requires: - - build - - dtests-no-vnodes: - requires: - - build + jobs: + - build + - unit_tests: + requires: + - build + - dtests-with-vnodes: + requires: + - build + - dtests-no-vnodes: + requires: + - build with_dtest_jobs_only: &with_dtest_jobs_only - jobs: - - build - - dtests-with-vnodes: - requires: - - build - - dtests-no-vnodes: - requires: - - build + jobs: + - build + - dtests-with-vnodes: + requires: + - build + - dtests-no-vnodes: + requires: + - build workflows: - version: 2 - build_and_run_tests: *default_jobs - #build_and_run_tests: *with_dtest_jobs_only - #build_and_run_tests: *with_dtest_jobs - #build_and_run_tests: *unittest-test-coverage - #build_and_run_tests: *with_dtest_jobs_only-test-coverage - #build_and_run_tests: *with_dtest_jobs-test-coverage + version: 2 + build_and_run_tests: *default_jobs + # build_and_run_tests: *with_dtest_jobs_only + # build_and_run_tests: *with_dtest_jobs + # build_and_run_tests: *unittest-test-coverage + # build_and_run_tests: *with_dtest_jobs_only-test-coverage + # build_and_run_tests: *with_dtest_jobs-test-coverage jobs: build: @@ -277,10 +277,10 @@ jobs: export JAVA_TOOL_OPTIONS=""-Dfile.encoding=UTF8"" ant eclipse-warnings - persist_to_workspace: - root: /home/cassandra - paths: - - cassandra - - .m2 + root: /home/cassandra + paths: + - cassandra + - .m2 unit_tests: <<: *env_settings <<: *container_config From 13c6c5a3111f3cbf3c30d9b8e812be14bfbbbaba Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Fri, 21 Sep 2018 13:57:26 -0600 Subject: [PATCH 3/6] circleci: Add test coverage jobs and workflows. --- .circleci/config.yml | 196 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index da4943789160..d96748aeeaaf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -162,6 +162,23 @@ references: cd /tmp/cassandra ant testclasslist -Dtest.classlistfile=/tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt || $TEST_SUCCESS_OVERRIDE + run_parallel_unit_tests_gen_coverage: &run_parallel_unit_tests_gen_coverage + run: + name: Run Unit Tests with test coverage + no_output_timeout: 15m + command: | + #Skip all syncing to disk to avoid performance issues in flaky CI environments + export CASSANDRA_SKIP_SYNC=true + + time cp -rp ~/cassandra /tmp + cd /tmp/cassandra + + # Generate unique exec file for each running container + export JACOCO_EXECFILE=/home/cassandra/cassandra/build/jacoco/partials/partial-unit_tests-${CIRCLE_NODE_INDEX}.exec + + ant jacoco-run -Dtaskname=testclasslist -Dtest.classlistfile=/tmp/java_tests_${CIRCLE_NODE_INDEX}_final.txt -Djacoco.partialexecfile=${JACOCO_EXECFILE} || $TEST_SUCCESS_OVERRIDE + find $(dirname ${JACOCO_EXECFILE}) -ls + # Determine which tests to run on this node # Requires environment variables set for the job # DTEST_TESTS arguments for selecting dtests to run @@ -204,6 +221,37 @@ references: export CASSANDRA_SKIP_SYNC=true set -o pipefail && cd ~/cassandra-dtest && (pytest --log-level="INFO" ${DTEST_TESTS} --junit-xml=/tmp/results/dtests/pytest_result_${DTEST_SUFFIX}.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir $SPLIT_TESTS 2>&1 || $TEST_SUCCESS_OVERRIDE) | tee /tmp/dtest/stdout.txt + # Run parallel tests, requires same environment variables as determine_parallel_dtests_to_run + run_parallel_dtests_gen_coverage: &run_parallel_dtests_gen_coverage + run: + name: Run dtests + no_output_timeout: 15m + command: | + echo "cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt" + cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt + + cd ~/cassandra-dtest + mkdir -p /tmp/dtest + + echo "env: $(env)" + echo "** done env" + mkdir -p /tmp/results/dtests + # we need the "set -o pipefail" here so that the exit code that circleci will actually use is from pytest and not the exit code from tee + export SPLIT_TESTS=`cat /tmp/split_dtest_tests_${DTEST_SUFFIX}_final.txt` + #Skip all syncing to disk to avoid performance issues in flaky CI environments + export CASSANDRA_SKIP_SYNC=true + + # Generate unique exec file for each running container + export JACOCO_EXECFILE=/home/cassandra/cassandra/build/jacoco/partials/partial-dtest_${DTEST_SUFFIX}-${CIRCLE_NODE_INDEX}.exec + + set -o pipefail && cd ~/cassandra-dtest && (pytest --log-level="INFO" ${DTEST_TESTS} --junit-xml=/tmp/results/dtests/pytest_result_${DTEST_SUFFIX}.xml -s --cassandra-dir=/home/cassandra/cassandra --skip-resource-intensive-tests --keep-test-dir --enable-jacoco-code-coverage $SPLIT_TESTS 2>&1 || $TEST_SUCCESS_OVERRIDE) | tee /tmp/dtest/stdout.txt + + persist_jacoco_workspace: &persist_jacoco_workspace + persist_to_workspace: + root: /home/cassandra + paths: + - cassandra/build/jacoco/partials + default_jobs: &default_jobs jobs: - build @@ -232,6 +280,49 @@ with_dtest_jobs_only: &with_dtest_jobs_only requires: - build +unittest-test-coverage: &unittest-test-coverage + jobs: + - build + - unit_tests_gen_coverage: + requires: + - build + - coverage_report: + requires: + - unit_tests_gen_coverage + +with_dtests_jobs-test-coverage: &with_dtest_jobs-test-coverage + jobs: + - build + - unit_tests_gen_coverage: + requires: + - build + - dtests-with-vnodes_gen_coverage: + requires: + - build + - dtests-no-vnodes_gen_coverage: + requires: + - build + - coverage_report: + requires: + - unit_tests_gen_coverage + - dtests-with-vnodes_gen_coverage + - dtests-no-vnodes_gen_coverage + +with_dtest_jobs_only-test-coverage: &with_dtest_jobs_only-test-coverage + jobs: + - build + - dtests-with-vnodes_gen_coverage: + requires: + - build + - dtests-no-vnodes_gen_coverage: + requires: + - build + - coverage_report: + requires: + - dtests-with-vnodes_gen_coverage + - dtests-no-vnodes_gen_coverage + + workflows: version: 2 build_and_run_tests: *default_jobs @@ -300,6 +391,28 @@ jobs: path: /tmp/cassandra/build/test/logs destination: logs + unit_tests_gen_coverage: + <<: *env_settings + <<: *container_config + environment: + TEST_SUCCESS_OVERRIDE: /bin/true + shell: /bin/bash -eo pipefail -l + steps: + - *attach_workspace + - *configure_java + - *log_environment + - *determine_parallel_unit_tests_to_run + - *run_parallel_unit_tests_gen_coverage + - store_test_results: + path: /tmp/cassandra/build/test/output/ + - store_artifacts: + path: /tmp/cassandra/build/test/output + destination: junitxml + - store_artifacts: + path: /tmp/cassandra/build/test/logs + destination: logs + - *persist_jacoco_workspace + dtests-with-vnodes: <<: *env_settings <<: *container_config @@ -347,3 +460,86 @@ jobs: - store_artifacts: path: ~/cassandra-dtest/logs destination: dtest_no_vnodes_logs + + dtests-with-vnodes_gen_coverage: + <<: *env_settings + <<: *container_config + environment: + DTEST_TESTS: --use-vnodes --num-tokens=32 + DTEST_SUFFIX: with_vnodes + TEST_SUCCESS_OVERRIDE: /bin/true + shell: /bin/bash -eo pipefail -l + steps: + - *attach_workspace + - *clone_dtest + - *configure_java + - *configure_dtest_python + - *log_environment + - *determine_parallel_dtests_to_run + - *run_parallel_dtests_gen_coverage + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/dtest + destination: dtest_with_vnodes + - store_artifacts: + path: ~/cassandra-dtest/logs + destination: dtest_with_vnodes_logs + - *persist_jacoco_workspace + + dtests-no-vnodes_gen_coverage: + <<: *env_settings + <<: *container_config + environment: + DTEST_TESTS: "" # default is test with no vnodes + DTEST_SUFFIX: without_vnodes + TEST_SUCCESS_OVERRIDE: /bin/true + shell: /bin/bash -eo pipefail -l + steps: + - *attach_workspace + - *clone_dtest + - *configure_java + - *configure_dtest_python + - *log_environment + - *determine_parallel_dtests_to_run + - *run_parallel_dtests_gen_coverage + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/dtest + destination: dtest_no_vnodes + - store_artifacts: + path: ~/cassandra-dtest/logs + destination: dtest_no_vnodes_logs + - *persist_jacoco_workspace + + # Generate a code coverage report from the partial data stored under + # ~/cassandra/build/jacococ. Any previous jobs *must* apply the + # *persist_jacoco_workspace step, and the job spec must set all tasks that + # generate coverage information as a dependency. + coverage_report: + <<: *env_settings + parallelism: 1 # This job doesn't benefit from parallelism + <<: *container_config + working_directory: ~/ + shell: /bin/bash -eo pipefail -l + steps: + - *attach_workspace + - *configure_java + - run: + name: Generate code coverage report + no_output_timeout: 15m + command: | + cd ~/cassandra + find build/jacoco -ls + ant jacoco-report + # It took 20 mins to upload all of the artifacts from a full + # coverage run, so create an archive fork download instead. + mkdir -p build/jacoco-report + rsync -a build/jacoco build/jacoco-report/cassandra-coverage-${CIRCLE_SHA1} --exclude '*.exec' + mkdir -p build/jacoco-report-tgz + cd build/jacoco-report + tar cfz ../jacoco-report-tgz/cassandra-coverage-${CIRCLE_SHA1}.tar.gz cassandra-coverage-${CIRCLE_SHA1} + - store_artifacts: + path: /home/cassandra/cassandra/build/jacoco-report-tgz + destination: jacoco From 7eb925d567debfc0bf4123940207ecc49bca0919 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Fri, 21 Sep 2018 13:39:43 -0600 Subject: [PATCH 4/6] circleci: Added comment header block --- .circleci/config.yml | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d96748aeeaaf..4e0ccb188f03 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,51 @@ --- # yamllint disable rule:line-length +# +# CircleCI Configuration +# +# Workflows +# --------- +# Several different workflows are supported, to switch between +# them enable the desired on in the workflow: section below +# +# default_jobs - build the jar and run unit tests +# with_dtest_jobs_only - build the jar and dtests (no unittests) +# with_dtest_jobs - build the jar, unit tests and dtests +# unittest-test-coverage - as above with test coverage +# with_dtest_jobs_only-test-coverage - as above with test coverage +# with_dtest_jobs-test-coverage - as above with test coverage +# +# +# CircleCI Capacity +# ----------------- +# If you have access to additional capacity in CircleCI, update the +# env_settings and env_vars section to comment out the default and enable +# the high_capacity options. +# +# When modifying the config, to spot errors as early as possible in +# the edit/push cycle the command below does some pre-validation of +# problems. +# +# $ circleci config validate && yamllint .circleci/config.yml +# +# +# Test Coverage +# ------------- +# Workflows with test coverage enabled use JaCoCo to generate +# a coverage report and upload it to the build artifacts. +# +# The report is named after the commit being tested. +# +# N.B. when running with test coverage the unit tests/dtest +# jobs are forced to succeed so that coverage inforamtion +# can be collected even when tests fail. CircleCI will +# parse the junitxml generated by those jobs and show +# if there are any problems. +# +# The behavior can be changed by commenting out the +# TEST_SUCCESS_OVERRIDE environment variable in the +# gen_coverage jobs. + version: 2.0 references: From c14bb122995bb217c8412d75cceb6b6cf10fc9a0 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Thu, 13 Sep 2018 16:33:30 -0600 Subject: [PATCH 5/6] Upgrade JaCoCo from 0.7.5.201505241946 to 0.8.2 Enables experimental support for Java 11/12. --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index 86462f7bfd82..cb8af98889d5 100644 --- a/build.xml +++ b/build.xml @@ -115,7 +115,7 @@ - + From 0d96bddc383191818b4ffa8f3fa7e935e95b07c7 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Sun, 23 Sep 2018 11:19:30 -0600 Subject: [PATCH 6/6] circleci: Omit generated lexer/parser from coverage The data from it is not particularly helpful and having it present reduces the impact of the missed instruction/branches bars in the coverage report. --- build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build.xml b/build.xml index cb8af98889d5..7feadad5230b 100644 --- a/build.xml +++ b/build.xml @@ -1613,6 +1613,7 @@ +