Release and Deploy Ansible Collection with GitHub Actions

Jose Angel Munoz - Aug 9 '20 - - Dev Community

Prepare your repository

Follow the Ansible Developer Guide to prepare your content. The published collection can contain plugins, roles and playbooks (TBD) among others. Please check the oficial documentation regularly to keep your collection up to date.

Create your Ansible Galaxy account

Go to Ansible Galaxy and connect with your GitHub account. In order to publish content automatically to your account, you have to get and copy your personal API key.

  1. Click over your username.
  2. Preferences.
  3. API Key. Show API Key.

Alt Text

Tip: For debugging and development purposes, there is a Development Environment of Ansible Galaxy available.

Adding the API Key to GitHub

  1. On GitHub, navigate to the main page of the repository.
  2. Under your repository name, click Settings.
  3. In the left sidebar, click Secrets.
  4. Type a name for your secret in the Name input box. We will use GALAXY_API_KEY for production and GALAXYDEV_API_KEY for development.

Alt Text

Find the full procedure in the GitHub Documentation.

Generate your galaxy.yml file

The process will read and use the file galaxy.yml not only to build the package with the ansible-galaxy command, also to create the tag and the release on GitHub. Be sure that the version in the file is correct and has not been used before.

At the time of writting, the process doesn't support tag replacement on GitHub or overwrite the version on Galaxy. Although the replace_old_tag flag will be available soon for GitHub I recommend to keep control of the releases process. I also recommend the use of the development environment for the first steps.

Example galaxy.yml:



---
namespace: "imjoseangel"
name: "common"
version: "0.1.4"
readme: "README.md"
authors:
    - "Jose Angel Munoz <josea.munoz@gmail.com>"
license:
    - "MIT"
tags:
    - imjoseangel
    - common
    - collection
    - linux
    - windows
    - util
repository: "https://www.github.com/imjoseangel/ansiblecommon"



Enter fullscreen mode Exit fullscreen mode

In this example we will create the release 0.1.4 whether in GitHub and Ansible Galaxy.

Create the GitHub workflow

Create the following structure in your project:



.github/
└── workflows
    └── release.yml


Enter fullscreen mode Exit fullscreen mode

The release.yml contains the actions for GitHub. In our example, we are going to use the action on-demand, using the workflow_dispatch option. So the header is:



---
name: Release and Deploy collection
on: # yamllint disable-line rule:truthy
  workflow_dispatch:


Enter fullscreen mode Exit fullscreen mode

We are going to use only one job. The release and the deploy will use exactly the same build and we will avoid different builds for release and deploy.



jobs:
  releaseanddeploy:
    runs-on: ubuntu-latest
    if: github.repository == 'imjoseangel/ansiblecommon'
    strategy:
      matrix:
        python-version: [3.8]


Enter fullscreen mode Exit fullscreen mode

Steps

First download the branch and read the version from the galaxy.yml file:



    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Get current version
        id: cversion
        run: echo "::set-output name=version::$(grep version galaxy.yml | awk -F'"' '{ print $2 }')"


Enter fullscreen mode Exit fullscreen mode

Use the python version defined in the matrix and install ansible. Install also the requirements.txt if found. This step is not needed but I think it was cool to keep 😜 as reference.



      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install --upgrade ansible
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi


Enter fullscreen mode Exit fullscreen mode

Create a build directory with the content that will be included in the collection. Note that if you want to add extra files or directories, you need to add those to the files or directories variables.



      - name: Copy files and directories to source
        run: |
          mkdir -p build/src
          cp $files build/src
          cp -rf $directories build/src
        env:
          files: "README.md LICENSE ansible.cfg galaxy.yml"
          directories: "inventories playbooks roles vars"


Enter fullscreen mode Exit fullscreen mode

Time to build the collection.



      - name: Build Ansible Collection
        run: ansible-galaxy collection build build/src --force


Enter fullscreen mode Exit fullscreen mode

The next two steps will do the following:

  1. Creates the release and tag with the version in the galaxy.yml file.
  2. Adds the instructions to the release.
  3. Attachs the collection to the release, keeping the source code (The whole project) and the collection package.


      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: v${{ steps.cversion.outputs.version }}
          release_name: Release v${{ steps.cversion.outputs.version }}
          body: |
            # Ansible Collection: imjoseangel.common
            ![ReleaseBuildCollection](https://github.com/imjoseangel/ansiblecommon/workflows/ReleaseBuildCollection/badge.svg)

            Install with:
            ansible-galaxy collection install -r requirements.yml -f

            The requirements.yml needs to have the following format and content:
            ---
            collections:
                - https://github.com/imjoseangel/ansiblecommon/releases/download/v${{ steps.cversion.outputs.version }}/imjoseangel-common-${{ steps.cversion.outputs.version }}.tar.gz
          draft: false
          prerelease: false

      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: imjoseangel-common-${{ steps.cversion.outputs.version }}.tar.gz
          asset_name: imjoseangel-common-${{ steps.cversion.outputs.version }}.tar.gz
          asset_content_type: application/tar+gzip


Enter fullscreen mode Exit fullscreen mode

Finally deploy the package to Ansible Galaxy.



      - name: Deploy Ansible collection to Galaxy
        run: ansible-galaxy collection publish imjoseangel-common-${{ steps.cversion.outputs.version }}.tar.gz --api-key ${{ secrets.GALAXY_API_KEY }}


Enter fullscreen mode Exit fullscreen mode

If we want to use the development environment, the run: line has to be:



run: ansible-galaxy collection publish imjoseangel-common-${{ steps.cversion.outputs.version }}.tar.gz --server https://galaxy-dev.ansible.com/ --api-key ${{ secrets.GALAXYDEV_API_KEY }}


Enter fullscreen mode Exit fullscreen mode

Where to find the release

On GitHub, under your project releases:

In the example: https://github.com/imjoseangel/ansiblecommon/releases

Alt Text

On Ansible Galaxy, under My Content

Alt Text

How to install the collection

The easiest way to install the collection is copying the ansible-galaxy command from the Ansible Galaxy project:

ansible-galaxy collection install imjoseangel.common

For internal projects, the best way is creating a requirements.yml file and follow the instructions in the release document:



---
collections:
    - https://github.com/imjoseangel/ansiblecommon/releases/download/v0.1.4/imjoseangel-common-0.1.4.tar.gz


Enter fullscreen mode Exit fullscreen mode

Install it with:



ansible-galaxy collection install -r requirements.yml -f


Enter fullscreen mode Exit fullscreen mode

If you want to improve this process or understand it better, you can visit the original project on GitHub

. . . . . . . . . .