Ansible in CI/CD

Lint, check mode, and safe automation.

Advanced12 min · lesson 12 of 12

Running Ansible from CI turns infrastructure change into reviewed, repeatable automation, and the pipeline mirrors other IaC: lint and syntax-check on a pull request, run in check mode to preview changes, and apply on merge to the target environment. ansible-lint enforces best practices and catches the shell-instead-of-module and missing-name smells before they reach a host.

ANSIBLE IN A CI/CD PIPELINE
1Pull request
ansible-lint + --syntax-check
2Check mode
--check --diff previews changes
3Merge to main
reviewed change approved
4Apply
manual approval for production
Lint and dry-run on every PR give reviewers a concrete plan before anything reaches a host.
.gitlab-ci.yml
lint:
script:
- ansible-lint site.yml
- ansible-playbook --syntax-check site.yml
check:
script:
- ansible-playbook -i inventory site.yml --check --diff # dry run + show diffs
apply:
script: [ansible-playbook -i inventory site.yml]
rules: [{ if: '$CI_COMMIT_BRANCH == "main"' }]
when: manual # approval for prod
environment: production

Check mode and diff

--check runs the play without making changes and reports what would change; --diff shows the actual before/after of files it would modify. Together they are your safe preview — the closest Ansible has to a plan — and running them on every PR gives reviewers a concrete picture of the change. Not every module supports check mode perfectly, so treat it as a strong signal, not an absolute guarantee.

CI holds SSH and Vault access — harden the runner
An Ansible CI job carries the SSH keys and Vault password to change your whole fleet, making the runner a top-tier target. Pull those secrets from the CI secret store (or a real vault) at run time rather than baking them into the image, scope the SSH credential to what the job needs, gate prod applies behind approval, and isolate the runner — the pipeline that configures production deserves the CI/CD course’s full hardening.