GitHub Actions

tutorial

Custom actions

Mender provides actions for uploading Mender Artifacts and creating deployments to a group of devices. Both actions are composite and require bash and curl to be available in a used container.

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

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

Upload a Mender Artifact action

mendersoftware/mender-gh-action-upload-artifact action uploads a Mender Artifact to a Mender Server. Find more information about the action usage in the related documentation.

Create a deployment action

mendersoftware/mender-gh-action-create-deployment action creates a deployment on a Mender Server. Find more information about the action usage in the related documentation.

Setup

The actions require the following secret to be set in a repository settings:

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 GitHub repo settings.
#

name: Build Mender Artifact and trigger a deployment

on:
  pull_request:
    branches:
      - main
      - production
    types:
      - closed

env:
  MENDER_SERVER_URL: https://hosted.mender.io         # Mender server URL
  MENDER_DEPLOYMENT_DEVICES_GROUP_DEV: group-dev      # Mender development deployment name
  MENDER_DEPLOYMENT_DEVICES_GROUP_PROD: group-prod    # Mender production deployment name
  MENDER_ARTIFACTS_CI_ARTIFACT_NAME: mender-artifacts # GitHub Actions artifact name
  MENDER_ARTIFACTS_CI_ARTIFACT_PATH: mender-artifacts # GitHub Actions artifact path

jobs:
  #
  # Build Mender artifact
  #
  build:
    runs-on: ubuntu-latest
    # conrainer with pre-installed mender-artifact and mender-cli tools
    container:
      image: mendersoftware/mender-ci-tools:1.0.0
    outputs:
      mender_release_name: ${{ steps.release_name.outputs.mender_release_name }}
      mender_devices_group: ${{ steps.deployment_group.outputs.mender_devices_group }}
      mender_deployment_name: ${{ steps.deployment_name.outputs.mender_deployment_name }}
      mender_artifact_name: ${{ steps.create_artifact.outputs.mender_artifact_name }}
    steps:
      # Checkout git repository
      - uses: actions/checkout@v2
      # Initialise the workspace
      - name: Init workspace
        run: |
          mkdir -p ${MENDER_ARTIFACTS_CI_ARTIFACT_PATH}
      # Generates the required variables to later create the Mender Artifact, using a dummy application
      # name "change-the-world-to-better" with a random version.
      - name: Generate Mender release name
        id: release_name
        run: |
          APP_NAME=change-the-world-to-better
          VERSION="$(($RANDOM%9+1)).$(($RANDOM%9+1)).$(($RANDOM%9+1))"
          MENDER_RELEASE_NAME=${APP_NAME}_v${VERSION}
          echo "MENDER_RELEASE_NAME=${MENDER_RELEASE_NAME}" >> ${GITHUB_ENV}
          echo "mender_release_name=${MENDER_RELEASE_NAME}" >> ${GITHUB_OUTPUT}
      # Selects one of MENDER_DEPLOYMENT_DEVICES_GROUP_DEV or MENDER_DEPLOYMENT_DEVICES_GROUP_PROD
      # Mender deployment group name based on the branch name to later create the Mender deployment
      - name: Choose Mender deployment group
        id: deployment_group
        run: |
          if [[ "${GITHUB_BASE_REF}" == "production" ]]; then
            MENDER_DEPLOYMENT_DEVICES_GROUP=${MENDER_DEPLOYMENT_DEVICES_GROUP_PROD}
          elif [[ "${GITHUB_BASE_REF}" == "main" ]]; then
            MENDER_DEPLOYMENT_DEVICES_GROUP=${MENDER_DEPLOYMENT_DEVICES_GROUP_DEV}
          else
            echo "ERROR: workflow execution on not supported branch"
            exit 1
          fi
          echo "mender_devices_group=${MENDER_DEPLOYMENT_DEVICES_GROUP}" >> ${GITHUB_OUTPUT}
      # Generates Mender deployment name to later create the Mender deployment
      - name: Generate Mender deployment name
        id: deployment_name
        run: |
          COMMIT_SHORT_SHA="${GITHUB_SHA:0:8}"
          MENDER_DEPLOYMENT_NAME=${MENDER_RELEASE_NAME}_${COMMIT_SHORT_SHA}
          echo "mender_deployment_name=${MENDER_DEPLOYMENT_NAME}" >> ${GITHUB_OUTPUT}
      # Creates Mender Artifact, using randomly generated dummy name
      # 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 Mender docs:
      # https://docs.mender.io/artifact-creation/create-an-artifact
      - name: Create Mender Artifact
        id: create_artifact
        run: |
          curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
          chmod 755 hello-mender.py
          MENDER_ARTIFACT_NAME=artifact_${MENDER_RELEASE_NAME}.mender
          single-file-artifact-gen \
            --device-type raspberrypi4 \
            -o ${MENDER_ARTIFACTS_CI_ARTIFACT_PATH}/${MENDER_ARTIFACT_NAME} \
            -n ${MENDER_RELEASE_NAME} \
            --software-name hello-mender \
            --software-version 1.0 \
            --dest-dir /usr/local/bin \
            hello-mender.py
          echo "mender_artifact_name=${MENDER_ARTIFACT_NAME}" >> ${GITHUB_OUTPUT}
      # Uploads GitHub Actions artifacts to GitHub artifact storage to pass them to the further jobs
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.MENDER_ARTIFACTS_CI_ARTIFACT_NAME }}
          path: ${{ env.MENDER_ARTIFACTS_CI_ARTIFACT_PATH }}

  #
  # Upload Built Mender artifact to a Mender server
  #
  publish:
    needs:
      - build
    runs-on: ubuntu-latest
    steps:
      # Downloads built in previous job GitHub Actions artifacts
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.MENDER_ARTIFACTS_CI_ARTIFACT_NAME }}
          path: ${{ env.MENDER_ARTIFACTS_CI_ARTIFACT_PATH }}
      # Uploads Mender Artifact to a Mender server, using previously generated Mender Artifact name
      - name: Upload Mender Artifact to Mender server
        uses: mendersoftware/mender-gh-action-upload-artifact@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_artifact: ${{ env.MENDER_ARTIFACTS_CI_ARTIFACT_PATH }}/${{ needs.build.outputs.mender_artifact_name }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}

  #
  # Create Deployment on Mender server
  #
  deploy:
    needs:
      - build
      - publish
    runs-on: ubuntu-latest
    steps:
      # Creates a deployment on a Mender server, using previously generated Mender deployment and release names
      - name: Create deployment on Mender server
        uses: mendersoftware/mender-gh-action-create-deployment@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}
          mender_deployment_name: ${{ needs.build.outputs.mender_deployment_name }}
          mender_release_name: ${{ needs.build.outputs.mender_release_name }}
          mender_devices_group: ${{ needs.build.outputs.mender_devices_group }}

