From 175da9ba757682bd07803e4bc1325a758c2aef90 Mon Sep 17 00:00:00 2001 From: Guillem Serra Cazorla Date: Mon, 18 May 2026 14:33:15 +0100 Subject: [PATCH] ci: fan out Azure pipelines on Python version (parallel matrix) Previously, each (os, test_suite) pair ran as a single Azure Pipelines job and iterated over python_versions as a template loop inside that job's steps: strategy: matrix: : {...} steps: - ${{ each pyver in parameters.python_versions }}: - install python pyver - configure - run test_suite Consequence: all Python versions for a given (os, test_suite) ran sequentially on the same agent. If the first Python version failed (e.g. an env-specific test failure on the *_latest_from_pip matrix), all subsequent Python versions were skipped instead of also running and showing whether they were affected. Move python_version into the strategy.matrix so each (python_version, test_suite) combination runs as its own parallel job on its own agent VM. Each job becomes shorter (one Python install + configure + test run instead of N of each) and an issue affecting one Python version no longer hides results for the others. Matrix keys are of the form 'py3_10_all' / 'py3_11_misc_and_scancode' etc. (matrix keys must be alphanumeric+underscore, so dots in version strings are replaced). No changes to the per-job test command or to the caller pipelines in azure-pipelines.yml -- the python_versions and test_suites parameters keep the same shape. Signed-off-by: Guillem Serra Cazorla --- etc/ci/azure-posix.yml | 40 +++++++++++++++++++++++----------------- etc/ci/azure-win.yml | 40 +++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/etc/ci/azure-posix.yml b/etc/ci/azure-posix.yml index 9fdc7f1522e..18f3d9fdfb7 100644 --- a/etc/ci/azure-posix.yml +++ b/etc/ci/azure-posix.yml @@ -11,29 +11,35 @@ jobs: pool: vmImage: ${{ parameters.image_name }} + # Fan out on both Python version AND test suite so each + # (python_version, test_suite) combination runs as its own parallel + # job on its own agent VM. Previously python_versions were iterated + # as sequential steps inside a single job, so a failure on the first + # Python version skipped all subsequent ones. strategy: matrix: - ${{ each tsuite in parameters.test_suites }}: - ${{ tsuite.key }}: - test_suite_label: ${{ tsuite.key }} - test_suite: ${{ tsuite.value }} + ${{ each pyver in parameters.python_versions }}: + ${{ each tsuite in parameters.test_suites }}: + py${{ replace(pyver, '.', '_') }}_${{ tsuite.key }}: + python_version: ${{ pyver }} + test_suite_label: ${{ tsuite.key }} + test_suite: ${{ tsuite.value }} steps: - checkout: self fetchDepth: 10 - - ${{ each pyver in parameters.python_versions }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: '${{ pyver }}' - architecture: '${{ parameters.python_architecture }}' - displayName: '${{ pyver }} - Install Python' + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python_version)' + architecture: '${{ parameters.python_architecture }}' + displayName: 'Install Python $(python_version)' - - script: | - python${{ pyver }} --version - echo "python${{ pyver }}" > PYTHON_EXECUTABLE - ./configure --clean && ./configure --dev - displayName: '${{ pyver }} - Configure' + - script: | + python$(python_version) --version + echo "python$(python_version)" > PYTHON_EXECUTABLE + ./configure --clean && ./configure --dev + displayName: 'Configure with Python $(python_version)' - - script: $(test_suite) - displayName: '${{ pyver }} - $(test_suite_label) on ${{ parameters.job_name }}' + - script: $(test_suite) + displayName: '$(test_suite_label) on ${{ parameters.job_name }} with Python $(python_version)' diff --git a/etc/ci/azure-win.yml b/etc/ci/azure-win.yml index 26b41116ef2..0057f90ed2d 100644 --- a/etc/ci/azure-win.yml +++ b/etc/ci/azure-win.yml @@ -11,29 +11,35 @@ jobs: pool: vmImage: ${{ parameters.image_name }} + # Fan out on both Python version AND test suite so each + # (python_version, test_suite) combination runs as its own parallel + # job on its own agent VM. Previously python_versions were iterated + # as sequential steps inside a single job, so a failure on the first + # Python version skipped all subsequent ones. strategy: matrix: - ${{ each tsuite in parameters.test_suites }}: - ${{ tsuite.key }}: - test_suite_label: ${{ tsuite.key }} - test_suite: ${{ tsuite.value }} + ${{ each pyver in parameters.python_versions }}: + ${{ each tsuite in parameters.test_suites }}: + py${{ replace(pyver, '.', '_') }}_${{ tsuite.key }}: + python_version: ${{ pyver }} + test_suite_label: ${{ tsuite.key }} + test_suite: ${{ tsuite.value }} steps: - checkout: self fetchDepth: 10 - - ${{ each pyver in parameters.python_versions }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: '${{ pyver }}' - architecture: '${{ parameters.python_architecture }}' - displayName: '${{ pyver }} - Install Python' + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python_version)' + architecture: '${{ parameters.python_architecture }}' + displayName: 'Install Python $(python_version)' - - script: | - python --version - echo | set /p=python> PYTHON_EXECUTABLE - configure --clean && configure --dev - displayName: '${{ pyver }} - Configure' + - script: | + python --version + echo | set /p=python> PYTHON_EXECUTABLE + configure --clean && configure --dev + displayName: 'Configure with Python $(python_version)' - - script: $(test_suite) - displayName: '${{ pyver }} - $(test_suite_label) on ${{ parameters.job_name }}' + - script: $(test_suite) + displayName: '$(test_suite_label) on ${{ parameters.job_name }} with Python $(python_version)'