# 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.8", "3.9", "3.10", "3.11", "3.12"] - name: "minimumPythonVersion" displayName: "Minimum supported version of Python" type: string default: "3.8" - 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