qiskit/azure-pipelines.yml

250 lines
10 KiB
YAML

# Trigger types. This needs to include all the triggers for the different
# pipelines we might want to run.
#
# Each of these individually triggers the pipeline compilation step, but it's
# the templating expressions in the `stages` list that actually set what runs.
trigger:
branches:
include:
- 'main'
- 'stable/*'
- 'gh-readonly-queue/*'
pr:
autoCancel: true
branches:
include:
- '*'
# A schedule only runs on branches that match include rules from _both_ `main`
# and the branch itself. On `main`, we blanket include all branches that might
# want to be enabled, then particular branches can override it to exclude
# themselves by removing themselves from the trigger list. For example, old
# stable branches can remove `stable/*` from their copy of this file once they
# reach their end-of-life.
schedules:
- cron: "20 6 * * *"
displayName: "Complete matrix test"
branches:
include: [ "main", "stable/*" ]
always: false # Only run if the code changed since the last cron sync.
# Configuration. In theory a manual trigger on the Azure website or embedding
# this pipeline as a template can override these, but we're not interested in
# that. We just want to give names to things to make it easier to read.
parameters:
- name: "supportedPythonVersions"
displayName: "All supported versions of Python"
type: object
default: ["3.9", "3.10", "3.11", "3.12"]
- name: "minimumPythonVersion"
displayName: "Minimum supported version of Python"
type: string
default: "3.9"
- name: "maximumPythonVersion"
displayName: "Maximum supported version of Python"
type: string
default: "3.12"
# These two versions of Python can be chosen somewhat arbitrarily, but we get
# slightly better coverage per PR if they're neither the maximum nor minimum
# supported versions.
- name: "branchPushPythonVersion"
displayName: "Version of Python to run simple tests on pushes to protected branches"
type: string
default: "3.9"
# Sync with 'python-version' in '.github/workflows/docs_deploy.yml'.
- name: "documentationPythonVersion"
displayName: "Version of Python to use to build Sphinx documentation"
type: string
default: "3.9"
# Conditional compilation logic. This is all the logic for "what to run"; each
# stage in turn delegates to various templates in ".azure" that provide the
# information on "how to run" them.
#
# The conditional conditions use the template-expression syntax `${{ }}` so only
# the relevant stages even appear in the job list. The documentation on the
# expression syntax is here:
#
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops
#
# Not all variables are available at template-expansion time - this happens
# before any machine is provisioned, so mostly you can access things from
# GitHub, but nothing about the actual machine. This is the list of variables
# (look in the "available in templates" column):
#
# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
#
# The main differentiator is `variables['Build.Reason']`, which contains the
# trigger type:
# - cron (`Schedule`)
# - push to a git reference like a branch or tag (`IndividualCI`)
# - push to a pull request (`PullRequest`)
# For `IndividualCI` (push/merge to a branch/tag on Qiskit/qiskit-terra), you
# need to examine `variables['Build.SourceBranch']` to determine whether it's a
# branch or a tag, and if a branch, then whether it's in the merge queue or a
# push to a "real" branch.
stages:
# Nightly cron job.
#
# For this to run on a branch, the `schedules` trigger up at the top of this
# file needs to match on _both_ `main` and the branch itself.
- ${{ if eq(variables['Build.Reason'], 'Schedule') }}:
- stage: "Nightly"
displayName: "Nightly complete matrix tests"
jobs:
- ${{ each version in parameters.supportedPythonVersions }}:
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ version }}
testImages: false
testRust: false
installOptionals: true
- template: ".azure/test-macos.yml"
parameters:
pythonVersion: ${{ version }}
installOptionals: true
- template: ".azure/test-windows.yml"
parameters:
pythonVersion: ${{ version }}
installOptionals: true
- stage: "Nightly_Failure"
displayName: "Comment on nightly failure"
dependsOn: "Nightly"
condition: failed()
pool: {vmImage: 'ubuntu-latest'}
jobs:
- job: "Comment"
steps:
- task: GitHubComment@0
inputs:
gitHubConnection: Qiskit
repositoryName: ${{ variables['Build.Repository.Name'] }}
id: 7864
comment: Nightly test job failed at commit $(Build.SourceVersion). View the logs at $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId).
# Full PR suite. PRs need to pass this pipeline in order to be moved to the
# merge queue, where they'll use the next rule as the branch-protection rule
# for the final merge to the base branch.
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
# The preliminary stage should be small in both total runtime (including
# provisioning) and resources required. About half of PR commits result in
# a CI failure, and over 90% of these are in linting, documention or a test
# failure that would affect _any_ OS or Python version. The goal in the
# first stage is to catch the vast majority of failures with minimal cost.
- stage: "Lint_Docs_Prelim_Tests"
displayName: "Preliminary tests"
jobs:
- template: ".azure/lint_docs_qpy-linux.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
# A PR is more likely to fail CI because it introduces a logic error
# into an existing test than because it adds a new test / optional
# dependency that isn't accounted for in the test-skipping logic
# (and such a failure would need fewer iterations to fix). We want
# to fail fast in the first CI stage.
installOptionals: true
testRust: true
testImages: true
# The rest of the PR pipeline is to test the oldest and newest supported
# versions of Python. It's very rare for a failure to be specific to an
# intermediate version of Python, so we just catch those in the cron-job
# pipeline to reduce the amount of resources used.
- stage: "Tests"
displayName: "Main tests"
dependsOn: "Lint_Docs_Prelim_Tests"
jobs:
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
testRust: false
testImages: false
installFromSdist: true
installOptionals: false
- template: ".azure/test-macos.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
installOptionals: true
- template: ".azure/test-macos.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
installOptionals: false
- template: ".azure/test-windows.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
installOptionals: true
- template: ".azure/test-windows.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
installOptionals: false
# Merge queue. A PR that reaches here has already passed the more rigorous PR
# suite, so is very likely to pass. The main reasons for failures here are
# flaky VMs timing out (which we can't do much about), or a merge conflict
# with another PR that is also in the merge queue.
#
# There's no reason to have multiple stages in this case, because we're
# expecting it to pass. Having more than one stage frustrates parallel
# throughput in low-contention cases, and guarantees a longer critical path.
- ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), contains(variables['Build.SourceBranch'], 'gh-readonly-queue')) }}:
- stage: "Merge_Queue"
displayName: "Merge queue"
jobs:
- template: ".azure/lint_docs_qpy-linux.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ parameters.minimumPythonVersion }}
installOptionals: true
testRust: true
testImages: true
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
installOptionals: false
testRust: false
testImages: false
- template: ".azure/test-macos.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
installOptionals: false
- template: ".azure/test-windows.yml"
parameters:
pythonVersion: ${{ parameters.maximumPythonVersion }}
installOptionals: false
# Push to main or the stable branches. The triggering branches also need to
# be in the triggers at the top of this file.
- ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/stable/'))) }}:
- stage: "Push"
jobs:
- template: ".azure/test-linux.yml"
parameters:
pythonVersion: ${{ parameters.branchPushPythonVersion }}
testRust: true
testImages: true
installOptionals: false