Mood: Slightly annoyed at CI pipelines 🧨
CI runs shouldn’t feel like molasses. Here’s how I got Ansible to stop downloading the internet. You’re welcome.
Let’s get one thing straight: nobody likes waiting on CI.
Not you. Not me. Not even the coffee you brewed while waiting for Galaxy roles to install — again.
So I said “nope” and made it snappy. Enter: GitHub Actions Cache + Ansible + a generous helping of grit and retries.
🧙♂️ Why cache your Ansible Galaxy installs?
Because time is money, and your CI shouldn’t feel like it’s stuck in dial-up hell.
If you’ve ever screamed internally watching community.general
get re-downloaded for the 73rd time this month — same, buddy, same.
The fix? Cache that madness. Save your roles and collections once, and reuse like a boss.
💾 The basics: caching 101
Here’s the money snippet:
path: .ansible/
key: ansible-deps-${{ hashFiles('requirements.yml') }}
restoreKeys: |
ansible-deps-
🧠 Translation:
- Store everything Ansible installs in
.ansible/
- Cache key changes when
requirements.yml
changes — nice and deterministic - If the exact match doesn’t exist, fall back to the latest vaguely-similar key
Result? Fast pipelines. Happy devs. Fewer rage-tweets.
🔁 Retry like you mean it
Let’s face it: ansible-galaxy
has… moods.
Sometimes Galaxy API is down. Sometimes it’s just bored. So instead of throwing a tantrum, I taught it patience:
for i in {1..5}; do
if ansible-galaxy install -vv -r requirements.yml; then
break
else
echo "Galaxy is being dramatic. Retrying in $((i * 10)) seconds…" >&2
sleep $((i * 10))
fi
done
That’s five retries. With increasing delays.
💬 “You good now, Galaxy? You sure? Because I’ve got YAML to lint.”
⚠️ The catch (a.k.a. cache wars)
Here’s where things get spicy:
actions/cache
only saves when a job finishes successfully.
So if two jobs try to save the exact same cache at the same time?
💥 Boom. Collision. One wins. The other walks away salty:
Unable to reserve cache with key ansible-deps-...,
another job may be creating this cache.
Rude.
🧊 Fix: preload the cache in a separate job
The solution is elegant:
Warm-up job. One that only does Galaxy installs and saves the cache. All your other jobs just consume it. Zero drama. Maximum speed. 💃
🪄 Tempted to symlink instead of copy?
Yeah, I thought about it too.
“But what if we symlink .ansible/
and skip the copy?”
Nah. Not worth the brainpower. Just cache the thing directly.
✅ It works. 🧼 It’s clean. 😌 You sleep better.
🧠 Pro tips
- Use the hash of
requirements.yml
as your cache key. Trust me. - Add a fallback prefix like
ansible-deps-
so you’re never left cold. - Don’t overthink it. Let the cache work for you, not the other way around.
✨ TL;DR
- ✅ GitHub Actions cache = fast pipelines
- ✅ Smart keys based on
requirements.yml
= consistency - ✅ Retry loops = less flakiness
- ✅ Preload job = no more cache collisions
- ❌ Re-downloading Galaxy junk every time = madness
🔥 Go forth and cache like a pro.
Got better tricks? Hit me up on Mastodon and show me your CI magic.
And remember: Friends don’t let friends wait on Galaxy.
💚 Peace, love, and fewer ansible-galaxy
downloads.