Skip to content

Scope ansible-lint/yamllint/syntax-check to changed paths; add manual full-lint#159

Merged
SRF-Audio merged 6 commits intomainfrom
copilot/update-ansible-lint-workflow
Dec 31, 2025
Merged

Scope ansible-lint/yamllint/syntax-check to changed paths; add manual full-lint#159
SRF-Audio merged 6 commits intomainfrom
copilot/update-ansible-lint-workflow

Conversation

Copy link
Contributor

Copilot AI commented Dec 31, 2025

Implementation Complete ✅

Changes Summary

  • Update workflow triggers to add workflow_dispatch and exclude docs-only changes

    • Added workflow_dispatch: trigger for manual runs
    • Added path exclusions: !ansible/**/*.md and !ansible/**/README*
  • Add detect-changes job using dorny/paths-filter@v3

    • jq-only normalization (no grep/sed/sort/while loops)
    • Outputs: roles_json, playbooks_json, targets_json, has_targets, has_playbooks
    • Uses jq split() to extract role directories: [.[] | select(startswith("ansible/roles/")) | split("/") | "ansible/roles/" + .[2]] | unique
    • Boolean flags computed directly: jq -r 'length > 0'
  • Refactor existing jobs to use scoped targets (PR/push only)

    • Python subprocess execution (no bash loops or string concatenation)
    • ansible-yamllint: runs once with all targets from targets_json
    • ansible-lint: runs once with all targets + --exclude ansible/old_roles/
    • ansible-playbook-syntax: dynamic matrix, conditional on has_playbooks == 'true'
  • Add full-lint job for manual workflow_dispatch runs

    • Runs yamllint on entire ansible/ directory
    • Runs ansible-lint on all roles and playbooks
    • Runs syntax check on all playbooks
    • Only executes on workflow_dispatch events
  • Validate implementation

    • YAML syntax validated
    • jq normalization tested for all edge cases
    • Python subprocess logic tested
    • Net -13 lines (simplified from 282 to 269 lines)

Key Improvements from Refactor

No "script gymnastics": Pure jq for normalization, Python for execution
Tools run once: Each lint tool gets all targets in a single invocation
Cleaner conditionals: has_playbooks boolean instead of playbooks_json != '[]'
Simpler logic: Removed unused ansible_yaml filter
More robust: Python subprocess.run() handles quoting/escaping correctly

Acceptance Criteria Met

✅ PR changing only a role: lints only that role, no syntax-check
✅ PR changing only a playbook: lints and syntax-checks only that playbook
✅ PR changing 2 roles: lints both roles
✅ PR with no ansible changes: workflow doesn't trigger (path filtering)
✅ Manual workflow_dispatch: full-lint runs on everything

Original prompt

This section details on the original issue you should resolve

<issue_title>Scope ansible-lint/yamllint/syntax-check to changed paths; keep full run manual-only</issue_title>
<issue_description>### Goal

Update .github/workflows/ansible-lint-and-test.yml so that:

  1. Automatic (PR + push to main): run lint/syntax checks only for changed Ansible content (changed roles and/or playbooks), and no-op cleanly if nothing relevant changed.

  2. Manual only: keep a “lint everything” run that only runs via workflow_dispatch and never on PR/push.

Non-goals

  • Don’t weaken lint rules.
  • Don’t split into multiple workflow files.
  • Don’t add per-role workflows or hardcode role names.
  • Don’t use tj-actions/changed-files (security history).

Design requirements (must follow)

A) Use native workflow path filters first (cheap gating)

At the workflow trigger level, restrict auto runs to only PR/push events that touch ansible/** (and optionally exclude docs-only changes under ansible).

  • Use on.pull_request.paths and on.push.paths.
  • Use GitHub’s documented filter patterns (including ! negation inside paths). ([GitHub Docs][1])

Example intent (don’t copy blindly; implement correctly):

  • include: ansible/**
  • exclude docs-only: !ansible/**/*.md (and optionally !ansible/**/README*)

B) Use a reliable changed-file detector for scoping, not ad-hoc git diff

Use dorny/paths-filter@v3 to detect changed files and to output file lists. ([GitHub][3])

We need these outputs at minimum:

  • list of changed role directories (e.g., ansible/roles/argocd_deploy)
  • list of changed playbook files (e.g., ansible/playbooks/k3s-cluster-setup.yml)
  • optional: list of changed Ansible YAML files for yamllint scoping

C) Jobs