Build and deploy multiple Mender Artifacts

#
# The example shows how to build, upload and deploy Mender Artifacts for two different 
# device types in paralel.
#
# 'MENDER_SERVER_ACCESS_TOKEN' secret is required to be set in GitHub repo settings.
#

name: Build and Deploy Two Mender Artifacts

on:
  push:
    branches:
      - main

env:
  MENDER_SERVER_URL: https://hosted.mender.io       # Mender server URL
  MENDER_DEPLOYMENT_DEVICES_GROUP_PREFIX: group-dev # Mender deployment name prefix

jobs:
  #
  # Build two Mender artifacts and deploy them to related groups
  #
  build-and-deploy:
    runs-on: ubuntu-latest
    # run multiply jobs for different device types
    strategy:
      matrix:
        device: ["sensor", "executive"]
    # conrainer with pre-installed mender-artifact and mender-cli tools
    container:
      image: mendersoftware/mender-ci-tools:1.0.0
    steps:
      # Checkout git repository
      - uses: actions/checkout@v2
      # Generates the required variables to later create the Mender Artifact, using a dummy application
      # name "change-the-world-to-better" with a random version.
      - name: Generrate Mender release name
        run: |
          APP_NAME=change-the-world-to-better
          VERSION="$(($RANDOM%9+1)).$(($RANDOM%9+1)).$(($RANDOM%9+1))"
          MENDER_RELEASE_NAME=${APP_NAME}_v${VERSION}
          echo "MENDER_RELEASE_NAME=${MENDER_RELEASE_NAME}" >> ${GITHUB_ENV}
      # Generates Mender deployment name to later create the Mender deployment
      - name: Generate Mender deployment name
        run: |
          COMMIT_SHORT_SHA="${GITHUB_SHA:0:8}"
          MENDER_DEPLOYMENT_NAME=${{ matrix.device }}_${MENDER_RELEASE_NAME}_${COMMIT_SHORT_SHA}
          echo "MENDER_DEPLOYMENT_NAME=${MENDER_DEPLOYMENT_NAME}" >> ${GITHUB_ENV}
      # Creates Mender Artifact, using randomly generated dummy name
      # 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 Mender docs:
      # https://docs.mender.io/artifact-creation/create-an-artifact
      - name: Create Mender Artifact
        run: |
          curl -O https://raw.githubusercontent.com/mendersoftware/mender-ci-workflows/master/examples/hello-mender.py
          chmod 755 hello-mender.py
          MENDER_ARTIFACT_NAME=artifact_$(( $RANDOM % 9999 + 1000 )).mender
          SOFTWARE_NAME=${{ matrix.device }}
          SOFTWARE_VERSION="$(($RANDOM%9+1)).$(($RANDOM%9+1))"
          single-file-artifact-gen \
            --device-type raspberrypi4 \
            -o ${MENDER_ARTIFACT_NAME} \
            -n ${MENDER_RELEASE_NAME} \
            --software-name ${SOFTWARE_NAME} \
            --software-version ${SOFTWARE_VERSION} \
            --dest-dir /usr/local/bin \
            hello-mender.py
          echo "MENDER_ARTIFACT_NAME=${MENDER_ARTIFACT_NAME}" >> ${GITHUB_ENV}
      # Uploads Mender Artifact to a Mender server, using previously generated Mender Artifact name
      - name: Upload Mender Artifacts to Mender server
        uses: mendersoftware/mender-gh-action-upload-artifact@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_artifact: ${{ env.MENDER_ARTIFACT_NAME }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}
      # Creates a deployment on a Mender server, using previously generated Mender deployment and release names
      - name: Create deployment on Mender server
        uses: mendersoftware/mender-gh-action-create-deployment@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}
          mender_deployment_name: ${{ env.MENDER_DEPLOYMENT_NAME }}
          mender_release_name: ${{ env.MENDER_RELEASE_NAME }}
          mender_devices_group: ${{ env.MENDER_DEPLOYMENT_DEVICES_GROUP_PREFIX }}-${{ matrix.device }}

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 GitHub repo settings
#

