Azure DevOps

tutorial

Stage templates

In addition to the mender-ci-tools Docker image, Mender provides stage templates for uploading Mender Artifacts and creating deployments to a group of devices.

The templates use the Personal Access Tokens feature which is only available in Mender Server version 3.4 or newer.

In this chapter we introduce the different stages and provide examples on how to use them.

Upload a Mender Artifact

Upload Mender Artifact stage template uploads a Mender Artifact to a Mender Server.

The template has the following parameters:

  • mender_uri: Mender Server's URL (default: https://hosted.mender.io)
  • mender_pat: Mender Personal Access Token (read the documentation for more information)
  • mender_artifact: Path of Mender Artifact file, relative to $(System.DefaultWorkingDirectory)

Create a deployment job

Create deployment on Mender Server stage template creates a deployment on a Mender Server.

The template has the following parameters:

  • mender_uri: Mender Server's URL (default: https://hosted.mender.io).
  • mender_pat: Mender Personal Access Token (read the documentation for more information).
  • mender_deployment_name: Mender deployment's name.
  • mender_release_name: Mender release's name.
  • mender_devices_list: The list of Mender devices a deployment will be triggered to.
  • mender_deployment_group: The name of the Mender devices group your deployment will target. One of mender_deployment_group or mender_devices_list is required. mender_devices_list takes the priority if both are set.

Pipelines examples

Build and deploy a Mender Artifact

#
# The example shows how to build, upload and deploy a Mender Artifact.
#
# 'MENDER_SERVER_ACCESS_TOKEN' secret is required to be set in the Azure DevOps pipeline settings
#

# specific branch build
trigger:
  branches:
    include:
    - main

variables:
- name: MENDER_SERVER_URL # Mender server's URL
  value: https://hosted.mender.io
- name: MENDER_ARTIFACT_NAME # Mender Artifact's file name
  value: artifact.mender
- name: MENDER_RELEASE_NAME # Mender release's name for the Artifact
  value: release-1.0
- name: MENDER_DEPLOYMENT_NAME # Mender deployment's name
  value: deployment-release-1.0
- name: MENDER_DEVICES_GROUP_NAME # The name of Mender devices group a deployment with Mender Artifact will be triggered to
  value: group-dev

resources:
  # Use other repositories for templates
  # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates
  repositories:
    - repository: templates
      type: github
      name: mendersoftware/mender-ci-workflows
      ref: refs/heads/master
      # GitHub service connection
      # https://learn.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints
      endpoint: github_service_connection

#
# Builds Mender Artifacts using 'mender-artifact' tool
#
jobs:
- job: build_mender_artifact
  pool:
    vmImage: ubuntu-latest
  # container with pre-installed mender-artifact and mender-cli tools
  container: mendersoftware/mender-ci-tools:1.0.0
  steps:
  # Creates Mender Artifact
  # In this example, hello-mender.py represents a single file Python application that we have
  # built and test in our CI and now we want to deploy into a device running Mender. We will
  # package it as a Single File Application Update. For more information visit the Mender docs:
  # https://docs.mender.io/artifact-creation/create-an-artifact
  - script: |
      curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
      chmod 755 hello-mender.py
      single-file-artifact-gen \
        --device-type raspberrypi4 \
        -o ${MENDER_ARTIFACT_NAME} \
        -n ${MENDER_RELEASE_NAME} \
        --software-name hello-mender \
        --software-version 1.0 \
        --dest-dir /usr/local/bin \
        hello-mender.py
    displayName: Build Mender Artifact
  # Uploads Azure DevOps artifacts to Azure artifact storage to pass them to the further jobs
  - task: PublishPipelineArtifact@1
    inputs:
      targetPath: $(MENDER_ARTIFACT_NAME)
      artifactName: mender_artifact
    displayName: Publish the Azure DevOps artifact

#
# Uploads built Mender Artifacts to Mender server
#
- job: upload_mender_artifact
  dependsOn:
  - build_mender_artifact
  pool:
    vmImage: ubuntu-latest
  steps:
  # Downloads built in previous job Azure DevOps artifacts
  - task: DownloadPipelineArtifact@2
    inputs:
      artifact: mender_artifact
      patterns: $(MENDER_ARTIFACT_NAME)
      path: $(System.DefaultWorkingDirectory)
  # Uploads Mender Artifact to a Mender server
  - template: templates/azure/mender-artifact-upload.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_artifact: $(MENDER_ARTIFACT_NAME)

#
# Creates deployments on Mender server
#
- job: create_deployment
  dependsOn:
  - upload_mender_artifact
  pool:
    vmImage: ubuntu-latest
  steps:
  # Creates a deployment on a Mender server, using previously generated Mender deployment name
  - template: templates/azure/mender-deployment-create.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_deployment_name: $(MENDER_DEPLOYMENT_NAME)
      mender_release_name: $(MENDER_RELEASE_NAME)
      mender_deployment_group: $(MENDER_DEVICES_GROUP_NAME)

Build and deploy multiple Mender Artifacts

