Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 158 additions & 15 deletions .github/workflows/ansible-lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,86 @@ on:
pull_request:
paths:
- "ansible/**"
- "!ansible/**/*.md"
- "!ansible/**/README*"
- ".github/workflows/ansible-lint-and-test.yml"
push:
branches:
- main
paths:
- "ansible/**"
- "!ansible/**/*.md"
- "!ansible/**/README*"
- ".github/workflows/ansible-lint-and-test.yml"
workflow_dispatch:

jobs:
detect-changes:
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
roles_json: ${{ steps.normalize.outputs.roles_json }}
playbooks_json: ${{ steps.normalize.outputs.playbooks_json }}
targets_json: ${{ steps.normalize.outputs.targets_json }}
has_targets: ${{ steps.normalize.outputs.has_targets }}
has_playbooks: ${{ steps.normalize.outputs.has_playbooks }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect changed files
uses: dorny/paths-filter@v3
id: filter
with:
list-files: json
filters: |
roles:
- ansible/roles/**
playbooks:
- ansible/playbooks/**/*.yml
- ansible/playbooks/**/*.yaml
- ansible/site.yml

- name: Normalize changed paths to targets
id: normalize
run: |
set -euo pipefail

ROLES_FILES='${{ steps.filter.outputs.roles_files }}'
PLAYBOOKS_FILES='${{ steps.filter.outputs.playbooks_files }}'

# Extract unique role directories using jq only
ROLES_JSON=$(echo "$ROLES_FILES" | jq -c '[.[] | select(startswith("ansible/roles/")) | split("/") | "ansible/roles/" + .[2]] | unique')

# Extract unique playbook files
PLAYBOOKS_JSON=$(echo "$PLAYBOOKS_FILES" | jq -c 'unique')

# Combine roles + playbooks for targets
TARGETS_JSON=$(jq -nc --argjson r "$ROLES_JSON" --argjson p "$PLAYBOOKS_JSON" '$r + $p | unique')

# Boolean flags
HAS_TARGETS=$(echo "$TARGETS_JSON" | jq -r 'length > 0')
HAS_PLAYBOOKS=$(echo "$PLAYBOOKS_JSON" | jq -r 'length > 0')

{
echo "roles_json=$ROLES_JSON"
echo "playbooks_json=$PLAYBOOKS_JSON"
echo "targets_json=$TARGETS_JSON"
echo "has_targets=$HAS_TARGETS"
echo "has_playbooks=$HAS_PLAYBOOKS"
} >> "$GITHUB_OUTPUT"

echo "Changed roles: $ROLES_JSON"
echo "Changed playbooks: $PLAYBOOKS_JSON"
echo "Combined targets: $TARGETS_JSON"
echo "Has targets: $HAS_TARGETS"
echo "Has playbooks: $HAS_PLAYBOOKS"

ansible-yamllint:
if: github.event_name != 'workflow_dispatch' && needs.detect-changes.outputs.has_targets == 'true'
needs: detect-changes
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -42,10 +112,20 @@ jobs:
--pull=always
run: |
pip install --quiet yamllint
echo "Running yamllint on Ansible YAML files..."
yamllint ansible/
echo "Running yamllint on changed Ansible YAML files..."
python3 -c '
import json, sys, subprocess
targets = json.loads(sys.argv[1])
if targets:
print(f"Linting {len(targets)} target(s): {targets}")
subprocess.run(["yamllint"] + targets, check=True)
else:
print("No targets to lint")
' '${{ needs.detect-changes.outputs.targets_json }}'

ansible-lint:
if: github.event_name != 'workflow_dispatch' && needs.detect-changes.outputs.has_targets == 'true'
needs: detect-changes
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -75,28 +155,28 @@ jobs:
run: |
ansible-galaxy collection install -r ansible/requirements.yml
pip install --quiet ansible-lint
echo "Running ansible-lint on roles and playbooks..."
ansible-lint ansible/playbooks/ ansible/roles/ ansible/site.yml --exclude ansible/old_roles/
echo "Running ansible-lint on changed roles and playbooks..."
python3 -c '
import json, sys, subprocess
targets = json.loads(sys.argv[1])
if targets:
print(f"Linting {len(targets)} target(s): {targets}")
subprocess.run(["ansible-lint"] + targets + ["--exclude", "ansible/old_roles/"], check=True)
else:
print("No targets to lint")
' '${{ needs.detect-changes.outputs.targets_json }}'

ansible-playbook-syntax:
if: github.event_name != 'workflow_dispatch' && needs.detect-changes.outputs.has_playbooks == 'true'
needs: detect-changes
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
strategy:
fail-fast: false
matrix:
playbook:
- ansible/playbooks/audio-production.yml
- ansible/playbooks/coachlight-infra-stack.yml
- ansible/playbooks/file_copier_examples.yml
- ansible/playbooks/k3s-cluster-setup.yml
- ansible/playbooks/omada-netbox-sync.yml
- ansible/playbooks/omada-tester.yml
- ansible/playbooks/op_tester.yml
- ansible/playbooks/proxmox.yml
- ansible/playbooks/workstations.yml
- ansible/site.yml
playbook: ${{ fromJSON(needs.detect-changes.outputs.playbooks_json) }}

steps:
- name: Normalize repo name to lowercase
Expand All @@ -123,3 +203,66 @@ jobs:
ansible-galaxy collection install -r ansible/requirements.yml
echo "Checking syntax for ${{ matrix.playbook }}..."
ansible-playbook ${{ matrix.playbook }} --syntax-check

full-lint:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: read

steps:
- name: Normalize repo name to lowercase
id: normalize
run: |
echo "REPO_LOWER=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT

- name: Set tooling image
id: image
run: |
echo "IMAGE=ghcr.io/${{ steps.normalize.outputs.REPO_LOWER }}/fedora-43-homelab-tooling:latest" >> $GITHUB_OUTPUT

- name: Checkout repository
uses: actions/checkout@v4

- name: Run yamllint inside tooling container
uses: addnab/docker-run-action@v3
with:
image: ${{ steps.image.outputs.IMAGE }}
options: |
-v ${{ github.workspace }}:/workspace
--pull=always
run: |
pip install --quiet yamllint
echo "Running yamllint on all Ansible YAML files..."
yamllint ansible/

- name: Run ansible-lint inside tooling container
uses: addnab/docker-run-action@v3
with:
image: ${{ steps.image.outputs.IMAGE }}
options: |
-v ${{ github.workspace }}:/workspace
--pull=always
run: |
ansible-galaxy collection install -r ansible/requirements.yml
pip install --quiet ansible-lint
echo "Running ansible-lint on all roles and playbooks..."
ansible-lint ansible/playbooks/ ansible/roles/ ansible/site.yml --exclude ansible/old_roles/

- name: Run syntax check on all playbooks
uses: addnab/docker-run-action@v3
with:
image: ${{ steps.image.outputs.IMAGE }}
options: |
-v ${{ github.workspace }}:/workspace
--pull=always
run: |
ansible-galaxy collection install -r ansible/requirements.yml
echo "Checking syntax for all playbooks..."
for playbook in ansible/playbooks/*.yml ansible/site.yml; do
if [ -f "$playbook" ]; then
echo "Checking syntax for $playbook..."
ansible-playbook "$playbook" --syntax-check
fi
done
5 changes: 5 additions & 0 deletions semicolon_delimited_script
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot remove this file

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ansible --version
ansible-lint --version
yamllint --version
python3 --version