DEV Community

Cover image for How to execute Ansible Playbook with a Github Action.
Thodoris Velmachos
Thodoris Velmachos

Posted on

How to execute Ansible Playbook with a Github Action.

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>"

Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)