#
# The example shows how to build, upload and deploy Mender Artifacts for two different devices.
#
# 'MENDER_SERVER_ACCESS_TOKEN' secret is required to be set in Azure DevOps pipeline settings.
#

# specific branch build
trigger:
  branches:
    include:
    - main

variables:
- name: MENDER_SERVER_URL # Mender server's URL
  value: https://hosted.mender.io
- name: MENDER_ARTIFACT_NAME_ONE # First Mender Artifact's file name
  value: artifact_one.mender
- name: MENDER_ARTIFACT_NAME_TWO # Second Mender Artifact's file name
  value: artifact_two.mender
- name: MENDER_RELEASE_NAME_ONE # Mender release's name for the for the Mender Artifact name `MENDER_ARTIFACT_NAME_ONE`
  value: release-1.0-gateway
- name: MENDER_RELEASE_NAME_TWO # Mender release's name for the for the Mender Artifact name `MENDER_ARTIFACT_NAME_TWO`
  value: release-1.0-sensor
- name: MENDER_DEVICES_GROUP_NAME_ONE # The name of Mender devices group a deployment with Mender Artifact name `MENDER_ARTIFACT_NAME_ONE` will be triggered to
  value: group-gateway
- name: MENDER_DEVICES_GROUP_NAME_TWO # The name of Mender devices group a deployment with Mender Artifact name `MENDER_ARTIFACT_NAME_TWO` will be triggered to
  value: group-sensor

resources:
  # Use other repositories for templates
  # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates
  repositories:
    - repository: templates
      type: github
      name: mendersoftware/mender-ci-workflows
      ref: refs/heads/master
      # GitHub service connection
      # https://learn.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints
      endpoint: github_service_connection

jobs:
#
# Build Mender Artifacts using 'mender-artifact' tool
#
- job: build_mender_artifact_one
  pool:
    vmImage: ubuntu-latest
  # container with pre-installed mender-artifact and mender-cli tools
  container: mendersoftware/mender-ci-tools:1.0.0
  steps:
  # Creates Mender Artifact
  # In this example, hello-mender.py represents a single file Python application that we have
  # built and test in our CI and now we want to deploy into a device running Mender. We will
  # package it as a Single File Application Update. For more information visit the Mender docs:
  # https://docs.mender.io/artifact-creation/create-an-artifact
  - script: |
      curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
      chmod 755 hello-mender.py
      single-file-artifact-gen \
        --device-type raspberrypi4 \
        -o ${MENDER_ARTIFACT_NAME_ONE} \
        -n ${MENDER_RELEASE_NAME_ONE} \
        --software-name hello-mender \
        --software-version 1.0 \
        --dest-dir /usr/local/bin \
        hello-mender.py
    displayName: Build Mender Artifact
  # Uploads Azure DevOps artifacts to Azure artifact storage to pass them to the further jobs
  - task: PublishPipelineArtifact@1
    inputs:
      targetPath: $(MENDER_ARTIFACT_NAME_ONE)
      artifactName: mender_artifact_one
    displayName: Publish the Azure DevOps artifact

- job: build_mender_artifact_two
  pool:
    vmImage: ubuntu-latest
  # conrainer with pre-installed mender-artifact and mender-cli tools
  container: mendersoftware/mender-ci-tools:1.0.0
  steps:
  # Creates Mender Artifact
  # In this example, hello-mender.py represents a single file Python application that we have
  # built and test in our CI and now we want to deploy into a device running Mender. We will
  # package it as a Single File Application Update. For more information visit the Mender docs:
  # https://docs.mender.io/artifact-creation/create-an-artifact
  - script: |
      curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
      chmod 755 hello-mender.py
      single-file-artifact-gen \
        --device-type raspberrypi4 \
        -o ${MENDER_ARTIFACT_NAME_TWO} \
        -n ${MENDER_RELEASE_NAME_TWO} \
        --software-name hello-mender \
        --software-version 1.0 \
        --dest-dir /usr/local/bin \
        hello-mender.py
    displayName: Build Mender Artifact
  # Uploads Azure DevOps artifacts to Azure artifact storage to pass them to the further jobs
  - task: PublishPipelineArtifact@1
    inputs:
      targetPath: $(MENDER_ARTIFACT_NAME_TWO)
      artifactName: mender_artifact_two
    displayName: Publish the Azure DevOps artifact

#
# Upload built Mender Artifacts to the Mender server
#
- job: upload_mender_artifact_one
  dependsOn:
  - build_mender_artifact_one
  pool:
    vmImage: ubuntu-latest
  steps:
  # Downloads built in previous job Azure DevOps artifacts
  - task: DownloadPipelineArtifact@2
    inputs:
      artifact: mender_artifact_one
      patterns: $(MENDER_ARTIFACT_NAME_ONE)
      path: $(System.DefaultWorkingDirectory)
  # Uploads Mender Artifact to a Mender server
  - template: templates/azure/mender-artifact-upload.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_artifact: $(MENDER_ARTIFACT_NAME_ONE)

