• 3 min read
  • Azure Pipelines does have an extensions marketplace available, but there isn’t always a task to fill a gap. GitHub Actions Marketplace has a quickly growing list of actions and has several related to markdown linting, which was the use case I was after.

    But how does one get the GitHub Action running from an Azure DevOps Pipeline?

    Find the Docker image for the GitHub Action

    Fortunately, it’s fairly straightforward to get an GitHub Action running from your AzDO Pipeline provided the author uses a Docker container — there are several GitHub action types, and not all of them use Docker. Once you’ve found a marketplace Action you like, go to its repo using the link on the right-hand pane above Open Issues.

    Any Docker-based task will have an action.yaml file in their repo, so if the author doesn’t mention the image name in their README peek at the runs section of their action.yaml to find their registry and image name. For example, have a look at the action.yaml from the Markdown Lint action).

    If it’s not a Docker based task, sometimes you’re lucky and the author provides one anyways in the README - such is the case for Markdown Link Check, even though it is a JavaScript-based action.

    Configure your pipeline

    Provided a Docker container is available for the Action, it’s a fairly straightforward to integrate it into a DevOps after installing Docker tools onto your build agent.

    First, ensure you have the docker tools available on your build agent:

    ...
    steps:
      - task: DockerInstaller@0
        displayName: Docker Installer
        inputs:
          releaseType: stable
      ...

    Next, use a script task to issue a docker run that sets up an environment similar to that created by GitHub actions. For most Actions, I’ve found that just mapping a volume of the repository root to /tmp and setting the working directory to the same to be sufficient:

    steps:
      # ...
      - script: |
          docker run --rm -i -v $(pwd):/tmp -w /tmp IMAGE_NAME:TAG ARGS_IF_APPLICABLE
        displayName: "Run GitHub Action "

    For example, for the Markdown Link Check:

    steps:
      # ...
      # https://github.com/marketplace/actions/markdown-link-check
      - script: |
          docker run --rm -i -v $(pwd):/tmp:ro -w /tmp ghcr.io/tcort/markdown-link-check:stable *.md **/*.md
        displayName: "Check for broken URLs"

    (note here, since link checking doesn’t require write access to the repo I’ve also marked the /tmp volume as ro to limit its permissions - this is optional, but recommended)

    Some actions may make use of GitHub built-in environment variables. If you run into errors due to missing variable values, you will need to look at the Action repo to find out when are used, and map them to the Azure Pipelines Predefined Variables as best you can:

    docker run --rm -i -v "$(pwd):/tmp:ro" -w /tmp -e GITHUB_SHA="$(Build.SourceVersion)" -e GITHUB_JOB="$(System.JobId)" IMAGE_NAME:TAG ARGS

    Putting it all together

    Here’s an sample complete job template YAML to kick off markdown linting, link checking, and spellchecking:

    # Re-usable pipeline job template to perform markdown linting.
    
    jobs:
      - job: verify_markdown
        timeoutInMinutes: 10
        pool:
          vmImage: ubuntu-latest
        steps:
          - task: DockerInstaller@0
            displayName: Docker Installer
            inputs:
              releaseType: stable
    
          # https://github.com/marketplace/actions/markdown-linting-action
          - script: |
              docker run --rm -v $(pwd):/tmp:ro -w /tmp avtodev/markdown-lint:master .
            displayName: "Lint markdown"
    
          # https://github.com/marketplace/actions/markdown-link-check
          - script: |
              docker run --rm -i -v $(pwd):/tmp:ro -w /tmp ghcr.io/tcort/markdown-link-check:stable *.md **/*.md
            displayName: "Check for broken URLs"
    
          # https://github.com/marketplace/actions/github-spellcheck-action
          - script: |
              docker run --rm -v $(pwd):/tmp jonasbn/github-action-spellcheck
            displayName: "Check for spelling errors"

    Note - since this trick only involves setting up the Docker image in the right way, you can also use these Actions locally using the same docker run commands as your pipeline, as long as you can find the right values any environment variables if they are required by the Action.