Ansible Workflows with Gitea Actions

In this post, we'll look at how to use Gitea Actions to automate Ansible workflows including linting and running the playbooks and some key gotcha's when setting up the workflow

Pre-Requisites

This blog post assumes that you:

  1. Have Gitea and Gitea Actions set up and installed
  2. Have a repository with Ansible playbooks

Prepare The Environment

Before you can run the Ansible Playbooks you need to set a few environment variables in the Gitea repository settings.

  1. VAULT_PASSWORD - This is the password used to decrypt the Ansible vault
  2. SSH_PRIVATE_KEY - This is the SSH private key used to connect to the servers

To set these you need to go to settings -> actions -> secrets in the repository settings.

Ansible Lint Workflow

The Ansible Link Github Action is provided as an easy to use action that, in theory, is compatible with Gitea Actions. However I wasn’t able to get it work on the base ubuntu-latest image.

Instead, we can use a custom workflow to install ansible, decrypt our vault, and run ansible-lint. This has the added benefit of allowing us to pass any additional arguments we need directly to ansible-lint.

This Workflow Will:

  1. Checkout the repository
  2. Install Ansible and Ansible lint. Some guides will say to use the –user flag to install ansible. We cannot use this because in the container the installation location for –user is not in the $PATH and you action will fail.
  3. Decrypt the vault using the action secret you’ve set VAULT_PASSWORD. This requires some trickery because ansible-vault does not support reading a password from an environment file so we instead write out a short script that will yield the VAULT_PASSWORD when it reads the file.
  4. Run ansible-lint with the configuration file .ansible-lint.yml and the playbooks ansible/playbook.*.yaml you will need to adjust these arguments to fit your environment
# file ./gitea/workflows/ansible-lint.yaml
name: Ansible Lint
on:
  pull_request:
    branches:
      - main

jobs:
  Homelab-Deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      # install ansbile
      - name: Install Ansible
        run: |
          apt update -y
          apt install python3-pip -y
          python3 -m pip install ansible
          python3 -m pip install ansible-lint          

      - name: Decrypt vault
        env:
          VAULT_PASSWORD: ${{ secrets.VAULT_PASSWORD }}
        run: |
          echo '#!/bin/bash 
          echo "${VAULT_PASSWORD}"' > ./vault-pw.sh
          chmod +x ./vault-pw.sh
          ansible-vault decrypt --vault-password-file ./vault-pw.sh ansible/vars/vault.yaml          

      - name: Run ansible-lint
        run: |
          ansible-lint -c ./.ansible-lint.yml ansible/playbook.*.yaml          

Ansible Run Workflow

For our actual ansbile workflow we can use the Ansible Playbook Action as it works as expected with the ubuntu-latest images that run on Gitea Actions.

This Workflow Will:

  1. Checkout the repository
  2. Install Ansible
  3. Install Ansible Galaxy requirements
  4. For each playbook defined in the matrix, run the playbook with the inventory file ansible/inventory.yaml, vault password VAULT_PASSWORD, and the SSH private key SSH_PRIVATE_KEY
# file ./gitea/workflows/ansible-deploy.yaml
name: Ansible Deploy
on:
  push:
    branches:
      - main

jobs:
  Homelab-Deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        playbook:
          - ansible/playbook.sidecar.yaml
          - ansible/playbook.asguard.yaml
          - ansible/playbook.nvr.yaml
          - ansible/playbook.zues.yaml

    steps:
      - uses: actions/checkout@v4

      # install ansbile
      - name: Install Ansible
        run: |
          apt update -y
          apt install python3-pip -y
          python3 -m pip install ansible          

      - name: Install Ansible Galaxy requirements
        run: |
          ansible-galaxy install -r requirements.yaml          

      - name: Run playbook
        uses: dawidd6/action-ansible-playbook@v2
        with:
          # Required, playbook filepath
          playbook: ${{ matrix.playbook }}
          # Optional, directory where playbooks live
          directory: ./
          # Optional, SSH private key
          key: ${{secrets.SSH_PRIVATE_KEY}}
          vault_password: ${{secrets.VAULT_PASSWORD}}
          # Optional, galaxy requirements filepath
          requirements: requirements.yaml
          options: |
            --inventory ansible/inventory.yaml