[BUG] fix cmaes optimizer tests #489
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: tests | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| pull_request: | |
| branches: | |
| - main | |
| - dev | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CI_IMAGE: ghcr.io/hyperactive-project/hyperactive-ci | |
| jobs: | |
| # =========================================================================== | |
| # STAGE 0: Detect what changed (runs immediately) | |
| # =========================================================================== | |
| detect-changes: | |
| name: detect-changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| core: ${{ steps.filter.outputs.core }} | |
| sklearn: ${{ steps.filter.outputs.sklearn }} | |
| sktime: ${{ steps.filter.outputs.sktime }} | |
| skpro: ${{ steps.filter.outputs.skpro }} | |
| utils: ${{ steps.filter.outputs.utils }} | |
| docs: ${{ steps.filter.outputs.docs }} | |
| examples: ${{ steps.filter.outputs.examples }} | |
| any_src: ${{ steps.filter.outputs.any_src }} | |
| deps_changed: ${{ steps.filter.outputs.deps_changed }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect changed paths | |
| id: filter | |
| run: | | |
| if [ "${{ github.event_name }}" == "push" ]; then | |
| BASE_SHA="${{ github.event.before }}" | |
| # Handle initial push where before is all zeros | |
| if [ "$BASE_SHA" == "0000000000000000000000000000000000000000" ]; then | |
| BASE_SHA="HEAD~1" | |
| fi | |
| else | |
| BASE_SHA="${{ github.event.pull_request.base.sha }}" | |
| fi | |
| CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "${{ github.sha }}" || echo "") | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| # Core: base module, main hyperactive files, or general tests | |
| if echo "$CHANGED_FILES" | grep -qE "^src/hyperactive/(base|tests|__init__|hyperactive)"; then | |
| echo "core=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "core=false" >> $GITHUB_OUTPUT | |
| fi | |
| # sklearn integration | |
| if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/sklearn"; then | |
| echo "sklearn=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "sklearn=false" >> $GITHUB_OUTPUT | |
| fi | |
| # sktime integration | |
| if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/sktime"; then | |
| echo "sktime=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "sktime=false" >> $GITHUB_OUTPUT | |
| fi | |
| # skpro integration | |
| if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/integrations/skpro"; then | |
| echo "skpro=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "skpro=false" >> $GITHUB_OUTPUT | |
| fi | |
| # utils | |
| if echo "$CHANGED_FILES" | grep -q "^src/hyperactive/utils"; then | |
| echo "utils=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "utils=false" >> $GITHUB_OUTPUT | |
| fi | |
| # docs | |
| if echo "$CHANGED_FILES" | grep -qE "^docs/|\.rst$|\.md$"; then | |
| echo "docs=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "docs=false" >> $GITHUB_OUTPUT | |
| fi | |
| # examples | |
| if echo "$CHANGED_FILES" | grep -q "^examples/"; then | |
| echo "examples=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "examples=false" >> $GITHUB_OUTPUT | |
| fi | |
| # any source code | |
| if echo "$CHANGED_FILES" | grep -q "^src/"; then | |
| echo "any_src=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "any_src=false" >> $GITHUB_OUTPUT | |
| fi | |
| # dependencies changed (triggers CI image rebuild) | |
| if echo "$CHANGED_FILES" | grep -qE "^pyproject.toml$|^docs/requirements.txt$|^.github/docker/Dockerfile$"; then | |
| echo "deps_changed=true" >> $GITHUB_OUTPUT | |
| echo "Dependencies changed - CI images will be rebuilt" | |
| else | |
| echo "deps_changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| # =========================================================================== | |
| # STAGE 0.5: Rebuild CI images if dependencies changed | |
| # =========================================================================== | |
| rebuild-ci-images: | |
| name: rebuild-ci-images | |
| needs: [detect-changes] | |
| if: needs.detect-changes.outputs.deps_changed == 'true' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: .github/docker/Dockerfile | |
| push: true | |
| tags: ghcr.io/hyperactive-project/hyperactive-ci:py${{ matrix.python-version }} | |
| build-args: | | |
| PYTHON_VERSION=${{ matrix.python-version }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Gate job: ensures images are ready before tests run | |
| images-ready: | |
| name: images-ready | |
| needs: [detect-changes, rebuild-ci-images] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check image status | |
| run: | | |
| if [[ "${{ needs.detect-changes.outputs.deps_changed }}" == "true" ]]; then | |
| if [[ "${{ needs.rebuild-ci-images.result }}" != "success" ]]; then | |
| echo "CI image rebuild failed" | |
| exit 1 | |
| fi | |
| echo "CI images rebuilt successfully" | |
| else | |
| echo "No dependency changes - using existing CI images" | |
| fi | |
| # =========================================================================== | |
| # STAGE 1: Fast checks (code-quality) | |
| # =========================================================================== | |
| code-quality: | |
| name: code-quality | |
| needs: [images-ready] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get changed files | |
| id: changed-files | |
| run: | | |
| git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
| CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | tr '\n' ' ') | |
| echo "CHANGED_FILES=${CHANGED_FILES}" >> $GITHUB_ENV | |
| - name: Print changed files | |
| run: | | |
| echo "Changed files:" && echo "$CHANGED_FILES" | tr ' ' '\n' | |
| - name: Run pre-commit on changed files | |
| run: | | |
| if [ -n "$CHANGED_FILES" ]; then | |
| pre-commit run --color always --files $CHANGED_FILES --show-diff-on-failure | |
| else | |
| echo "No changed files to check." | |
| fi | |
| test-no-extras: | |
| name: test-no-extras | |
| needs: [targeted-tests-gate] | |
| strategy: | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| os: ["macos-latest", "windows-latest", "ubuntu-latest"] | |
| exclude: | |
| - os: "windows-latest" | |
| python-version: "3.13" | |
| fail-fast: false | |
| runs-on: ${{ matrix.os }} | |
| container: ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/hyperactive-project/hyperactive-ci', matrix.python-version) || '' }} | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| if: matrix.os != 'ubuntu-latest' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies (non-container) | |
| if: matrix.os != 'ubuntu-latest' | |
| run: | | |
| python -m pip install --no-cache-dir --upgrade pip | |
| python -m pip install --no-cache-dir build | |
| make install-no-extras-for-test | |
| - name: Install package (container) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| pip install --no-cache-dir -e .[test] | |
| - name: Show dependencies | |
| run: python -m pip list | |
| - name: Test core package | |
| run: | | |
| python -m pytest src/hyperactive -p no:warnings | |
| test-all-extras: | |
| name: test-all-extras | |
| needs: [targeted-tests-gate] | |
| strategy: | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| os: ["macos-latest", "windows-latest", "ubuntu-latest"] | |
| exclude: | |
| - os: "windows-latest" | |
| python-version: "3.13" | |
| fail-fast: false | |
| runs-on: ${{ matrix.os }} | |
| container: ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/hyperactive-project/hyperactive-ci', matrix.python-version) || '' }} | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| if: matrix.os != 'ubuntu-latest' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies (non-container) | |
| if: matrix.os != 'ubuntu-latest' | |
| run: | | |
| python -m pip install --no-cache-dir --upgrade pip | |
| python -m pip install --no-cache-dir build | |
| make install-all-extras-for-test | |
| - name: Install package (container) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test,sktime-integration] | |
| - name: Show dependencies | |
| run: python -m pip list | |
| - name: Test core package | |
| run: | | |
| python -m pytest src/hyperactive -p no:warnings | |
| test-sklearn-versions: | |
| name: test-sklearn-${{ matrix.sklearn-version }}-python-${{ matrix.python-version }} | |
| needs: [targeted-tests-gate] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py${{ matrix.python-version }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| sklearn-version: ["1.5", "1.6", "1.7"] | |
| python-version: ["3.11", "3.12", "3.13", "3.14"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package and specific sklearn version | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test] | |
| pip install --no-cache-dir scikit-learn==${{ matrix.sklearn-version }}.* | |
| - name: Show dependencies | |
| run: python -m pip list | |
| - name: Run sklearn integration tests for ${{ matrix.sklearn-version }} | |
| run: | | |
| python -m pytest -x -p no:warnings src/hyperactive/integrations/sklearn/ | |
| # =========================================================================== | |
| # STAGE 2: Targeted tests (only for changed areas, fast feedback) | |
| # =========================================================================== | |
| targeted-core: | |
| name: targeted-core | |
| needs: [code-quality, detect-changes] | |
| if: needs.detect-changes.outputs.core == 'true' || needs.detect-changes.outputs.any_src == 'false' | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[test] | |
| - name: Run core tests | |
| run: | | |
| python -m pytest src/hyperactive/base/tests/ src/hyperactive/tests/ -v -p no:warnings | |
| targeted-sklearn: | |
| name: targeted-sklearn | |
| needs: [code-quality, detect-changes] | |
| if: needs.detect-changes.outputs.sklearn == 'true' | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test] | |
| - name: Run sklearn integration tests | |
| run: | | |
| python -m pytest src/hyperactive/integrations/sklearn/tests/ -v -p no:warnings | |
| targeted-sktime: | |
| name: targeted-sktime | |
| needs: [code-quality, detect-changes] | |
| if: needs.detect-changes.outputs.sktime == 'true' | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[sktime-integration,test] | |
| - name: Run sktime integration tests | |
| run: | | |
| python -m pytest src/hyperactive/integrations/sktime/tests/ -v -p no:warnings | |
| targeted-skpro: | |
| name: targeted-skpro | |
| needs: [code-quality, detect-changes] | |
| if: needs.detect-changes.outputs.skpro == 'true' | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[sktime-integration,test] | |
| - name: Run skpro integration tests | |
| run: | | |
| python -m pytest src/hyperactive/integrations/skpro/tests/ -v -p no:warnings | |
| targeted-utils: | |
| name: targeted-utils | |
| needs: [code-quality, detect-changes] | |
| if: needs.detect-changes.outputs.utils == 'true' | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[test] | |
| - name: Run utils tests | |
| run: | | |
| python -m pytest src/hyperactive/utils/tests/ -v -p no:warnings | |
| # Gate job: passes if all targeted tests pass OR are skipped (not failed) | |
| targeted-tests-gate: | |
| name: targeted-tests-gate | |
| needs: [targeted-core, targeted-sklearn, targeted-sktime, targeted-skpro, targeted-utils] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check targeted test results | |
| run: | | |
| echo "Core: ${{ needs.targeted-core.result }}" | |
| echo "Sklearn: ${{ needs.targeted-sklearn.result }}" | |
| echo "Sktime: ${{ needs.targeted-sktime.result }}" | |
| echo "Skpro: ${{ needs.targeted-skpro.result }}" | |
| echo "Utils: ${{ needs.targeted-utils.result }}" | |
| # Fail if any targeted test failed (not skipped) | |
| if [[ "${{ needs.targeted-core.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.targeted-sklearn.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.targeted-sktime.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.targeted-skpro.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.targeted-utils.result }}" == "failure" ]]; then | |
| echo "One or more targeted tests failed" | |
| exit 1 | |
| fi | |
| echo "All targeted tests passed or were skipped" | |
| # =========================================================================== | |
| # STAGE 3: Full test matrix (only after targeted tests pass) | |
| # =========================================================================== | |
| coverage: | |
| name: coverage | |
| needs: [targeted-tests-gate] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test,sktime-integration] | |
| - name: Run tests with coverage | |
| run: | | |
| python -m pytest src/hyperactive/ --cov=src/hyperactive --cov-report=xml --cov-report=term -p no:warnings | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: ./coverage.xml | |
| fail_ci_if_error: false | |
| verbose: true | |
| doctest-examples: | |
| name: doctest-examples | |
| needs: [targeted-tests-gate] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install package with all dependencies | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test,sktime-integration] | |
| - name: Run docstring example tests | |
| run: | | |
| python -m pytest --doctest-modules src/hyperactive/ -v -p no:warnings | |
| test-examples: | |
| name: test-examples | |
| needs: [targeted-tests-gate] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ghcr.io/hyperactive-project/hyperactive-ci:py3.11 | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for example changes | |
| id: check-examples | |
| run: | | |
| git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
| if [ "${{ github.event_name }}" == "push" ]; then | |
| # For pushes, compare with previous commit | |
| CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD | grep "^examples/" || true) | |
| else | |
| # For pull requests, compare with base branch | |
| CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep "^examples/" || true) | |
| fi | |
| if [ -n "$CHANGED_FILES" ]; then | |
| echo "examples_changed=true" >> $GITHUB_OUTPUT | |
| echo "Examples changed:" | |
| echo "$CHANGED_FILES" | |
| else | |
| echo "examples_changed=false" >> $GITHUB_OUTPUT | |
| echo "No example files changed" | |
| fi | |
| - name: Install package | |
| if: steps.check-examples.outputs.examples_changed == 'true' | |
| run: | | |
| pip install --no-cache-dir -e .[all_extras,test,sktime-integration] | |
| - name: Show dependencies | |
| if: steps.check-examples.outputs.examples_changed == 'true' | |
| run: python -m pip list | |
| - name: Test examples | |
| if: steps.check-examples.outputs.examples_changed == 'true' | |
| run: | | |
| python -m pytest examples/ -v -p no:warnings |