- job: upload_mender_artifact_two
  dependsOn:
  - build_mender_artifact_two
  pool:
    vmImage: ubuntu-latest
  steps:
  # Downloads built in previous job Azure DevOps artifacts
  - task: DownloadPipelineArtifact@2
    inputs:
      artifact: mender_artifact_two
      patterns: $(MENDER_ARTIFACT_NAME_TWO)
      path: $(System.DefaultWorkingDirectory)
  # Uploads Mender Artifact to a Mender server
  - template: templates/azure/mender-artifact-upload.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_artifact: $(MENDER_ARTIFACT_NAME_TWO)

#
# Create deployments on the Mender server
#
- job: create_deployment_one
  dependsOn:
  - upload_mender_artifact_one
  pool:
    vmImage: ubuntu-latest
  steps:
  # Sets Mender deployment name
  - script: |
      # set 'deployment_one' value of 'MENDER_DEPLOYMENT_NAME' variable to be available across the job
      # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables
      echo "##vso[task.setvariable variable=MENDER_DEPLOYMENT_NAME;isOutput=true;]deployment_one"
    name: set_variable
  # Creates a deployment on a Mender server, using previously generated Mender deployment name
  - template: templates/azure/mender-deployment-create.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_deployment_name: $(set_variable.MENDER_DEPLOYMENT_NAME)
      mender_release_name: $(MENDER_RELEASE_NAME_ONE)
      mender_deployment_group: $(MENDER_DEVICES_GROUP_NAME_ONE)

- job: create_deployment_two
  dependsOn:
  - upload_mender_artifact_two
  pool:
    vmImage: ubuntu-latest
  steps:
  # Sets Mender deployment name
  - script: |
      # set 'deployment_one' value of 'MENDER_DEPLOYMENT_NAME' variable to be available across the job
      # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables
      echo "##vso[task.setvariable variable=MENDER_DEPLOYMENT_NAME;isOutput=true;]deployment_two"
    name: set_variable
  # Creates a deployment on a Mender server, using previously generated Mender deployment name
  - template: templates/azure/mender-deployment-create.yml@templates
    parameters:
      mender_uri: $(MENDER_SERVER_URL)
      mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
      mender_deployment_name: $(set_variable.MENDER_DEPLOYMENT_NAME)
      mender_release_name: $(MENDER_RELEASE_NAME_TWO)
      mender_deployment_group: $(MENDER_DEVICES_GROUP_NAME_TWO)

Build and deploy a Mender Artifact to a single device

#
# The example shows how to deploy a Mender artifact to a single device.
#
# 'MENDER_SERVER_ACCESS_TOKEN' secret is required to be set in Azure DevOps pipeline settings
#

# specific branch build
trigger:
  branches:
    include:
    - main

variables:
- name: MENDER_SERVER_URL # Mender server's URL
  value: https://hosted.mender.io
- name: MENDER_ARTIFACT_NAME # Mender Artifact's file name
  value: artifact.mender
- name: MENDER_RELEASE_NAME # Mender release's name for the Artifact
  value: release-1.0
- name: MENDER_DEPLOYMENT_NAME # Mender deployment's name
  value: deployment-release-1.0
- name: MENDER_DEVICES_LIST # List of devices to deploy built artifact to
  value: '[\"6702a302-9122-44ae-971a-625aa3c4055b\"]'

resources:
  # Use other repositories for templates
  # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates
  repositories:
    - repository: templates
      type: github
      name: mendersoftware/mender-ci-workflows
      ref: refs/heads/master
      # GitHub service connection
      # https://learn.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints
      endpoint: github_service_connection

pool:
  vmImage: ubuntu-latest

# conrainer with pre-installed mender-artifact and mender-cli tools
container: mendersoftware/mender-ci-tools:1.0.0

steps:
# Creates Mender Artifact
# In this example, hello-mender.py represents a single file Python application that we have
# built and test in our CI and now we want to deploy into a device running Mender. We will
# package it as a Single File Application Update. For more information visit the Mender docs:
# https://docs.mender.io/artifact-creation/create-an-artifact
- script: |
    curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
    chmod 755 hello-mender.py
    single-file-artifact-gen \
      --device-type raspberrypi4 \
      -o ${MENDER_ARTIFACT_NAME} \
      -n ${MENDER_RELEASE_NAME} \
      --software-name hello-mender \
      --software-version 1.0 \
      --dest-dir /usr/local/bin \
      hello-mender.py
  displayName: Build Mender Artifact

# Uploads Mender Artifact to a Mender server
- template: templates/azure/mender-artifact-upload.yml@templates
  parameters:
    mender_uri: $(MENDER_SERVER_URL)
    mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
    mender_artifact: $(MENDER_ARTIFACT_NAME)

# Creates a deployment on a Mender server
- template: templates/azure/mender-deployment-create.yml@templates
  parameters:
    mender_uri: $(MENDER_SERVER_URL)
    mender_pat: $(MENDER_SERVER_ACCESS_TOKEN)
    mender_deployment_name: $(MENDER_DEPLOYMENT_NAME)
    mender_release_name: $(MENDER_RELEASE_NAME)
    mender_devices_list: $(MENDER_DEVICES_LIST)

We welcome contributions to improve this documentation. To submit a change, use the Edit link at the top of the page or email us at .