name: Build and Deploy to a Single Device

on:
  push:
    branches:
      - main

env:
  MENDER_SERVER_URL: https://hosted.mender.io           # Mender server URL
  MENDER_DEPLOYMENT_NAME: my-app-v1.0-dev               # Mender deployment name
  MENDER_RELEASE_NAME: change-the-world-to-better-v1.0  # Mender release name
  MENDER_ARTIFACT_NAME: artifact.mender                 # Mender artifact name
  MENDER_DEVICES_LIST: '[\"5ca6090ff3a8e90001206535\"]' # List of devices to deploy built artifact to

jobs:
  #
  # Build two Mender artifacts and deploy them to related groups
  #
  build-and-deploy:
    runs-on: ubuntu-latest
    # conrainer with pre-installed mender-artifact and mender-cli tools
    container:
      image: mendersoftware/mender-ci-tools:1.0.0
    steps:
      # Checkout git repository
      - uses: actions/checkout@v2
      # 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 Mender docs:
      # https://docs.mender.io/artifact-creation/create-an-artifact
      - name: Create Mender Artifact
        run: |
          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
      # Uploads Mender Artifact to a Mender server
      - name: Upload Mender Artifacts to Mender server
        uses: mendersoftware/mender-gh-action-upload-artifact@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_artifact: ${{ env.MENDER_ARTIFACT_NAME }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}
      # Creates a deployment on a Mender server
      - name: Create deployment on Mender server
        uses: mendersoftware/mender-gh-action-create-deployment@master
        with:
          mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
          mender_uri: ${{ env.MENDER_SERVER_URL }}
          mender_deployment_name: ${{ env.MENDER_DEPLOYMENT_NAME }}
          mender_release_name: ${{ env.MENDER_RELEASE_NAME }}
          mender_devices_list: ${{ env.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 .