version: 2.1 # Common variables, containers, jobs and steps. job_defaults: &job_defaults # TODO: We should move away from using a directory # TODO: that requires root permission to be created. # TODO: Changing this requires rebuilding all docker images. working_directory: /app shell: /bin/bash --login test_containers: - &job_parameters parameters: ruby_version: description: Ruby version type: string image: description: Docker image location type: string jit: description: Jit enabled? type: boolean default: false - &container_base_environment BUNDLE_GEMFILE: /app/Gemfile - &container_parameters_environment - *container_base_environment - RUBY_OPT: <<# parameters.jit >>--jit<> - TEST_DATADOG_INTEGRATION: 1 - COVERAGE_BASE_DIR: coverage - &container_base image: <> environment: *container_parameters_environment - &test_job_default <<: *job_defaults <<: *job_parameters docker: - *container_base - &container_postgres image: postgres:9.6 environment: - POSTGRES_PASSWORD=postgres - POSTGRES_USER=postgres - POSTGRES_DB=postgres - &postgres_port 5432 - &container_presto image: prestosql/presto - &presto_port 8080 - &container_mysql image: mysql:5.6 environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_PASSWORD=mysql - MYSQL_USER=mysql - &mysql_port 3306 - &container_elasticsearch image: elasticsearch:2.4 - &elasticsearch_port 9200 - &container_redis image: redis:3.0 - &redis_port 6379 - &container_mongo image: mongo:3.5 - &mongo_port 27017 - &container_memcached image: memcached:1.5-alpine - &memcached_port 11211 - &container_agent image: datadog/docker-dd-agent environment: - DD_APM_ENABLED=true - DD_BIND_HOST=0.0.0.0 - DD_API_KEY=invalid_key_but_this_is_fine - &agent_port 8126 step_init_bundle_checksum: &step_init_bundle_checksum run: name: Initialize bundle cache key command: | touch .circleci/bundle_checksum step_bundle_install: &step_bundle_install run: name: Install gem dependencies command: bundle install step_rubocop: &step_rubocop run: name: Delint with Rubocop command: bundle exec rake rubocop step_appraisal_install: &step_appraisal_install run: name: Install Appraisal gems command: | bundle exec appraisal clean # Ensure we fetch the latest version of dependencies bundle exec appraisal install step_compute_bundle_checksum: &step_compute_bundle_checksum run: name: Compute bundle checksum command: | # JRuby: Ensure files exist when Appraisal generates no output mkdir gemfiles touch gemfiles/_.gemfile.lock cat Gemfile.lock gemfiles/*.gemfile.lock > .circleci/bundle_checksum step_run_all_tests: &step_run_all_tests run: name: Run tests command: | echo " --format=progress --format=RspecJunitFormatter --out='/tmp/rspec/-<%= ARGV.join.gsub('/', '-') %>.xml' " > .rspec-local # Configure RSpec metadata exporter bundle exec rake ci step_release_docs: &step_release_docs run: name: Upload release docs command: S3_DIR=trace bundle exec rake release:docs filters_all_branches_and_tags: &filters_all_branches_and_tags filters: tags: only: /.*/ filters_only_release_tags: &filters_only_release_tags filters: branches: ignore: /.*/ tags: only: /^v\d+(\.\d+){0,3}(\.(alpha|beta|rc)\d+)?$/ orbs: orb: jobs: build: <<: *test_job_default steps: - checkout - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - bundle-{{ .Environment.CIRCLE_CACHE_VERSION }}-<>-{{ checksum "lib/ddtrace/version.rb" }}-{{ .Branch }}-{{ checksum "Gemfile" }}-{{ checksum "Appraisals" }}-{{ checksum "ddtrace.gemspec" }} - bundle-{{ .Environment.CIRCLE_CACHE_VERSION }}-<>-{{ checksum "lib/ddtrace/version.rb" }}-{{ .Branch }}- - bundle-{{ .Environment.CIRCLE_CACHE_VERSION }}-<>-{{ checksum "lib/ddtrace/version.rb" }} - *step_init_bundle_checksum - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - *step_bundle_install - *step_appraisal_install - *step_compute_bundle_checksum - save_cache: key: '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' paths: - /app - save_cache: key: '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' paths: - /usr/local/bundle - save_cache: key: bundle-{{ .Environment.CIRCLE_CACHE_VERSION }}-<>-{{ checksum "lib/ddtrace/version.rb" }}-{{ .Branch }}-{{ checksum "Gemfile" }}-{{ checksum "Appraisals" }}-{{ checksum "ddtrace.gemspec" }}-{{ checksum ".circleci/bundle_checksum" }}' paths: - /usr/local/bundle test: <<: *test_job_default docker: - <<: *container_base - *container_postgres - *container_presto - *container_mysql - *container_elasticsearch - *container_redis - *container_mongo - *container_memcached - *container_agent parallelism: 22 steps: - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - run: name: Set coverage report directory command: | # Create a unique coverage directory for this job, to avoid conflicts when merging all results echo 'export COVERAGE_DIR="$COVERAGE_BASE_DIR/versions/$CIRCLE_JOB/$CIRCLE_NODE_INDEX"' >> $BASH_ENV # Wait for containers to start - docker-wait: port: *postgres_port - docker-wait: port: *presto_port - docker-wait: port: *mysql_port - docker-wait: port: *elasticsearch_port - docker-wait: port: *redis_port - docker-wait: port: *mongo_port - docker-wait: port: *memcached_port - docker-wait: port: *agent_port - *step_run_all_tests - store_test_results: path: /tmp/rspec - persist_to_workspace: root: . paths: - coverage benchmark: <<: *test_job_default docker: - <<: *container_base - *container_postgres - *container_redis - *container_agent steps: - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - run: name: Run Benchmark command: bundle exec appraisal rails5-postgres-sidekiq ruby benchmarks/sidekiq_test.rb 2>&1 1> /dev/null | tee benchmark_results.csv - run: name: Run Benchmark without ddtracer command: rm -f lib/ddtrace.rb && bundle exec appraisal rails5-postgres-sidekiq ruby benchmarks/sidekiq_test.rb 2>&1 1> /dev/null | tee benchmark_results.csv lint: <<: *test_job_default steps: - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - *step_rubocop coverage: <<: *test_job_default steps: - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - attach_workspace: at: /tmp/workspace - run: name: Install codecov command: bundle add codecov - run: name: Generate coverage report artifact "coverage/index.html" command: COVERAGE_DIR=/tmp/workspace/coverage bundle exec rake coverage:report - run: name: Generate coverage report artifact "coverage/versions/*/index.html" command: COVERAGE_DIR=/tmp/workspace/coverage bundle exec rake coverage:report_per_ruby_version - store_artifacts: path: /tmp/workspace/coverage/report/ destination: coverage changelog: <<: *test_job_default steps: - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundled-repo-<>-{{ .Environment.CIRCLE_SHA1 }}' - restore_cache: keys: - '{{ .Environment.CIRCLE_CACHE_VERSION }}-bundle-<>-{{ checksum ".circleci/bundle_checksum" }}' - attach_workspace: at: /tmp/workspace - run: name: Format changelog command: bundle exec rake changelog:format - run: name: Check if changelog was unformatted command: | if ! git diff-files --quiet; then echo "Please run 'bundle exec rake changelog:format' and commit the results." fi commands: docker-wait: description: Wait for containers to listen on a TCP port. parameters: port: description: TCP port the container is listening on. type: integer timeout: description: How long to wait for the port to be responsive. type: string default: 1m steps: - run: name: Wait for container on port <> command: dockerize -wait 'tcp://localhost:<>' -timeout '<>' executors: jobs: "deploy release": <<: *job_defaults docker: - environment: *container_base_environment image: marcotc/docker-library:ddtrace_rb_2_5_6 steps: - checkout - run: name: Install AWS CLI command: | apt-get -y -qq update apt-get -y -qq install awscli - *step_bundle_install - *step_release_docs - run: name: Upload release Gem and rebuild index command: S3_DIR=release bundle exec rake release:gem - store_artifacts: path: pkg/ destination: gem "deploy prerelease Gem": <<: *job_defaults docker: - environment: *container_base_environment image: marcotc/docker-library:ddtrace_rb_2_5_6 steps: - run: name: Check if this commit author has publishing credentials command: | if [[ -z "${AWS_ACCESS_KEY_ID}" ]] then echo 'No AWS credentials, skipping publish of pre-release build.' circleci task halt fi - checkout - run: name: Install AWS CLI command: | apt-get -y -qq update apt-get -y -qq install awscli - *step_bundle_install - run: name: Rename to pre-release version based on branch name and build number command: | # create safe version string PRE=$(echo "${CIRCLE_BRANCH:-unknown}.${CIRCLE_BUILD_NUM:-R$RANDOM}" | sed -e 's/[^a-zA-Z0-9+]\{1,\}/./g') echo PRE=$PRE sed lib/ddtrace/version.rb -i -e "s/^\([\t ]*PRE\) *=*/\1 = \'${PRE}\' #/g" - run: name: Upload prereleas Gem and rebuild index command: S3_DIR=prerelease bundle exec rake release:gem - store_artifacts: path: pkg/ destination: gem job_configuration: # MRI - &config-2_0 <<: *filters_all_branches_and_tags ruby_version: '2.0' image: palazzem/docker-library:ddtrace_rb_2_0_0 - &config-2_1 <<: *filters_all_branches_and_tags ruby_version: '2.1' image: palazzem/docker-library:ddtrace_rb_2_1_10 - &config-2_2 <<: *filters_all_branches_and_tags ruby_version: '2.2' image: palazzem/docker-library:ddtrace_rb_2_2_10 - &config-2_3 <<: *filters_all_branches_and_tags ruby_version: '2.3' image: palazzem/docker-library:ddtrace_rb_2_3_8 - &config-2_4 <<: *filters_all_branches_and_tags ruby_version: '2.4' image: palazzem/docker-library:ddtrace_rb_2_4_6 - &config-2_5 <<: *filters_all_branches_and_tags ruby_version: '2.5' image: marcotc/docker-library:ddtrace_rb_2_5_6 - &config-2_6 <<: *filters_all_branches_and_tags ruby_version: '2.6' image: marcotc/docker-library:ddtrace_rb_2_6_4 - &config-2_7 <<: *filters_all_branches_and_tags ruby_version: '2.7' image: marcotc/docker-library:ddtrace_rb_2_7_0 - &config-3_0 <<: *filters_all_branches_and_tags ruby_version: '3.0' image: marcotc/docker-library:ddtrace_rb_3.0.0 - &config-3_0-jit <<: *filters_all_branches_and_tags ruby_version: '3.0' image: marcotc/docker-library:ddtrace_rb_3.0.0 jit: true # JRuby - &config-jruby-9_2 <<: *filters_all_branches_and_tags ruby_version: 'jruby-9.2' image: marcotc/docker-library:ddtrace_rb_jruby_9_2 workflows: version: 2 build-and-test: jobs: - orb/lint: <<: *config-2_6 name: lint requires: - build-2.6 - orb/coverage: <<: *config-2_7 name: coverage requires: - test-2.0 - test-2.1 - test-2.2 - test-2.3 - test-2.4 - test-2.5 - test-2.6 - test-2.7 - test-3.0 - test-jruby-9.2 - orb/changelog: <<: *config-2_7 name: changelog requires: - build-2.7 filters: branches: only: /bump_to_version_.*/ # MRI - orb/build: <<: *config-2_0 name: build-2.0 - orb/test: <<: *config-2_0 name: test-2.0 requires: - build-2.0 - orb/build: <<: *config-2_1 name: build-2.1 - orb/test: <<: *config-2_1 name: test-2.1 requires: - build-2.1 - orb/build: <<: *config-2_2 name: build-2.2 - orb/test: <<: *config-2_2 name: test-2.2 requires: - build-2.2 - orb/build: <<: *config-2_3 name: build-2.3 - orb/test: <<: *config-2_3 name: test-2.3 requires: - build-2.3 - orb/benchmark: <<: *config-2_3 name: benchmark-2.3 requires: - build-2.3 - orb/build: <<: *config-2_4 name: build-2.4 - orb/test: <<: *config-2_4 name: test-2.4 requires: - build-2.4 - orb/build: <<: *config-2_5 name: build-2.5 - orb/test: <<: *config-2_5 name: test-2.5 requires: - build-2.5 - orb/build: <<: *config-2_6 name: build-2.6 - orb/test: <<: *config-2_6 name: test-2.6 requires: - build-2.6 - orb/build: <<: *config-2_7 name: build-2.7 - orb/test: <<: *config-2_7 name: test-2.7 requires: - build-2.7 - orb/build: <<: *config-3_0 name: build-3.0 - orb/test: <<: *config-3_0 name: test-3.0 requires: - build-3.0 - orb/build: <<: *config-3_0-jit name: build-3.0-jit - orb/test: <<: *config-3_0-jit name: test-3.0-jit requires: - build-3.0-jit # JRuby - orb/build: <<: *config-jruby-9_2 name: build-jruby-9.2 - orb/test: <<: *config-jruby-9_2 name: test-jruby-9.2 requires: - build-jruby-9.2 # Release jobs - "deploy prerelease Gem": <<: *filters_all_branches_and_tags requires: - lint - test-2.0 - test-2.1 - test-2.2 - test-2.3 - test-2.4 - test-2.5 - test-2.6 - test-2.7 - test-3.0 - test-3.0-jit - test-jruby-9.2 - "deploy release": <<: *filters_only_release_tags requires: - lint - test-2.0 - test-2.1 - test-2.2 - test-2.3 - test-2.4 - test-2.5 - test-2.6 - test-2.7 - test-3.0 - test-3.0-jit - test-jruby-9.2