Synology backup first pass #164
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |