Skip to content

[Backport 8.18] Migrate integration tests to built JS files #2780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
---
agents:
provider: "gcp"
image: family/core-ubuntu-2204
memory: "8G"
cpu: "2"

steps:
- label: ":elasticsearch: :javascript: ES JavaScript ({{ matrix.nodejs }}) Test Suite: {{ matrix.suite }}"
agents:
provider: "gcp"
- label: ":elasticsearch: :javascript: ES JavaScript ({{ matrix.nodejs }})"
env:
NODE_VERSION: "{{ matrix.nodejs }}"
TEST_SUITE: "{{ matrix.suite }}"
STACK_VERSION: 8.16.0
TEST_SUITE: "platinum"
STACK_VERSION: 9.0.0
GITHUB_TOKEN_PATH: "secret/ci/elastic-elasticsearch-js/github-token"
TEST_ES_STACK: "1"
matrix:
setup:
suite:
- "free"
- "platinum"
nodejs:
- "18"
- "20"
Expand All @@ -21,9 +24,6 @@ steps:
- wait: ~
continue_on_failure: true
- label: ":junit: Test results"
agents:
provider: "gcp"
image: family/core-ubuntu-2204
plugins:
- junit-annotate#v2.4.1:
artifacts: "junit-output/junit-*.xml"
Expand Down
39 changes: 23 additions & 16 deletions .buildkite/run-client.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,29 @@ export NODE_VERSION=${NODE_VERSION:-18}

echo "--- :javascript: Building Docker image"
docker build \
--file "$script_path/Dockerfile" \
--tag elastic/elasticsearch-js \
--build-arg NODE_VERSION="$NODE_VERSION" \
.
--file "$script_path/Dockerfile" \
--tag elastic/elasticsearch-js \
--build-arg NODE_VERSION="$NODE_VERSION" \
.

echo "--- :javascript: Running $TEST_SUITE tests"
GITHUB_TOKEN=$(vault read -field=token "$GITHUB_TOKEN_PATH")
export GITHUB_TOKEN

echo "--- :javascript: Running tests"
mkdir -p "$repo/junit-output"
docker run \
--network="${network_name}" \
--env "TEST_ES_SERVER=${elasticsearch_url}" \
--env "ELASTIC_PASSWORD=${elastic_password}" \
--env "TEST_SUITE=${TEST_SUITE}" \
--env "ELASTIC_USER=elastic" \
--env "BUILDKITE=true" \
--volume "$repo/junit-output:/junit-output" \
--name elasticsearch-js \
--rm \
elastic/elasticsearch-js \
bash -c "npm run test:integration; [ -f ./$TEST_SUITE-report-junit.xml ] && mv ./$TEST_SUITE-report-junit.xml /junit-output/junit-$BUILDKITE_JOB_ID.xml || echo 'No JUnit artifact found'"
--network="${network_name}" \
--env TEST_ES_STACK \
--env STACK_VERSION \
--env GITHUB_TOKEN \
--env "TEST_ES_SERVER=${elasticsearch_url}" \
--env "ELASTIC_PASSWORD=${elastic_password}" \
--env "ELASTIC_USER=elastic" \
--env "BUILDKITE=true" \
--volume "/usr/src/app/node_modules" \
--volume "$repo:/usr/src/app" \
--volume "$repo/junit-output:/junit-output" \
--name elasticsearch-js \
--rm \
elastic/elasticsearch-js \
bash -c "npm run test:integration; [ -f ./report-junit.xml ] && mv ./report-junit.xml /junit-output/junit-$BUILDKITE_JOB_ID.xml || echo 'No JUnit artifact found'"
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ elasticsearch
lib
junit-output
.tap
rest-api-spec
yaml-rest-tests
generated-tests
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,7 @@ bun.lockb
test-results
processinfo
.tap
rest-api-spec
yaml-rest-tests
generated-tests
schema
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,6 @@ CONTRIBUTING.md
src
bun.lockb
.tap
rest-api-spec
yaml-rest-tests
generated-tests
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"test:coverage-100": "npm run build && tap --coverage --100",
"test:coverage-report": "npm run build && tap --coverage && nyc report --reporter=text-lcov > coverage.lcov",
"test:coverage-ui": "npm run build && tap --coverage --coverage-report=html",
"test:integration": "tsc && node test/integration/index.js",
"test:integration-build": "npm run build && node test/integration/index.js",
"test:integration": "npm run test:integration-build && env tap run --jobs=1 --reporter=junit --reporter-file=report-junit.xml generated-tests/",
"lint": "ts-standard src",
"lint:fix": "ts-standard --fix src",
"license-checker": "license-checker --production --onlyAllow='MIT;Apache-2.0;Apache1.1;ISC;BSD-3-Clause;BSD-2-Clause;0BSD'",
Expand Down Expand Up @@ -76,8 +77,8 @@
"node-fetch": "2.7.0",
"ora": "5.4.1",
"proxy": "1.0.2",
"rimraf": "3.0.2",
"semver": "7.6.3",
"rimraf": "5.0.10",
"semver": "7.7.1",
"split2": "4.2.0",
"stoppable": "1.1.0",
"tap": "21.0.1",
Expand Down
170 changes: 55 additions & 115 deletions scripts/download-artifacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,162 +17,102 @@
* under the License.
*/

