diff --git a/.buildkite/pipelines/format_and_validation.yml.sh b/.buildkite/pipelines/format_and_validation.yml.sh index 66e895842..c6484d9cb 100755 --- a/.buildkite/pipelines/format_and_validation.yml.sh +++ b/.buildkite/pipelines/format_and_validation.yml.sh @@ -18,6 +18,15 @@ steps: notify: - github_commit_status: context: "Validate formatting with clang-format" + - label: "dev-tools pytest" + key: "dev_tools_pytest" + command: ".buildkite/scripts/steps/dev_tools_pytest.sh" + agents: + # bookworm (not slim): stable Python minor + curl/git for Buildkite hooks; avoids python:3 tag drift + image: "python:3.11-bookworm" + notify: + - github_commit_status: + context: "dev-tools pytest" - label: "Validate changelog entries" key: "validate_changelogs" command: ".buildkite/scripts/steps/validate-changelogs.sh" diff --git a/.buildkite/scripts/steps/dev_tools_pytest.sh b/.buildkite/scripts/steps/dev_tools_pytest.sh new file mode 100755 index 000000000..e1bbd07b0 --- /dev/null +++ b/.buildkite/scripts/steps/dev_tools_pytest.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License +# 2.0 and the following additional limitation. Functionality enabled by the +# files subject to the Elastic License 2.0 may only be used in production when +# invoked by an Elasticsearch process with a license key installed that permits +# use of machine learning features. You may not use this file except in +# compliance with the Elastic License 2.0 and the foregoing additional +# limitation. +# +# Installs dev-tools pytest deps once per job (PyPI), then runs run_dev_tools_tests.sh. +# Keeping pip here isolates network/bootstrap from the test runner; baking deps into +# the agent image would avoid live PyPI on every PR if desired. + +set -euo pipefail + +REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel)}" +cd "${REPO_ROOT}" + +if ! python3 -m pip install -q -r "${REPO_ROOT}/dev-tools/test-requirements.txt"; then + echo "ERROR: pip install failed for dev-tools/test-requirements.txt (network or PyPI?)." >&2 + echo "Install manually on this agent, then re-run:" >&2 + echo " python3 -m pip install -r ${REPO_ROOT}/dev-tools/test-requirements.txt" >&2 + exit 1 +fi + +exec "${REPO_ROOT}/dev-tools/run_dev_tools_tests.sh" -q --tb=short diff --git a/.buildkite/scripts/steps/test-changelog-tools.sh b/.buildkite/scripts/steps/test-changelog-tools.sh index 853b2775e..9953208cf 100755 --- a/.buildkite/scripts/steps/test-changelog-tools.sh +++ b/.buildkite/scripts/steps/test-changelog-tools.sh @@ -18,4 +18,6 @@ python3 -m pip install --quiet --break-system-packages pyyaml jsonschema 2>/dev/ || python3 -m pip install --quiet pyyaml jsonschema echo "Running Python unit tests for dev-tools changelog scripts..." -python3 -m unittest discover -s dev-tools/unittest -p 'test_*.py' -v +# Only test_changelog_tools.py: other modules under unittest/ may be pytest-only +# (e.g. test_version_bump_validation) and are run by the dev-tools pytest step. +python3 -m unittest discover -s dev-tools/unittest -p 'test_changelog_tools.py' -v diff --git a/dev-tools/pytest.ini b/dev-tools/pytest.ini new file mode 100644 index 000000000..254dbbf2b --- /dev/null +++ b/dev-tools/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +testpaths = unittest +pythonpath = . + +markers = + integration: requires git fetch from origin; opt-in via VERSION_BUMP_GIT_INTEGRATION=1 (see test file) diff --git a/dev-tools/run_dev_tools_tests.sh b/dev-tools/run_dev_tools_tests.sh new file mode 100755 index 000000000..09ac95594 --- /dev/null +++ b/dev-tools/run_dev_tools_tests.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License +# 2.0 and the following additional limitation. Functionality enabled by the +# files subject to the Elastic License 2.0 may only be used in production when +# invoked by an Elasticsearch process with a license key installed that permits +# use of machine learning features. You may not use this file except in +# compliance with the Elastic License 2.0 and the foregoing additional +# limitation. +# +# Runs dev-tools/unittest via pytest (see dev-tools/test-requirements.txt). +# Does not install packages — pytest must already be importable (venv, image, or +# a prior pip install). PR CI runs .buildkite/scripts/steps/dev_tools_pytest.sh, +# which performs one pip install per job from dev-tools/test-requirements.txt +# (PyPI); a future improvement is baking deps into the CI image to reduce that +# dependency. +# +# Usage (from repository root): +# ./dev-tools/run_dev_tools_tests.sh +# ./dev-tools/run_dev_tools_tests.sh -q --tb=short + +set -euo pipefail + +ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || true +if [[ -z "${ROOT}" ]]; then + echo "ERROR: not inside a git repository (git rev-parse --show-toplevel failed)." >&2 + echo "Run this script from a checkout of ml-cpp." >&2 + exit 1 +fi +cd "${ROOT}/dev-tools" + +if ! python3 -m pytest --version >/dev/null 2>&1; then + echo "pytest is not installed in the current environment." >&2 + echo "Install dev-tools test dependencies first, for example:" >&2 + echo " python3 -m pip install -r ${ROOT}/dev-tools/test-requirements.txt" >&2 + echo "On Buildkite, .buildkite/scripts/steps/dev_tools_pytest.sh installs this before invoking this script." >&2 + exit 1 +fi + +exec python3 -m pytest -c pytest.ini "$@" diff --git a/dev-tools/test-requirements.txt b/dev-tools/test-requirements.txt new file mode 100644 index 000000000..188fc9094 --- /dev/null +++ b/dev-tools/test-requirements.txt @@ -0,0 +1,5 @@ +# Python dependencies for dev-tools/unittest (pytest). +pytest>=7.0.0,<9 +# Import-time deps for changelog scripts exercised by tests (bundle_changelogs, etc.). +PyYAML>=6.0 +jsonschema>=4.0.0