Skip to content

Synology backup first pass #164

Synology backup first pass

Synology backup first pass #164

name: Ansible – Lint and Test
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
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 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
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 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 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: ${{ fromJSON(needs.detect-changes.outputs.playbooks_json) }}
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 syntax check on ${{ matrix.playbook }}
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 ${{ 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