Hello, are you wondering if you can execute an Ansible Playbook with a Github action then please continue reading.
In the particular case I needed to build a Docker image and push it on Dockerhub and after that manipulate the Docker Compose Manifest in order to update the service of the Stacks running in Swarm Mode.
So, Let's Dive In...
name: Build-Push-Deploy-Docker-Image
on:
workflow_dispatch:
inputs:
imageTag:
description: "Image Tag"
required: true
default: "0.0.0"
action:
description: "Both runs CI/CD Stages"
required: true
default: "both"
jobs:
build:
if: inputs.action == 'both'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- name: Prep Docker Image (Metadata)
id: meta
uses: docker/metadata-action@v4
with:
images: # <specify the image name>
tags: ${{ inputs.imageTag }} # Tag
- name: Build and push
uses: docker/build-push-action@v3
with:
context: ./
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
deployAnsible:
if: inputs.action == 'both'
needs: build
runs-on: ubuntu-latest
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
NEW_IMAGE_TAG: app:${{ inputs.imageTag }}
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/ansible
with:
playbook: ./.github/ansible/playbook.yml
inventory: ./.github/ansible/inventory
testDeployAnsible:
if: inputs.action == 'test-cd'
runs-on: ubuntu-latest
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
NEW_IMAGE_TAG: app:${{ inputs.imageTag }}
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/ansible
with:
playbook: ./.github/ansible/playbook.yml
inventory: ./.github/ansible/inventory
#./.github/ansible/playbook.yml
---
- hosts: all
remote_user: deploy
gather_facts: false
pre_tasks:
- name: Loading environment variables
tags: always
set_fact:
SSH_PRIVATE_KEY: "{{ lookup('env', 'SSH_PRIVATE_KEY') }}"
NEW_IMAGE_TAG: "{{ lookup('env', 'NEW_IMAGE_TAG') }}"
tasks:
- name: create .ssh directory
file:
path: /root/.ssh/
state: directory
mode: '0600'
delegate_to: localhost
delegate_facts: true
- name: Write SSH Key
copy:
content: "{{ SSH_PRIVATE_KEY }}"
dest: /root/.ssh/ansible_key
mode: 0400
delegate_to: localhost
delegate_facts: true
- name: Get hostname
shell: echo "$(hostname)"
register: result
### Actual Deploy of the app new version
- name: Backup Stack File
shell: "cp -vf /home/deploy/<app>/<stack>.yaml /home/deploy/<app>/<stack>.yaml.bak"
when: result.stdout == "<hostname>"
- name: Modify the App Version
shell: sed -i -E 's/app:[0-9\.]+/{{ NEW_IMAGE_TAG }}/g' /home/deploy/<app>/<stack>.yaml
when: result.stdout == "<hostname>"
- name: Restart Stack to Pull Image
shell: "docker stack deploy -c /home/deploy/<app>/<stack>.yaml <app>-stack --with-registry-auth"
when: result.stdout == "<hostname>"
- name: Sleep for 10 seconds
ansible.builtin.wait_for:
timeout: 10
delegate_to: localhost
- name: List the deployed Docker Swarm Serv
shell: "docker service ls"
when: result.stdout == "<hostname>"
- name: List the deployed Docker Swarm Serv
shell: "docker ps -a --filter status=running"
when: result.stdout == "<hostname>"
I hope you like the tutorial, if you do give a thumps up! and follow me in Twitter, also you can subscribe to my Newsletter in order to avoid missing any of the upcoming tutorials.
Media Attribution
I would like to thank Clark Tibbs for designing the awesome photo I am using in my posts.