diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 8e9b041d32d3e..0cd64dcfd41fd 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -12,8 +12,7 @@ pipeline { environment { BASE_DIR = 'src/github.com/elastic/kibana' HOME = "${env.WORKSPACE}" - APM_ITS = 'apm-integration-testing' - CYPRESS_DIR = 'x-pack/plugins/apm/e2e' + E2E_DIR = 'x-pack/plugins/apm/e2e' PIPELINE_LOG_LEVEL = 'DEBUG' } options { @@ -43,32 +42,6 @@ pipeline { env.APM_UPDATED = isGitRegionMatch(patterns: regexps) } } - dir("${APM_ITS}"){ - git changelog: false, - credentialsId: 'f6c7695a-671e-4f4f-a331-acdce44ff9ba', - poll: false, - url: "git@github.com:elastic/${APM_ITS}.git" - } - } - } - stage('Start services') { - options { skipDefaultCheckout() } - when { - anyOf { - expression { return params.FORCE } - expression { return env.APM_UPDATED != "false" } - } - } - steps { - notifyStatus('Starting services', 'PENDING') - dir("${APM_ITS}"){ - sh './scripts/compose.py start master --no-kibana' - } - } - post { - unsuccessful { - notifyStatus('Environmental issue', 'FAILURE') - } } } stage('Prepare Kibana') { @@ -85,7 +58,7 @@ pipeline { steps { notifyStatus('Preparing kibana', 'PENDING') dir("${BASE_DIR}"){ - sh script: "${CYPRESS_DIR}/ci/prepare-kibana.sh" + sh "${E2E_DIR}/ci/prepare-kibana.sh" } } post { @@ -105,24 +78,20 @@ pipeline { steps{ notifyStatus('Running smoke tests', 'PENDING') dir("${BASE_DIR}"){ - sh ''' - jobs -l - docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) ${CYPRESS_DIR}/ci - docker run --rm -t --user "$(id -u):$(id -g)" \ - -v `pwd`:/app --network="host" \ - --name cypress cypress''' + sh "${E2E_DIR}/ci/run-e2e.sh" } } post { always { - dir("${BASE_DIR}"){ - archiveArtifacts(allowEmptyArchive: false, artifacts: "${CYPRESS_DIR}/**/screenshots/**,${CYPRESS_DIR}/**/videos/**,${CYPRESS_DIR}/**/test-results/*e2e-tests.xml") - junit(allowEmptyResults: true, testResults: "${CYPRESS_DIR}/**/test-results/*e2e-tests.xml") - } - dir("${APM_ITS}"){ - sh 'docker-compose logs > apm-its.log || true' - sh 'docker-compose down -v || true' - archiveArtifacts(allowEmptyArchive: false, artifacts: 'apm-its.log') + dir("${BASE_DIR}/${E2E_DIR}"){ + archiveArtifacts(allowEmptyArchive: false, artifacts: 'cypress/screenshots/**,cypress/videos/**,cypress/test-results/*e2e-tests.xml') + junit(allowEmptyResults: true, testResults: 'cypress/test-results/*e2e-tests.xml') + dir('tmp/apm-integration-testing'){ + sh 'docker-compose logs > apm-its-docker.log || true' + sh 'docker-compose down -v || true' + archiveArtifacts(allowEmptyArchive: true, artifacts: 'apm-its-docker.log') + } + archiveArtifacts(allowEmptyArchive: true, artifacts: 'tmp/*.log') } } unsuccessful { @@ -137,7 +106,7 @@ pipeline { post { always { dir("${BASE_DIR}"){ - archiveArtifacts(allowEmptyArchive: true, artifacts: "${CYPRESS_DIR}/ingest-data.log,kibana.log") + archiveArtifacts(allowEmptyArchive: true, artifacts: "${E2E_DIR}/kibana.log") } } } diff --git a/x-pack/plugins/apm/e2e/README.md b/x-pack/plugins/apm/e2e/README.md index b630747ac2d3e..cf29b14d19541 100644 --- a/x-pack/plugins/apm/e2e/README.md +++ b/x-pack/plugins/apm/e2e/README.md @@ -6,21 +6,4 @@ x-pack/plugins/apm/e2e/run-e2e.sh ``` -_Starts Kibana, APM Server, Elasticsearch (with sample data) and runs the tests_ - -## Reproducing CI builds - -> This process is very slow compared to the local development described above. Consider that the CI must install and configure the build tools and create a Docker image for the project to run tests in a consistent manner. - -The Jenkins CI uses a shell script to prepare Kibana: - -```shell -# Prepare and run Kibana locally -$ x-pack/plugins/apm/e2e/ci/prepare-kibana.sh -# Build Docker image for Kibana -$ docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) x-pack/plugins/apm/e2e/ci -# Run Docker image -$ docker run --rm -t --user "$(id -u):$(id -g)" \ - -v `pwd`:/app --network="host" \ - --name cypress cypress -``` +_Starts APM Server, Elasticsearch (with sample data) and runs the tests_ diff --git a/x-pack/plugins/apm/e2e/ci/Dockerfile b/x-pack/plugins/apm/e2e/ci/Dockerfile deleted file mode 100644 index 2bcc5a5fd843a..0000000000000 --- a/x-pack/plugins/apm/e2e/ci/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -ARG NODE_VERSION -FROM node:$NODE_VERSION - -RUN apt-get -qq update \ - && apt-get -y -qq install xvfb \ - libgtk-3-0 \ - libxtst6 \ - libnotify-dev \ - libgconf-2-4 \ - libnss3 \ - libxss1 \ - libasound2 \ - --no-install-recommends \ - && rm -rf /var/lib/apt/lists/* - -## Add host.docker.internal to localhost -RUN apt-get -qq update \ - && apt-get -y -qq install dnsutils \ - --no-install-recommends \ - && rm -rf /var/lib/apt/lists/* - -COPY entrypoint.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/x-pack/plugins/apm/e2e/ci/entrypoint.sh b/x-pack/plugins/apm/e2e/ci/entrypoint.sh deleted file mode 100755 index 3349aa74dadb9..0000000000000 --- a/x-pack/plugins/apm/e2e/ci/entrypoint.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -set -xe - -## host.docker.internal is not available in native docker installations -kibana=$(dig +short host.docker.internal) -if [ -z "${kibana}" ] ; then - kibana=127.0.0.1 -fi - -export CYPRESS_BASE_URL=http://${kibana}:5701 - -## To avoid issues with the home and caching artifacts -export HOME=/tmp -npm config set cache ${HOME} - -## To avoid issues with volumes. -#rsync -rv --exclude=.git --exclude=docs \ -# --exclude=.cache --exclude=node_modules \ -# --exclude=test/ \ -# --exclude=src/ \ -# --exclude=packages/ \ -# --exclude=built_assets --exclude=target \ -# --exclude=data /app ${HOME}/ -#cd ${HOME}/app/x-pack/plugins/apm/e2e/cypress - -cd /app/x-pack/plugins/apm/e2e -## Install dependencies for cypress -CI=true npm install -yarn install - -# Wait for the kibana to be up and running -npm install wait-on -./node_modules/.bin/wait-on ${CYPRESS_BASE_URL}/status && echo 'Kibana is up and running' - -# Run cypress -npm run cypress:run diff --git a/x-pack/plugins/apm/e2e/ci/prepare-kibana.sh b/x-pack/plugins/apm/e2e/ci/prepare-kibana.sh index 637f8fa9b4c74..f383dd6d16f7f 100755 --- a/x-pack/plugins/apm/e2e/ci/prepare-kibana.sh +++ b/x-pack/plugins/apm/e2e/ci/prepare-kibana.sh @@ -1,21 +1,13 @@ #!/usr/bin/env bash -set -e +set -ex -E2E_DIR="x-pack/plugins/apm/e2e" - -echo "1/3 Install dependencies ..." +E2E_DIR=x-pack/plugins/apm/e2e +echo "1/2 Install dependencies ..." # shellcheck disable=SC1091 source src/dev/ci_setup/setup_env.sh true -yarn kbn bootstrap - -echo "2/3 Ingest test data ..." -pushd ${E2E_DIR} -yarn install -curl --silent https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output ingest-data/events.json -node ingest-data/replay.js --server-url http://localhost:8201 --secret-token abcd --events ./events.json > ingest-data.log +yarn kbn clean && yarn kbn bootstrap -echo "3/3 Start Kibana ..." -popd +echo "2/2 Start Kibana ..." ## Might help to avoid FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory export NODE_OPTIONS="--max-old-space-size=4096" -nohup node scripts/kibana --config "${E2E_DIR}/ci/kibana.e2e.yml" --no-base-path --optimize.watch=false> kibana.log 2>&1 & +nohup node ./scripts/kibana --no-base-path --no-watch --dev --no-dev-config --config ${E2E_DIR}/ci/kibana.e2e.yml > ${E2E_DIR}/kibana.log 2>&1 & diff --git a/x-pack/plugins/apm/e2e/ci/run-e2e.sh b/x-pack/plugins/apm/e2e/ci/run-e2e.sh new file mode 100755 index 0000000000000..c40ab5d646477 --- /dev/null +++ b/x-pack/plugins/apm/e2e/ci/run-e2e.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +## +## This is a wrapper to configure the environment with the right tools in the CI +## and run the e2e steps. +## + +E2E_DIR="${0%/*}/.." +# shellcheck disable=SC1091 +source src/dev/ci_setup/setup_env.sh true +set -ex +"${E2E_DIR}"/run-e2e.sh diff --git a/x-pack/plugins/apm/e2e/cypress.json b/x-pack/plugins/apm/e2e/cypress.json index 0894cfd13a197..33304c2d8625f 100644 --- a/x-pack/plugins/apm/e2e/cypress.json +++ b/x-pack/plugins/apm/e2e/cypress.json @@ -1,7 +1,6 @@ { "nodeVersion": "system", "baseUrl": "http://localhost:5701", - "video": false, "trashAssetsBeforeRuns": false, "fileServerFolder": "../", "fixturesFolder": "./cypress/fixtures", @@ -9,6 +8,8 @@ "pluginsFile": "./cypress/plugins/index.js", "screenshotsFolder": "./cypress/screenshots", "supportFile": "./cypress/support/index.ts", + "video": true, + "videoCompression": false, "videosFolder": "./cypress/videos", "useRelativeSnapshots": true, "reporter": "junit", diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts index 1e3228fdb0319..361d055db9ac1 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts @@ -7,6 +7,9 @@ import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps'; import { loginAndWaitForPage } from '../../integration/helpers'; +/** The default time in ms to wait for a Cypress command to complete */ +export const DEFAULT_TIMEOUT = 60 * 1000; + Given(`a user browses the APM UI application`, () => { // open service overview page loginAndWaitForPage(`/app/apm#/services`); @@ -14,7 +17,9 @@ Given(`a user browses the APM UI application`, () => { When(`the user inspects the opbeans-node service`, () => { // click opbeans-node service - cy.get(':contains(opbeans-node)').last().click({ force: true }); + cy.get(':contains(opbeans-node)', { timeout: DEFAULT_TIMEOUT }) + .last() + .click({ force: true }); }); Then(`should redirect to correct path with correct params`, () => { diff --git a/x-pack/plugins/apm/e2e/cypress/videos/apm.feature.mp4 b/x-pack/plugins/apm/e2e/cypress/videos/apm.feature.mp4 new file mode 100644 index 0000000000000..93c310aaa0d4e Binary files /dev/null and b/x-pack/plugins/apm/e2e/cypress/videos/apm.feature.mp4 differ diff --git a/x-pack/plugins/apm/e2e/run-e2e.sh b/x-pack/plugins/apm/e2e/run-e2e.sh index ebfd29377e013..157c42cc7e4ee 100755 --- a/x-pack/plugins/apm/e2e/run-e2e.sh +++ b/x-pack/plugins/apm/e2e/run-e2e.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # variables KIBANA_PORT=5701 @@ -65,6 +65,8 @@ ${APM_IT_DIR}/scripts/compose.py start master \ --elasticsearch-port $ELASTICSEARCH_PORT \ --apm-server-port=$APM_SERVER_PORT \ --elasticsearch-heap 4g \ + --apm-server-opt queue.mem.events=8192 \ + --apm-server-opt output.elasticsearch.bulk_max_size=4096 \ &> ${TMP_DIR}/apm-it.log # Stop if apm-integration-testing failed to start correctly @@ -98,7 +100,7 @@ curl --silent --user admin:changeme -XDELETE "localhost:${ELASTICSEARCH_PORT}/.a curl --silent --user admin:changeme -XDELETE "localhost:${ELASTICSEARCH_PORT}/apm*" > /dev/null # Ingest data into APM Server -node ingest-data/replay.js --server-url http://localhost:$APM_SERVER_PORT --events ${TMP_DIR}/events.json 2> ${TMP_DIR}/ingest-data.log +node ingest-data/replay.js --server-url http://localhost:$APM_SERVER_PORT --events ${TMP_DIR}/events.json 2>> ${TMP_DIR}/ingest-data.log # Stop if not all events were ingested correctly if [ $? -ne 0 ]; then @@ -113,6 +115,15 @@ echo "\n${bold}Waiting for Kibana to start...${normal}" echo "Note: you need to start Kibana manually. Find the instructions at the top." yarn wait-on -i 500 -w 500 http-get://admin:changeme@localhost:$KIBANA_PORT/api/status > /dev/null +## Workaround to wait for the http server running +## See: https://github.com/elastic/kibana/issues/66326 +if [ -e kibana.log ] ; then + grep -m 1 "http server running" <(tail -f -n +1 kibana.log) + echo "\n✅ Kibana server running...\n" + grep -m 1 "bundles compiled successfully" <(tail -f -n +1 kibana.log) + echo "\n✅ Kibana bundles have been compiled...\n" +fi + echo "\n✅ Setup completed successfully. Running tests...\n" # @@ -129,4 +140,3 @@ ${bold}If you want to run the test interactively, run:${normal} yarn cypress open --config pageLoadTimeout=100000,watchForFileChanges=true " -