Here at ClueTrust we have been using Ansible for several years now.
For a variety of reasons, we look at a lot of our Ansible development work through the lens of pushing everyhing possible into reusable libraries (roles), each with its own repo, and leveraging ansible-galaxy pointed at our own repos, to pull in dependencies on an as-needed basis. That leaves us with thin playbooks (in their own repos) to build similar sets of hosts - inventory directory hierarchies that contain playbooks that set variables and call roles (and may contain a few vaulted host-specific files such as ssh keys and x.509 certs) but have minimal or no tasks sections since all that has been pushed out to reusable roles.
Between Gaige and me, we have over 70 Ansible role Git repos. This approach has worked out very well for us. We are a small shop and don't suffer from a cohort of recalcitrant developers tugging us towards dependency hell (intentionally breaking their stuff in real time so they have to fix it is an oft-touted feature of monorepos).
I recently created a couple of roles that were failing when I ran
ansible-galaxy install -r requirements.yml. I looked them over, scratched my head...
- extracting splunk-forwarder-smartos to /tmp/ansibleroles/splunk-forwarder-smartos [WARNING]: - splunk-forwarder-smartos was NOT installed successfully: Could not update files in /tmp/ansibleroles/splunk-forwarder-smartos: [Errno 21] Is a directory: '/tmp/ansibleroles/splunk- forwarder-smartos/tasks' ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.
I couldn't figure out what was going on, and -vvvvv was no help.
Eventually the solution came out - kudos to Gaige for flagging this
one. I'm an Emacs user. Emacs saves the old version of a file as
filename~ - a relic of bygone days and influenced by operating
systems that had versioned filenames.
That ~ in the filename was giving the archiver library heartburn in a bad way - because I had neglected to add my standard .gitignore file for Ansible work (which by the way looks like this):
*~ *.retry __pycache__ *.pyc
Fortunately it only had a single commit, so a do-over with the right .gitignore file in place and then a force push was enough to set things right.