'use strict'

const { join } = require('path')
const minimist = require('minimist')
const stream = require('stream')
const { promisify } = require('util')
const { createWriteStream, promises } = require('fs')
const rimraf = require('rimraf')
const { rimraf } = require('rimraf')
const fetch = require('node-fetch')
const crossZip = require('cross-zip')
const ora = require('ora')

const { mkdir, writeFile } = promises
const { mkdir, cp } = promises
const pipeline = promisify(stream.pipeline)
const unzip = promisify(crossZip.unzip)
const rm = promisify(rimraf)

const esFolder = join(__dirname, '..', 'elasticsearch')
const zipFolder = join(esFolder, 'artifacts.zip')
const specFolder = join(esFolder, 'rest-api-spec', 'api')
const freeTestFolder = join(esFolder, 'rest-api-spec', 'test', 'free')
const xPackTestFolder = join(esFolder, 'rest-api-spec', 'test', 'platinum')
const artifactInfo = join(esFolder, 'info.json')

async function downloadArtifacts (opts) {
if (typeof opts.version !== 'string') {
throw new Error('Missing version')
}

const log = ora('Checking out spec and test').start()
const testYamlFolder = join(__dirname, '..', 'yaml-rest-tests')
const zipFile = join(__dirname, '..', 'elasticsearch-clients-tests.zip')

log.text = 'Resolving versions'
let resolved
try {
resolved = await resolve(opts.version, opts.hash)
} catch (err) {
log.fail(err.message)
process.exit(1)
}
const schemaFolder = join(__dirname, '..', 'schema')
const schemaJson = join(schemaFolder, 'schema.json')

opts.id = opts.id || resolved.id
opts.hash = opts.hash || resolved.hash
opts.version = resolved.version
async function downloadArtifacts (localTests, version = 'main') {
const log = ora('Checking out spec and test').start()

const info = loadInfo()
const { GITHUB_TOKEN } = process.env

if (info && info.version === opts.version) {
if (info.hash === opts.hash && info.id === opts.id) {
log.succeed('The artifact copy present locally is already up to date')
return
}
if (version !== 'main') {
version = version.split('.').slice(0, 2).join('.')
}

log.text = 'Cleanup checkouts/elasticsearch'
await rm(esFolder)
await mkdir(esFolder, { recursive: true })
log.text = 'Clean tests folder'
await rimraf(testYamlFolder)
await mkdir(testYamlFolder, { recursive: true })

log.text = 'Downloading artifacts'
const response = await fetch(resolved.url)
if (!response.ok) {
log.fail(`unexpected response ${response.statusText}`)
process.exit(1)
}
await pipeline(response.body, createWriteStream(zipFolder))
log.text = `Fetch test YAML files for version ${version}`

log.text = 'Unzipping'
await unzip(zipFolder, esFolder)
if (localTests) {
log.text = `Copying local tests from ${localTests}`
await cp(localTests, testYamlFolder, { recursive: true })
} else {
if (!GITHUB_TOKEN) {
log.fail("Missing required environment variable 'GITHUB_TOKEN'")
process.exit(1)
}

log.text = 'Cleanup'
await rm(zipFolder)
const response = await fetch(`https://api.github.com/repos/elastic/elasticsearch-clients-tests/zipball/${version}`, {
headers: {
Authorization: `Bearer ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github+json'
}
})

log.text = 'Update info'
await writeFile(artifactInfo, JSON.stringify(opts), 'utf8')
if (!response.ok) {
log.fail(`unexpected response ${response.statusText}`)
process.exit(1)
}

log.succeed('Done')
}
log.text = 'Downloading tests zipball'
await pipeline(response.body, createWriteStream(zipFile))

function loadInfo () {
try {
return require(artifactInfo)
} catch (err) {
return null
}
}
log.text = 'Unzipping tests'
await unzip(zipFile, testYamlFolder)

async function resolve (version, hash) {
const response = await fetch(`https://artifacts-api.elastic.co/v1/versions/${version}`)
if (!response.ok) {
throw new Error(`unexpected response ${response.statusText}`)
log.text = 'Cleanup'
await rimraf(zipFile)
}

const data = await response.json()
const esBuilds = data.version.builds
.filter(build => build.projects.elasticsearch != null)
.map(build => {
return {
projects: build.projects.elasticsearch,
buildId: build.build_id,
date: build.start_time,
version: build.version
}
})
.sort((a, b) => {
const dA = new Date(a.date)
const dB = new Date(b.date)
if (dA > dB) return -1
if (dA < dB) return 1
return 0
})
log.text = 'Fetching Elasticsearch specification'
await rimraf(schemaFolder)
await mkdir(schemaFolder, { recursive: true })

if (hash != null) {
const build = esBuilds.find(build => build.projects.commit_hash === hash)
if (!build) {
throw new Error(`Can't find any build with hash '${hash}'`)
}
const zipKey = Object.keys(build.projects.packages).find(key => key.startsWith('rest-resources-zip-') && key.endsWith('.zip'))
return {
url: build.projects.packages[zipKey].url,
id: build.buildId,
hash: build.projects.commit_hash,
version: build.version
}
const response = await fetch(`https://raw.githubusercontent.com/elastic/elasticsearch-specification/${version}/output/schema/schema.json`)
if (!response.ok) {
log.fail(`unexpected response ${response.statusText}`)
process.exit(1)
}

const lastBuild = esBuilds[0]
const zipKey = Object.keys(lastBuild.projects.packages).find(key => key.startsWith('rest-resources-zip-') && key.endsWith('.zip'))
return {
url: lastBuild.projects.packages[zipKey].url,
id: lastBuild.buildId,
hash: lastBuild.projects.commit_hash,
version: lastBuild.version
}
log.text = 'Downloading schema.json'
await pipeline(response.body, createWriteStream(schemaJson))

log.succeed('Done')
}

async function main (options) {
delete options._
await downloadArtifacts(options)
async function main () {
await downloadArtifacts()
}

if (require.main === module) {
process.on('unhandledRejection', function (err) {
console.error(err)
process.exit(1)
})

const options = minimist(process.argv.slice(2), {
string: ['id', 'version', 'hash']
})
main(options).catch(t => {
main().catch(t => {
console.log(t)
process.exit(2)
})
}

module.exports = downloadArtifacts
module.exports.locations = {
specFolder,
freeTestFolder,
xPackTestFolder
}
module.exports.locations = { testYamlFolder, zipFile, schemaJson }
2 changes: 1 addition & 1 deletion scripts/generate-docs-examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
const { join } = require('path')
const { writeFile } = require('fs/promises')
const fetch = require('node-fetch')
const rimraf = require('rimraf')
const { rimraf } = require('rimraf')
const ora = require('ora')
const { convertRequests } = require('@elastic/request-converter')
const minimist = require('minimist')
Expand Down
Loading