ansible-testing
Testing strategies and ansible-lint configuration for validating Ansible automation quality, covering lint rules, syntax validation, and integration test setup.
What this skill does
# Ansible Testing
Testing strategies and ansible-lint configuration for Ansible automation.
## ansible-lint
### Running Lint
```bash
# Via mise (recommended)
mise run ansible-lint
# Directly with uv
uv run ansible-lint ansible/playbooks/
# Specific file
uv run ansible-lint ansible/playbooks/my-playbook.yml
# With verbose output
uv run ansible-lint -v ansible/
```
### Configuration File
Located at `ansible/.ansible-lint`:
```yaml
---
# Profile: null, min, basic, moderate, safety, shared, production
profile: moderate
# Offline mode - don't download Galaxy requirements
offline: true
# Exclude paths
exclude_paths:
- .cache/
- .venv/
- .git/
- "*/templates/"
- "*.j2"
- .deprecated/
# Rules to skip completely
skip_list:
- var-naming[no-role-prefix] # We use descriptive names
- run-once[task] # Safe with our strategy
- command-instead-of-module # CLI tools require command
- yaml[line-length] # Long lines in infra configs
# Rules to warn but not fail
warn_list:
- fqcn[action-core]
- fqcn[action]
- no-handler
- name[play]
```
### Common Rule Categories
| Category | Description |
|----------|-------------|
| `fqcn` | Fully qualified collection names |
| `yaml` | YAML formatting (indentation, line length) |
| `name` | Task/play naming conventions |
| `command-instead-of-module` | Using command when module exists |
| `no-changed-when` | Missing changed_when on command |
| `risky-file-permissions` | Missing explicit file permissions |
### Fixing Common Issues
**Missing name on task:**
```yaml
# BAD
- ansible.builtin.apt:
name: nginx
# GOOD
- name: Install nginx
ansible.builtin.apt:
name: nginx
```
**Short module name:**
```yaml
# BAD (triggers fqcn warning)
- name: Install package
apt:
name: nginx
# GOOD
- name: Install package
ansible.builtin.apt:
name: nginx
```
**Using shell instead of command:**
```yaml
# BAD (when no shell features needed)
- name: List files
ansible.builtin.shell: ls -la /tmp
# GOOD
- name: List files
ansible.builtin.command: ls -la /tmp
changed_when: false
```
**Missing changed_when:**
```yaml
# BAD (always shows changed)
- name: Check status
ansible.builtin.command: systemctl status app
# GOOD
- name: Check status
ansible.builtin.command: systemctl status app
register: status_check
changed_when: false
failed_when: false
```
## Syntax Checking
Validate playbook syntax before running:
```bash
# Check syntax only
uv run ansible-playbook --syntax-check playbooks/my-playbook.yml
# Check mode (dry run)
uv run ansible-playbook playbooks/my-playbook.yml --check
# Diff mode (show changes)
uv run ansible-playbook playbooks/my-playbook.yml --check --diff
```
## Idempotency Testing
Verify playbooks are idempotent by running twice:
```bash
# First run - may show changes
uv run ansible-playbook playbooks/setup.yml
# Second run - should show 0 changes
uv run ansible-playbook playbooks/setup.yml
# If second run shows changes, playbook is NOT idempotent
```
### Automated Idempotency Check
```bash
#!/bin/bash
set -euo pipefail
PLAYBOOK="$1"
echo "First run..."
uv run ansible-playbook "$PLAYBOOK"
echo "Second run (checking idempotency)..."
OUTPUT=$(uv run ansible-playbook "$PLAYBOOK" 2>&1)
if echo "$OUTPUT" | grep -q "changed=0"; then
echo "✓ Playbook is idempotent"
exit 0
else
echo "✗ Playbook is NOT idempotent"
echo "$OUTPUT" | grep -E "(changed|failed)="
exit 1
fi
```
## Integration Testing
### Test Against Real Infrastructure
```bash
# Limit to test hosts
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts
# With verbose output
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts -vv
```
### Pre-flight Validation
Add validation tasks at playbook start:
```yaml
---
- name: Deploy with validation
hosts: all
become: true
pre_tasks:
- name: Validate target environment
ansible.builtin.assert:
that:
- ansible_distribution == "Debian"
- ansible_distribution_major_version | int >= 11
fail_msg: "Requires Debian 11+"
- name: Check connectivity
ansible.builtin.ping:
- name: Verify disk space
ansible.builtin.assert:
that:
- ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > 1073741824
fail_msg: "Insufficient disk space"
```
## Test Playbook Pattern
Create test playbooks for validation:
```yaml
# playbooks/test-role.yml
---
- name: Test role functionality
hosts: test_hosts
become: true
vars:
test_mode: true
roles:
- role: my_role
tasks:
- name: Verify service is running
ansible.builtin.systemd:
name: myservice
register: service_status
failed_when: service_status.status.ActiveState != "active"
- name: Verify config file exists
ansible.builtin.stat:
path: /etc/myservice/config.yml
register: config_stat
failed_when: not config_stat.stat.exists
- name: Verify port is listening
ansible.builtin.wait_for:
port: 8080
timeout: 10
```
## CI/CD Integration
### GitHub Actions
```yaml
name: Ansible Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
run: pip install uv
- name: Install dependencies
run: uv sync
- name: Run ansible-lint
run: uv run ansible-lint ansible/
```
## Debugging Playbooks
### Verbose Output
```bash
# Increase verbosity
uv run ansible-playbook playbook.yml -v # Basic
uv run ansible-playbook playbook.yml -vv # More detail
uv run ansible-playbook playbook.yml -vvv # Connection debugging
uv run ansible-playbook playbook.yml -vvvv # Maximum detail
```
### Debug Tasks
```yaml
- name: Debug variable value
ansible.builtin.debug:
var: my_variable
- name: Debug with message
ansible.builtin.debug:
msg: "The value is {{ my_variable }}"
- name: Debug registered result
ansible.builtin.debug:
var: command_result
when: ansible_verbosity > 0
```
### Step Mode
```bash
# Pause after each task
uv run ansible-playbook playbook.yml --step
```
## Lint Profiles
Choose appropriate profile based on needs:
| Profile | Strictness | Use Case |
|---------|------------|----------|
| `min` | Lowest | Legacy code, quick fixes |
| `basic` | Low | Development |
| `moderate` | Medium | General infrastructure |
| `safety` | High | Security-sensitive |
| `production` | Highest | Production deployments |
## Additional Resources
For detailed testing patterns and techniques, consult:
- **`references/testing-comprehensive.md`** - ansible-lint configuration, integration testing strategies, CI/CD patterns
## Related Skills
- **ansible-fundamentals** - Core Ansible patterns
- **ansible-idempotency** - Ensuring tasks are idempotent
Related in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.