10 Ready‑to‑Use Automation Scripts That Cut Release Time in Half for Small DevOps Teams
When you’re juggling on‑call alerts, a flaky pipeline, and a sprint deadline, every minute you save feels like a win. Small teams especially feel the pressure – you don’t have a dozen engineers to hand‑off tasks, so the right script can be the difference between a smooth release and a midnight fire‑fight.
Below are ten scripts I’ve used (and tweaked) over the past three years at a handful of startups. They are deliberately simple, require only common tools, and can be dropped into a repo today. I’ll walk through what each does, why it matters, and a quick example you can copy‑paste.
1. Git Tag & Changelog Generator
Why it matters – Tagging a commit and producing a changelog is a manual step that often slips. Missing a tag means you can’t trace a release later, and a handwritten changelog invites typos.
The script (bash, assumes git and awk are installed):
#!/usr/bin/env bash
set -e
# Get the next version number from the last tag
last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
IFS='.' read -r major minor patch <<<"${last_tag#v}"
new_patch=$((patch+1))
new_tag="v$major.$minor.$new_patch"
# Create the tag
git tag -a "$new_tag" -m "Release $new_tag"
git push origin "$new_tag"
# Generate a simple changelog from commits since last tag
git log "$last_tag"..HEAD --pretty=format:"- %s" > CHANGELOG.md
git add CHANGELOG.md
git commit -m "Update changelog for $new_tag"
git push
Drop this into your CI step right after a successful build. One run, and you have a proper tag and a fresh CHANGELOG.md.
2. Docker Image Builder with Cache Warm‑up
Why it matters – Building Docker images from scratch on every pipeline run wastes time and money. Warming the cache with a “builder” stage speeds things up dramatically.
The script (bash, uses Docker CLI):
#!/usr/bin/env bash
set -e
IMAGE_NAME="myapp"
CACHE_IMAGE="${IMAGE_NAME}:cache"
# Pull the cache image if it exists
docker pull "$CACHE_IMAGE" || true
# Build using the cache image as a base for layer reuse
docker build \
--cache-from "$CACHE_IMAGE" \
-t "${IMAGE_NAME}:latest" \
-t "$CACHE_IMAGE" \
.
# Push the new cache image for the next run
docker push "$CACHE_IMAGE"
Run this in your CI after tests. The first build will be slower, but every subsequent run reuses the cached layers, shaving off 30‑40% of build time.
3. Kubernetes Rollout Checker
Why it matters – A deployment may report “rolled out” while some pods are still initializing. A quick check that all pods are ready avoids premature traffic shift.
The script (bash, uses kubectl):
#!/usr/bin/env bash
set -e
NAMESPACE="${1:-default}"
DEPLOYMENT="${2:?deployment name required}"
# Wait for rollout to finish
kubectl rollout status deployment/"$DEPLOYMENT" -n "$NAMESPACE" --timeout=120s
# Verify all pods are ready
while true; do
not_ready=$(kubectl get pods -n "$NAMESPACE" -l app="$DEPLOYMENT" \
-o jsonpath='{.items[*].status.containerStatuses[*].ready}' | grep -c false)
if [ "$not_ready" -eq 0 ]; then
echo "All pods ready."
break
fi
echo "Waiting for pods to become ready..."
sleep 5
done
Add this after you apply your manifests. If anything hangs, the script exits with a non‑zero code, causing the pipeline to fail early.
4. Slack Notification on Pipeline Status
Why it matters – Teams spend time checking CI dashboards. A quick Slack ping tells everyone if the build succeeded or blew up.
The script (bash, requires curl and a Slack webhook URL):
#!/usr/bin/env bash
set -e
STATUS="${1:?success|failure}"
WEBHOOK_URL="${SLACK_WEBHOOK_URL:?set env var}"
MESSAGE=":white_check_mark: Build succeeded"
[ "$STATUS" = "failure" ] && MESSAGE=":x: Build failed"
payload=$(cat <<EOF
{
"text": "$MESSAGE",
"username": "CI Bot",
"icon_emoji": ":gear:"
}
EOF
)
curl -s -X POST -H 'Content-type: application/json' --data "$payload" "$WEBHOOK_URL"
Call it with success or failure at the end of your pipeline. The script is tiny, but the morale boost of a green check in Slack is real.
5. Secrets Sync from Vault
Why it matters – Hard‑coding secrets in config files is a recipe for leaks. Pulling them at runtime keeps them out of source control.
The script (bash, uses vault CLI):
#!/usr/bin/env bash
set -e
VAULT_PATH="${1:?vault secret path}"
DEST_FILE="${2:-.env}"
# Authenticate (assumes VAULT_TOKEN env var is set)
vault kv get -format=json "$VAULT_PATH" | \
jq -r '.data.data | to_entries[] | "\(.key)=\(.value)"' > "$DEST_FILE"
echo "Secrets written to $DEST_FILE"
Run this as a pre‑step before your container starts. The generated .env can be sourced by your app without ever touching the repo.
6. Automated Rollback Script
Why it matters – When a new release breaks something, you need to revert fast. Manual rollbacks are error‑prone.
The script (bash, uses kubectl):
#!/usr/bin/env bash
set -e
NAMESPACE="${1:-default}"
DEPLOYMENT="${2:?deployment name}"
# Get the previous revision number
REV=$(kubectl rollout history deployment/"$DEPLOYMENT" -n "$NAMESPACE" \
| tail -n +2 | awk 'NR==2 {print $1}')
if [ -z "$REV" ]; then
echo "No previous revision found."
exit 1
fi
echo "Rolling back $DEPLOYMENT to revision $REV"
kubectl rollout undo deployment/"$DEPLOYMENT" -n "$NAMESPACE" --to-revision="$REV"
Add this as a manual step in your CI/CD UI. One click and you’re back to the last known good state.
7. Dependency Update Bot
Why it matters – Out‑of‑date libraries are a security risk, but scanning them manually is tedious.
The script (Python, works for requirements.txt):
#!/usr/bin/env python3
import subprocess, sys, re
def latest_version(pkg):
out = subprocess.check_output(
["pip", "index", "versions", pkg], text=True
)
match = re.search(r'Available versions: ([\d.,]+)', out)
return match.group(1).split(',')[0].strip() if match else None
def main():
with open('requirements.txt') as f:
lines = f.readlines()
updated = []
for line in lines:
if '==' not in line:
updated.append(line)
continue
pkg, cur = line.strip().split('==')
latest = latest_version(pkg)
if latest and latest != cur:
updated.append(f"{pkg}=={latest}\n")
print(f"{pkg}: {cur} -> {latest}")
else:
updated.append(line)
with open('requirements.txt', 'w') as f:
f.writelines(updated)
if __name__ == "__main__":
main()
Run this nightly. If any package gets a newer version, the script updates the file and prints a quick diff. Pair it with a PR job and you’ve automated the boring part of dependency hygiene.
8. Test Result Aggregator
Why it matters – Unit, integration, and UI tests often run in separate jobs. Collating their results into a single report helps you see the big picture.
The script (bash, assumes JUnit XML files):
#!/usr/bin/env bash
set -e
REPORT_DIR="${1:-test-reports}"
AGGREGATE="aggregate-report.xml"
# Simple concatenation of test suites
echo '<?xml version="1.0" encoding="UTF-8"?><testsuites>' > "$AGGREGATE"
for file in "$REPORT_DIR"/*.xml; do
sed -n '/<testsuite/,/<\/testsuite>/p' "$file" >> "$AGGREGATE"
done
echo '</testsuites>' >> "$AGGREGATE"
echo "Aggregated report written to $AGGREGATE"
Upload aggregate-report.xml to your CI dashboard for a single pass/fail badge.
9. Infrastructure Drift Detector
Why it matters – Over time, manual tweaks to cloud resources cause drift from the declared IaC state. Detecting drift early avoids surprise costs.
The script (bash, uses terraform):
#!/usr/bin/env bash
set -e
TF_DIR="${1:-infra}"
cd "$TF_DIR"
terraform init -input=false
terraform plan -detailed-exitcode -out=plan.out
code=$?
if [ $code -eq 2 ]; then
echo "Drift detected! Run 'terraform apply' to reconcile."
exit 1
elif [ $code -eq 0 ]; then
echo "No drift. Infrastructure matches code."
else
echo "Terraform error."
exit $code
fi
Add this as a nightly job. If the script exits with code 1, your pipeline fails and you know something changed outside of Terraform.
10. Release Notes Emailer
Why it matters – Stakeholders love a concise email that lists what’s new. Manually drafting it after each release wastes time.
The script (bash, uses mailx):
#!/usr/bin/env bash
set -e
VERSION="${1:?release version}"
RECIPIENTS="${2:[email protected]}"
CHANGELOG="CHANGELOG.md"
if [ ! -f "$CHANGELOG" ]; then
echo "Changelog not found."
exit 1
fi
SUBJECT="Release $VERSION – Summary"
BODY=$(sed -n "/^## $VERSION$/,/^## /p" "$CHANGELOG" | head -n -1)
echo -e "Subject: $SUBJECT\n\n$BODY" | mailx -s "$SUBJECT" "$RECIPIENTS"
echo "Release notes emailed to $RECIPIENTS"
Run this right after your tag script. The email pulls the section for the new version from CHANGELOG.md, so you never have to copy‑paste again.
These ten scripts are not a silver bullet, but they are the kind of low‑friction tools that let a five‑person team move at the speed of a larger org. I’ve seen release cycles shrink from three days to under twelve hours simply by wiring these pieces together.
Give one a try today, and you’ll feel the difference the next time you push to production. Happy automating!
- → Productivity Hacks for Developers: Automating Repetitive Tasks with Scripts @techtalktoday
- → How to Choose the Right Industrial Indicator Light for Hazardous Environments @indicatorinsight
- → Build a Low‑Cost Autonomous Delivery Robot for Your Home in 7 Simple Steps @robofrontier
- → A Step-by‑by‑Step Guide to Selecting the Right Linear Brake for High‑Speed Automation @linearbrakehub
- → Designing a Fail‑Safe Brake System for Automated Production Lines: Best Practices and Safety Checklist @industrialbrakes