diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile deleted file mode 100644 index 92d87ec2ad..0000000000 --- a/.ci/Jenkinsfile +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env groovy -@Library('apm@current') _ - -pipeline { - agent { label 'linux && immutable' } - environment { - REPO = 'apm-agent-nodejs' - BASE_DIR = "src/github.com/elastic/${env.REPO}" - PIPELINE_LOG_LEVEL = 'INFO' - } - options { - timeout(time: 1, unit: 'HOURS') - buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30')) - timestamps() - ansiColor('xterm') - disableResume() - durabilityHint('PERFORMANCE_OPTIMIZED') - rateLimitBuilds(throttle: [count: 60, durationName: 'hour', userBoost: true]) - quietPeriod(10) - } - triggers { - issueCommentTrigger("^run benchmark tests.*") - } - parameters { - booleanParam(name: 'bench_ci', defaultValue: true, description: 'Enable benchmarks.') - } - stages { - /** - Checkout the code and stash it, to use it on other stages. - */ - stage('Checkout') { - options { skipDefaultCheckout() } - when { - beforeAgent true - allOf { - anyOf { - branch 'main' - expression { return env.GITHUB_COMMENT?.contains('benchmark tests') } - } - expression { return params.bench_ci } - } - } - steps { - pipelineManager([ cancelPreviousRunningBuilds: [ when: 'PR' ] ]) - deleteDir() - gitCheckout(basedir: "${BASE_DIR}", githubNotifyFirstTimeContributor: true, - shallow: false, reference: "/var/lib/jenkins/.git-references/${REPO}.git") - stash allowEmpty: true, name: 'source', useDefaultExcludes: false - } - } - /** - Run the benchmarks and store the results on ES. - The result JSON files are also archive into Jenkins. - */ - stage('Benchmarks') { - agent { label 'microbenchmarks-pool' } - options { skipDefaultCheckout() } - environment { - HOME = "${env.WORKSPACE}" - RESULT_FILE = 'apm-agent-benchmark-results.json' - NODE_VERSION = '14' - } - when { - beforeAgent true - allOf { - anyOf { - branch 'main' - expression { return env.GITHUB_COMMENT?.contains('benchmark tests') } - } - expression { return params.bench_ci } - } - } - steps { - withGithubNotify(context: 'Benchmarks', tab: 'artifacts') { - dir(env.BUILD_NUMBER) { - deleteDir() - unstash 'source' - dir(BASE_DIR){ - sh '.ci/scripts/run-benchmarks.sh "${RESULT_FILE}" "${NODE_VERSION}"' - } - } - } - } - post { - always { - catchError(message: 'sendBenchmarks failed', buildResult: 'FAILURE') { - sendBenchmarks(file: "${BUILD_NUMBER}/${BASE_DIR}/${RESULT_FILE}", - index: 'benchmark-nodejs', archive: true) - } - catchError(message: 'deleteDir failed', buildResult: 'SUCCESS', stageResult: 'UNSTABLE') { - deleteDir() - } - } - } - } - } -} diff --git a/.ci/jobs/apm-agent-nodejs-mbp.yml b/.ci/jobs/apm-agent-nodejs-mbp.yml deleted file mode 100644 index 9e754d1b6d..0000000000 --- a/.ci/jobs/apm-agent-nodejs-mbp.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -- job: - name: apm-agent-nodejs/apm-agent-nodejs-mbp - display-name: APM Agent Node.js - description: APM Agent Node.js - script-path: .ci/Jenkinsfile - scm: - - github: - branch-discovery: no-pr - discover-pr-forks-strategy: merge-current - discover-pr-forks-trust: permission - discover-pr-origin: merge-current - discover-tags: true - notification-context: 'apm-ci' - # Run CI builds only on main, PRs, non-EOL version branches, and release tags after v3.29.0. - head-filter-regex: '^(main|PR-.*|3\.x|v3.3[0-9].*|v3.[4-9].*|v[4-9].*)$' - repo: apm-agent-nodejs - repo-owner: elastic - credentials-id: 2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken - ssh-checkout: - credentials: f6c7695a-671e-4f4f-a331-acdce44ff9ba - build-strategies: - - tags: - ignore-tags-older-than: -1 - ignore-tags-newer-than: -1 - - regular-branches: true - - change-request: - ignore-target-only-changes: true - clean: - after: true - before: true - prune: true - shallow-clone: true - depth: 3 - do-not-fetch-tags: true - submodule: - disable: false - recursive: true - parent-credentials: true - timeout: 100 - reference-repo: /var/lib/jenkins/.git-references/apm-agent-nodejs.git - timeout: '15' - use-author: true - wipe-workspace: 'True' diff --git a/.ci/jobs/apm-agent-nodejs-schedule-daily.yml b/.ci/jobs/apm-agent-nodejs-schedule-daily.yml deleted file mode 100644 index defc156b55..0000000000 --- a/.ci/jobs/apm-agent-nodejs-schedule-daily.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- job: - name: apm-agent-nodejs/apm-agent-nodejs-schedule-daily - display-name: Node.js Jobs scheduled daily - description: Node.js Jobs scheduled daily from Monday to Friday - view: APM-CI - project-type: pipeline - parameters: - - string: - name: branch_specifier - default: main - description: the Git branch specifier to build - pipeline-scm: - script-path: .ci/schedule-daily.groovy - scm: - - git: - url: git@github.com:elastic/apm-agent-nodejs.git - refspec: +refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pr/* - wipe-workspace: 'True' - name: origin - shallow-clone: true - credentials-id: f6c7695a-671e-4f4f-a331-acdce44ff9ba - reference-repo: /var/lib/jenkins/.git-references/apm-agent-nodejs.git - branches: - - $branch_specifier - triggers: - - timed: 'H H(4-5) * * 1-5' diff --git a/.ci/jobs/apm-agent-nodejs.yml b/.ci/jobs/apm-agent-nodejs.yml deleted file mode 100644 index 2d308417ea..0000000000 --- a/.ci/jobs/apm-agent-nodejs.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- job: - name: apm-agent-nodejs - project-type: folder diff --git a/.ci/jobs/defaults.yml b/.ci/jobs/defaults.yml deleted file mode 100644 index 49b9e34bd6..0000000000 --- a/.ci/jobs/defaults.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- - -##### GLOBAL METADATA - -- meta: - cluster: apm-ci - -##### JOB DEFAULTS - -- job: - view: APM-CI - project-type: multibranch - logrotate: - numToKeep: 100 - number-to-keep: '5' - days-to-keep: '1' - concurrent: true - node: linux - prune-dead-branches: true - publishers: - - email: - recipients: infra-root+build@elastic.co diff --git a/.ci/schedule-daily.groovy b/.ci/schedule-daily.groovy deleted file mode 100644 index d67de741fd..0000000000 --- a/.ci/schedule-daily.groovy +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -@Library('apm@current') _ - -pipeline { - agent { label 'master' } - environment { - NOTIFY_TO = credentials('notify-to') - PIPELINE_LOG_LEVEL='INFO' - } - options { - timeout(time: 1, unit: 'HOURS') - buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30')) - timestamps() - ansiColor('xterm') - disableResume() - durabilityHint('PERFORMANCE_OPTIMIZED') - } - triggers { - cron('H H(4-5) * * 1-5') - } - stages { - stage('Run Tasks'){ - steps { - script { - ['main'].each { branch -> - build( - job: "apm-agent-nodejs/apm-agent-nodejs-mbp/${branch}", - parameters: [ - booleanParam(name: 'Run_As_Main_Branch', value: true), - booleanParam(name: 'bench_ci', value: false), - booleanParam(name: 'doc_ci', value: true), - booleanParam(name: 'tav_ci', value: true), - booleanParam(name: 'test_edge_ci', value: true) - ], - quietPeriod: 10, - wait: false - ) - } - } - } - } - } - post { - cleanup { - notifyBuildResult() - } - } -} diff --git a/.ci/scripts/bench.sh b/.ci/scripts/bench.sh new file mode 100755 index 0000000000..d509b60d9f --- /dev/null +++ b/.ci/scripts/bench.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Bash strict mode +set -eo pipefail + +# Found current script directory +RELATIVE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Found project directory +BASE_PROJECT="$(dirname "$(dirname "${RELATIVE_DIR}")")" + +# Run the microbenchmark in Buildkite and for such +# it configures the required settings in the Buildkite runners +# to execute the benchmarks afterwards + +## Buildkite specific configuration +if [ "${CI}" == "true" ] ; then + # If HOME is not set then use the Buildkite workspace + # that's normally happening when running in the CI + # owned by Elastic. + if [ -z "${HOME}" ] ; then + HOME="${BUILDKITE_BUILD_CHECKOUT_PATH}" + export HOME + fi +fi + +# Run benchmark +echo "--- Execute benchmarks" +"${BASE_PROJECT}/.ci/scripts/run-benchmarks.sh" "apm-agent-benchmark-results.json" "$(cat "${BASE_PROJECT}/.nvmrc")" + +echo "--- Send benchmark results" +sendBenchmark "${ES_USER_SECRET}" "${ES_PASS_SECRET}" "${ES_URL_SECRET}" "apm-agent-benchmark-results.json" diff --git a/.ci/scripts/prepare-benchmarks-env.sh b/.ci/scripts/prepare-benchmarks-env.sh index a74e915849..ad80af487a 100755 --- a/.ci/scripts/prepare-benchmarks-env.sh +++ b/.ci/scripts/prepare-benchmarks-env.sh @@ -6,27 +6,42 @@ # Usage: # NODE_VERSION=... # source .../prepare-benchmarks-env.sh +# +# Note: echo "--- ..." helps with presenting the output in Buildkite. +# set -xeo pipefail -if [[ -z "$NODE_VERSION" ]]; then +if [[ -z "${NODE_VERSION}" ]]; then echo "prepare-benchmarks-env.sh: error: NODE_VERSION envvar is not set" >&2 exit 1 fi +echo "--- Download nvm" # This particular configuration is required to be installed in the baremetal curl -sS -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash -export NVM_DIR="$HOME/.nvm" +export NVM_DIR="${HOME}/.nvm" + +echo "--- Install nvm" set +x # Disable xtrace because output using nvm.sh is huge. -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +# Flush positional arguments +shift $# +if [ -s "${NVM_DIR}/nvm.sh" ] ; then + \. "${NVM_DIR}/nvm.sh" +fi + +# Check nvm command is available command -v nvm nvm --version +echo "--- Run nvm install ${NODE_VERSION}" nvm install "${NODE_VERSION}" -set -x - -npm config list -npm install +# Check node command is available node --version npm --version + +echo "--- Install dependencies" +set -x +npm config list +npm install diff --git a/.ci/scripts/run-benchmarks.sh b/.ci/scripts/run-benchmarks.sh index 147b8e2d34..084ef20b26 100755 --- a/.ci/scripts/run-benchmarks.sh +++ b/.ci/scripts/run-benchmarks.sh @@ -1,6 +1,15 @@ #!/usr/bin/env bash -set -xueo pipefail +# Bash strict mode +set -eo pipefail + +# Found current script directory +RELATIVE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Found project directory +BASE_PROJECT="$(dirname "$(dirname "${RELATIVE_DIR}")")" + +# Arguments RESULT_FILE=$1 NODE_VERSION=$2 if [[ -z "$RESULT_FILE" || -z "$NODE_VERSION" ]]; then @@ -8,7 +17,9 @@ if [[ -z "$RESULT_FILE" || -z "$NODE_VERSION" ]]; then exit 1 fi -SCRIPTPATH=$(dirname "$0") -source ./${SCRIPTPATH}/prepare-benchmarks-env.sh +# Prepare benchmark environment +export NODE_VERSION="${NODE_VERSION}" +source "${RELATIVE_DIR}/prepare-benchmarks-env.sh" +# Run benchmark npm run bench:ci "${RESULT_FILE}" "${NODE_VERSION}" diff --git a/.github/workflows/microbenchmark.yml b/.github/workflows/microbenchmark.yml new file mode 100644 index 0000000000..8c73117ea4 --- /dev/null +++ b/.github/workflows/microbenchmark.yml @@ -0,0 +1,50 @@ +name: microbenchmark + +on: + workflow_dispatch: + push: + branches: + - main + paths-ignore: + - '**/*.md' + - '**/*.asciidoc' + - 'docs/**' + - 'examples/**' + +# limit the access of the generated GITHUB_TOKEN +permissions: + contents: read + +jobs: + microbenchmark: + runs-on: ubuntu-latest + # wait up to 1 hour + timeout-minutes: 60 + steps: + - id: buildkite + name: Run buildkite pipeline + uses: elastic/apm-pipeline-library/.github/actions/buildkite@current + with: + vaultUrl: ${{ secrets.VAULT_ADDR }} + vaultRoleId: ${{ secrets.VAULT_ROLE_ID }} + vaultSecretId: ${{ secrets.VAULT_SECRET_ID }} + pipeline: apm-agent-microbenchmark + triggerMessage: "${{ github.repository }}@${{ github.ref_name }}" + waitFor: true + printBuildLogs: true + buildEnvVars: | + script=.ci/scripts/bench.sh + repo=apm-agent-nodejs + sha=${{ github.sha }} + BRANCH_NAME=${{ github.ref_name }} + + - if: ${{ failure() }} + uses: elastic/apm-pipeline-library/.github/actions/slack-message@current + with: + url: ${{ secrets.VAULT_ADDR }} + roleId: ${{ secrets.VAULT_ROLE_ID }} + secretId: ${{ secrets.VAULT_SECRET_ID }} + channel: "#apm-agent-nodejs" + message: | + :ghost: [${{ github.repository }}] microbenchmark *${{ github.ref_name }}* failed to run in Buildkite. + Build: (<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|here>) diff --git a/.nvmrc b/.nvmrc index fac0b0a839..47979412e9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.20.0 +16.20.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09d8835cc1..d58e13dd40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -160,7 +160,7 @@ The following is an overview of what's required in order to add support to the a 1. List the supported versions of the package in [`docs/supported-technologies.asciidoc`](docs/supported-technologies.asciidoc) 1. We use the [test-all-versions](https://github.com/watson/test-all-versions) module to test the agent against all supported versions of each package we instrument. Add the supported versions and required test commands to the [`.tav.yml`](.tav.yml) file -1. Add the name of the module to one of the TAV groups in [`test/.jenkins_tav.yml`](test/.jenkins_tav.yml) for all Node.js versions. +1. Add the name of the module to one of the TAV groups in [`.ci/tav.json`](.ci/tav.json) for all Node.js versions. To better balance the work requried to run each TAV group, pick the TAV group that is currently running the fastest. diff --git a/test/benchmarks/scripts/run-benchmarks-ci.sh b/test/benchmarks/scripts/run-benchmarks-ci.sh index 51d01ca42d..94ac6ad81a 100755 --- a/test/benchmarks/scripts/run-benchmarks-ci.sh +++ b/test/benchmarks/scripts/run-benchmarks-ci.sh @@ -80,14 +80,12 @@ function safe_env_export() { } function benchmark() { - echo "export GIT_BUILD_CAUSE='${GIT_BUILD_CAUSE}'" > env_vars.sh - echo "export GIT_BASE_COMMIT='${GIT_BASE_COMMIT}'" >> env_vars.sh - echo "export GIT_COMMIT='${GIT_COMMIT}'" >> env_vars.sh - echo "export BRANCH_NAME='${BRANCH_NAME}'" >> env_vars.sh - echo "export CHANGE_ID='${CHANGE_ID}'" >> env_vars.sh - safe_env_export "CHANGE_TITLE" "${CHANGE_TITLE}" >> env_vars.sh - echo "export CHANGE_TARGET='${CHANGE_TARGET}'" >> env_vars.sh - echo "export CHANGE_URL='${CHANGE_URL}'" >> env_vars.sh + # sha and BRANCH_NAME are variables passed throught the GitHub action + echo "export BRANCH_NAME='${BRANCH_NAME}'" > env_vars.sh + echo "export GIT_BASE_COMMIT='${sha}'" >> env_vars.sh + # Needed by the benchmark script + echo "export GIT_BUILD_CAUSE='${GITHUB_EVENT_NAME}'" >> env_vars.sh + echo "export GIT_COMMIT='${sha}'" >> env_vars.sh sudo -n cset proc --exec /benchmark -- ./"${SCRIPTPATH}"/run-benchmarks.sh all "${RESULT_FILE}" "${NODE_VERSION}" }