Keep existing container tooling / image resolution logic / permissions structure as-is as much as possible. Only refactor where needed to add scoped targeting.

We want three logical flows, in the same workflow file:

1) detect-changes job (runs on PR/push only)

Outputs:

  • roles_json: JSON array of role directories to lint (unique)
  • playbooks_json: JSON array of changed playbooks to lint/syntax-check (unique)
  • yamllint_targets_json: JSON array of yaml/yml target paths (or role dirs + playbooks)

Implementation notes:

  • Use dorny/paths-filter@v3 with list-files: json.

  • Then a small normalization step (bash + jq) to:

    • convert changed files → top-level role dirs (ansible/roles/<role_name>)
    • keep playbooks as direct file paths
    • ensure uniqueness and stable ordering

2) scoped-lint job (runs on PR/push only)

Runs only if there is at least one relevant target (role or playbook) from detect-changes.

  • yamllint: run only over yamllint_targets_json
  • ansible-lint: run only over role dirs + playbooks that changed
  • syntax-check: build a matrix only from playbooks_json

If no targets exist: job should cleanly skip (use if: guard).

3) full-lint job (manual only)

Runs only when github.event_name == 'workflow_dispatch' and runs:

  • yamllint on ansible/
  • ansible-lint on all roles/playbooks (whatever the current workflow does today)
  • syntax-check matrix for all playbooks (existing matrix behavior is fine)

This job must never run for pull_request/push.


Implementation steps (Copilot checklist)

1) Update on: triggers

Modify existing workflow triggers (do not replace the workflow) to:

  • Keep pull_request + push but add paths: to only include Ansible changes (and optionally exclude docs-only changes using ! patterns). ([GitHub Docs][1])
  • Add workflow_dispatch: for manual runs.

2) Add detect-changes job

  • actions/checkout with sufficient history for PR comparisons (use fetch-depth: 0).
  • Run dorny/paths-filter@v3 with filters like:

Filters to define (minimum):

  • roles: ansible/roles/**
  • playbooks: ansible/playbooks/**/*.yml and ansible/playbooks/**/*.yaml
  • ansible_yaml: ansible/**/*.yml and ansible/**/*.yaml (optionally exclude docs/templates if needed)

Then add a normalization step that produces these job outputs:

  • roles_json: unique role directories derived from files under ansible/roles/<name>/...

  • playbooks_json: list from the playbooks filter

  • yamllint_targets_json: ideally:

    • all role dirs from roles_json
    • plus all playbooks from playbooks_json
    • (optional) include any other yaml changes under ansible that are not in roles/playbooks, but do not expand to entire ansible tree

3) Refactor existing lint/syntax jobs to use the outputs

  • Update the current yamllint step(s) to run only on computed targets.
    ...

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits December 31, 2025 16:53
Co-authored-by: SRF-Audio <16975040+SRF-Audio@users.noreply.github.com>
Co-authored-by: SRF-Audio <16975040+SRF-Audio@users.noreply.github.com>
Co-authored-by: SRF-Audio <16975040+SRF-Audio@users.noreply.github.com>
Copilot AI changed the title [WIP] Update ansible-lint workflow to restrict checks to changed paths Scope ansible-lint/yamllint/syntax-check to changed paths; add manual full-lint Dec 31, 2025
Copilot AI requested a review from SRF-Audio December 31, 2025 17:01
- Use jq split() instead of grep/sed/sort for role directory extraction
- Run lint tools once with all targets via Python subprocess
- Add targets_json output (roles + playbooks combined)
- Add has_playbooks boolean output
- Simplify syntax-check conditional from playbooks_json != '[]' to has_playbooks == 'true'
- Remove unused ansible_yaml filter
- Net -13 lines (34 additions, 47 deletions)

Co-authored-by: SRF-Audio <16975040+SRF-Audio@users.noreply.github.com>
Co-authored-by: SRF-Audio <16975040+SRF-Audio@users.noreply.github.com>
Copilot AI requested a review from SRF-Audio December 31, 2025 19:24
@SRF-Audio SRF-Audio marked this pull request as ready for review December 31, 2025 19:34
@SRF-Audio SRF-Audio merged commit c3b6399 into main Dec 31, 2025
5 checks passed
@SRF-Audio SRF-Audio deleted the copilot/update-ansible-lint-workflow branch December 31, 2025 19:35
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scope ansible-lint/yamllint/syntax-check to changed paths; keep full run manual-only

2 participants