Deploy Ansible with GitHub Actions
"Automate, customize, and execute your software development workflows right in your repository with GitHub Actions." Says the introduction on the GitHub Actions documentation page. How does this relate to Ansible? Ansible is code and because of that, you can build a workflow that deploys it based on Git events. Such as a push or pull request to the repository.
Create an Ansible Action
GitHub Actions are individual tasks that you combine to create jobs and customize workflows. Using a Docker container Action, you will create your own to run Ansible whenever you push or merge a pull request.
Create the Ansible Action directory.
mkdir .github/actions/ansible
Create a new Dockerfile
.
FROM <DockerHub-UserName>/ansible-in-containers
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["bash","/entrypoint.sh"]
Copy the entrypoint.sh
script to the Ansible Action directory.
#BASH
Copy entrypoint.sh .github/actions/ansible
#POWERSHELL
Copy-Item entrypoint.sh .github/actions/ansible
Create the action.yml
in the new directory.
name: 'Ansible'
description: 'Runs an Ansible playbook'
inputs:
playbook:
description: 'Ansible playbook to run'
required: true
default: playbook.yml
inventory:
description: 'Ansible inventory to use'
required: true
default: localhost
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.playbook }}
- ${{ inputs.inventory }}
Name and description give context to what the action is and what it does. Inputs define the parameters used by the Docker container Action. The playbook and inventory are required inputs for this action because without them the entry point arguments would be empty and the ansible-command
would fail to run. Each of the inputs also has a default value.
Within the runs section where the magic happens. Setting using to docker is what specifies the Action type as a Docker container Action. Setting the image to Dockerfile instructs the Action to use the Dockerfile local to the Action's directory to build the container used by the Action. Args then are passed in after the image is built and the Action runs the container.
Create the Workflow
Workflows are custom automated processes that allow you to orchestrate your build, test, and release. Using a workflow you will lint all your Ansible files, then run the Ansible Docker container Action.
Create the workflow
directory
mkdir .github/workflows
Create the deploy_ansible.yml
workflow file.
name: deploy ansible
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repo
uses: actions/checkout@v2
- name: Lint Ansible Playbook
uses: ansible/ansible-lint-action@master
with:
targets: ""
deployAnsible:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: ./.github/actions/ansible
with:
playbook: playbook.yml
inventory: localhost
The above will create a GitHub workflow named deploy Ansible. It will only be triggered when there is a push or pull request made to the master branch of the repository. Once triggered the workflow will kick-off two jobs. First, the build
job runs. Build runs a public GitHub Action called ansible-lint which runs the ansible-lint command-line utility against all .yml or.yaml files in your repository. If ansible-lint is successful the second job is triggered. Running the Ansible Docker container action deployAnsible
runs using the with values provided as arguments to the container. The container then runs the ansible-playbook
command with the arguments specified in the with
list.
Only one thing remains, push your changes. GitHub will detect the files within the .github directory and create the Actions and Workflow based on the .yml documents in the corresponding directories. Give it a minute or two, then your repository on GitHub.com, and review the action's results under the Actions tab.
Conclusion
You've now learned how to build, run, and deploy Ansible inside a Docker container. Containers are no longer something only developers use to run applications. It's also how sysadmins, DevOps engineers, and SREs deploy infrastructure as code. Using containers yourself you'll see the benefits first hand. Containers provide a consistent development experience for you, your team, and release pipelines, versioned images of your Ansible environment, increased portability, and flexibility. Containers are the future of infrastructure, not just web apps. Don't wait until you need to learn about them, start today, start now.
Read the full blog post, "Using Ansible in Containers" on duffney.io
Top comments (8)
After the Github action is triggered by a new push into the repo, I get this error - " /entrypoint.sh: line 9: ansible-playbook: command not found " while running the 'deployAnsible' job. Could you point out what could I be doing wrong here?
Hey Ankit,
The error typically means the OS can't find the Ansible installation. To troubleshoot I'd enter the container locally by overriddng the entry point. My blog post on this is current offline as I'm migrating, but here's a link to the doc on GitHub.
github.com/Duffney/duffney.io/blob...
Once inside the container I'd attempt to run the ansible-playbook command and if it's not preset update the dockerfile to get a proper installation. :)
Hope this helps and gets you start in the right direction. Please lmk how it goes.
Hi Josh,
I am getting this error now:
manifest for ankitjaadoo/ansible-container:latest not found: manifest unknown: manifest unknown
Error: Docker build failed with exit code 1
I am using DockerHub and working on Windows 10. Could you sense what the issue might be here?
That means that the container image wasn't found locally. You'll first have to run the docker build . -t ankitjaadoo/ansible-container:latest from the directory where the dockerfile is located for the GH action. :)
Please lmk if that helps.
alright, I am going to try that
BTW if I were to run the docker build command as apart of the github actions, should I include it in the actions preceding the workflows or within a new workflow altogether?
You say "Copy the entrypoint.sh script to the Ansible Action directory." even though you don't show us where the file is created or what are its contents, or maybe my own knowledge is just limited, I could use some help.
Isn't the action run in a virtual machine /container to start with? You can't just use the run: tag?
Sorry for the newb question but everyone uses docker, just wondering why.