Build Python apps

Azure Pipelines

This article describes how to customize the Azure Pipelines azure-pipelines.yml file to build, test, and deploy Python apps or scripts.

If you're new to pipelines, or want an end-to-end walkthrough, see Use CI/CD to deploy a Python web app to Azure App Service on Linux.

To create and activate an Anaconda environment and install Anaconda packages with conda, see Run pipelines with Anaconda environments.

Build environment

You don't have to set up anything for Azure Pipelines to build Python projects. Python is preinstalled on Microsoft-hosted build agents for Linux, macOS, or Windows. To see which Python versions are preinstalled, see Use a Microsoft-hosted agent.

Use a specific Python version

To use a specific version of Python in your pipeline, add the Use Python Version task to azure-pipelines.yml. This snippet sets the pipeline to use Python 3.6:

steps:
- task: UsePythonVersion@0
  inputs:
    versionSpec: '3.6'

Use multiple Python versions

To run a pipeline with multiple Python versions, for example to test a package against those versions, define a job with a matrix of Python versions. Then set the UsePythonVersion task to reference the matrix variable.

jobs:
- job: 'Test'
  pool:
    vmImage: 'ubuntu-16.04' # other options: 'macOS-10.13', 'vs2017-win2016'
  strategy:
    matrix:
      Python27:
        python.version: '2.7'
      Python35:
        python.version: '3.5'
      Python36:
        python.version: '3.6'

  steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '$(python.version)'

You can add tasks to run using each Python version in the matrix.

Run Python scripts

To run Python scripts in your repository, use a script element and specify a filename. For example:

- script: python src/example.py

You can also run inline Python scripts with the Python Script task:

- task: PythonScript@0
  inputs:
    scriptSource: 'inline'
    script: |
      print('Hello world 1')
      print('Hello world 2')

To parameterize script execution, use the PythonScript task with arguments values to pass arguments into the executing process. You can use sys.argv or the more sophisticated argparse library to parse the arguments.

- task: PythonScript@0
  inputs:
    scriptSource: inline
    script: |
      import sys
      print ('Executing script file is:', str(sys.argv[0]))
      print ('The arguments are:', str(sys.argv))
      import argparse
      parser = argparse.ArgumentParser()
      parser.add_argument("--world", help="Provide the name of the world to greet.")
      args = parser.parse_args()
      print ('Hello ', args.world)
    arguments: --world Venus

Install dependencies

You can use scripts to install specific PyPI packages with pip. For example, this YAML installs or upgrades pip and the setuptools and wheel packages.

- script: python -m pip install --upgrade pip setuptools wheel
  displayName: 'Install tools'

Install requirements

After you update pip and friends, a typical next step is to install dependencies from requirements.txt:

- script: pip install -r requirements.txt
  displayName: 'Install requirements'

Run tests

You can use scripts to install and run various tests in your pipeline.

Run lint tests with flake8

To install or upgrade flake8 and use it to run lint tests, use this YAML:

- script: |
    python -m pip install flake8
    flake8 .
  displayName: 'Run lint tests'

Test with pytest and collect coverage metrics with pytest-cov

Use this YAML to install pytest and pytest-cov, run tests, output test results in JUnit format, and output code coverage results in Cobertura XML format:

- script: |
    pip install pytest
    pip install pytest-cov
    pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html
  displayName: 'Test with pytest'

Run tests with Tox

Azure Pipelines can run parallel Tox test jobs to split up the work. On a development computer, you have to run your test environments in series. This sample uses tox -e py to run whichever version of Python is active for the current job.

- job:

  pool:
    vmImage: 'ubuntu-16.04'
  strategy:
    matrix:
      Python27:
        python.version: '2.7'
      Python35:
        python.version: '3.5'
      Python36:
        python.version: '3.6'
      Python37:
        python.version: '3.7'

  steps:
  - task: UsePythonVersion@0
    displayName: 'Use Python $(python.version)'
    inputs:
      versionSpec: '$(python.version)'

  - script: pip install tox
    displayName: 'Install Tox'

  - script: tox -e py
    displayName: 'Run Tox'

Publish test results

Add the Publish Test Results task to publish JUnit or xUnit test results to the server:

- task: PublishTestResults@2
  condition: succeededOrFailed()
  inputs:
    testResultsFiles: '**/test-*.xml'
    testRunTitle: 'Publish test results for Python $(python.version)'

Publish code coverage results

Add the Publish Code Coverage Results task to publish code coverage results to the server. You can see coverage metrics in the build summary, and download HTML reports for further analysis.

- task: PublishCodeCoverageResults@1
  inputs:
    codeCoverageTool: Cobertura
    summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
    reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'

Package and deliver code

To authenticate with twine, use the Twine Authenticate task to store authentication credentials in the PYPIRC_PATH environment variable.

- task: TwineAuthenticate@0
  inputs:
    artifactFeed: '<Azure Artifacts feed name>'
    pythonUploadServiceConnection: '<twine service connection from external organization>'

Then, add a custom script that uses twine to publish your packages.

- script: |
   twine upload -r "<feed or service connection name>" --config-file $(PYPIRC_PATH) <package path/files>

You can also use Azure Pipelines to build an image for your Python app and push it to a container registry.