Automation & DevOps Capstone Projects
A complete price monitoring engine that parses product pages, compares current prices against user alert thresholds, and triggers notifications on price drops:
# =========================================================================
# PROJECT 1: AUTOMATED PRICE DROP SCRAPER & ALERT ENGINE
# =========================================================================
class PriceDropMonitor:
"""Monitors product prices and triggers alerts when price drops below threshold."""
def __init__(self):
self.watchlist = {} # {product_id: {"name": str, "target_price": float, "last_price": float}}
def add_to_watchlist(self, product_id, name, target_price, initial_price):
self.watchlist[product_id] = {
"name": name,
"target_price": target_price,
"last_price": initial_price
}
print(f"๐ฏ Watchlist Added: '{name}' | Target Alert Price: โน{target_price:,.2f}")
def check_price_update(self, product_id, current_scraped_price):
item = self.watchlist.get(product_id)
if not item:
return "Product not found in watchlist."
old_price = item["last_price"]
item["last_price"] = current_scraped_price
if current_scraped_price <= item["target_price"]:
discount = old_price - current_scraped_price
return (
f"๐จ [PRICE DROP ALERT!] '{item['name']}' dropped to โน{current_scraped_price:,.2f}! "
f"(Target: โน{item['target_price']:,.2f} | Saved: โน{discount:,.2f})"
)
return f"โน๏ธ '{item['name']}' price is โน{current_scraped_price:,.2f} (Above target โน{item['target_price']:,.2f})"
# Run Project 1 Demonstration:
monitor = PriceDropMonitor()
monitor.add_to_watchlist("PROD-1", "Sony WH-1000XM5 Headphones", target_price=24999.0, initial_price=29999.0)
monitor.add_to_watchlist("PROD-2", "MacBook Air M3", target_price=95000.0, initial_price=114900.0)
# Simulate Daily Price Scraping Checks:
print("\n--- ๐ก Simulating Daily Automated Price Checks ---")
print(monitor.check_price_update("PROD-1", 27999.0)) # Above target
print(monitor.check_price_update("PROD-1", 23499.0)) # Drops below target! ALERTS!
print(monitor.check_price_update("PROD-2", 94000.0)) # Drops below target! ALERTS!
In production, combine this monitor with the schedule library to run every morning at 08:00 AM and send alerts via Telegram/WhatsApp APIs.
An automated accounting engine generating structured invoices and financial summaries with tax computations:
# =========================================================================
# PROJECT 2: AUTOMATED INVOICE & FINANCIAL REPORT ENGINE
# =========================================================================
class InvoiceEngine:
def __init__(self, company_name="Our Compiler Tech Solutions"):
self.company = company_name
def generate_invoice(self, invoice_num, client_name, line_items):
"""Generates detailed invoice breakdown: line_items = [(desc, qty, unit_price)]"""
subtotal = 0.0
details = []
for desc, qty, price in line_items:
line_total = qty * price
subtotal += line_total
details.append(f" โข {desc:32} (Qty: {qty:>2} x โน{price:>8,.2f}) = โน{line_total:>10,.2f}")
gst = subtotal * 0.18 # 18% GST
grand_total = subtotal + gst
invoice_text = [
f"======================================================================",
f" TAX INVOICE: {self.company.upper()}",
f" Invoice Number: {invoice_num:<20} Date: 2026-08-14",
f" Billed To: {client_name}",
f"----------------------------------------------------------------------",
*details,
f"----------------------------------------------------------------------",
f" Subtotal: โน{subtotal:>10,.2f}",
f" Applicable GST (18%): โน{gst:>10,.2f}",
f" GRAND TOTAL PAYABLE: โน{grand_total:>10,.2f}",
f"======================================================================"
]
return "\n".join(invoice_text)
# Run Project 2 Demonstration:
engine = InvoiceEngine()
inv = engine.generate_invoice(
invoice_num="INV-2026-0042",
client_name="Tata Consultancy Services",
line_items=[
("Python Masterclass Corporate Licenses", 25, 4999.0),
("FastAPI Backend Microservice Consulting", 10, 8500.0),
("Dedicated Cloud Server Provisioning", 1, 15000.0)
]
)
print(inv)
Formats currencies and itemized line items with dynamic tax calculations, ready for PDF export or email delivery.
An automated file manager that scans directories, classifies file types, and records actions in an audit log:
# =========================================================================
# PROJECT 3: INTELLIGENT FILE ORGANIZER WITH AUDIT LOGGING
# =========================================================================
class SmartFolderOrganizer:
CATEGORIES = {
"Documents": [".pdf", ".docx", ".xlsx", ".txt"],
"Images": [".png", ".jpg", ".jpeg", ".svg"],
"Code": [".py", ".js", ".html", ".css"],
"Archives": [".zip", ".tar", ".gz"]
}
def __init__(self):
self.audit_log = []
def organize_files(self, file_list):
for filename in file_list:
ext = "." + filename.split(".")[-1].lower() if "." in filename else ""
target_folder = "Others"
for folder, extensions in self.CATEGORIES.items():
if ext in extensions:
target_folder = folder
break
action_record = f"[SORTED] '{filename}' โโโบ ๐ [{target_folder}/]"
self.audit_log.append(action_record)
print(f"โข {action_record}")
# Run Project 3 Demonstration:
organizer = SmartFolderOrganizer()
print("--- ๐ Organizing Cluttered Downloads Directory ---")
organizer.organize_files([
"Q3_Financial_Report.pdf",
"dashboard_mockup.png",
"api_backend_server.py",
"dataset_customers.xlsx",
"system_backup.zip"
])
print(f"\nโ
Successfully organized {len(organizer.audit_log)} files with zero errors!")
Maintains an internal log of every moved file to support audit checks and undo functionality.
A batch email sending engine with templating, personalized placeholders, and dispatch delays:
# =========================================================================
# PROJECT 4: AUTOMATED BATCH EMAIL DISPATCHER
# =========================================================================
class BatchEmailDispatcher:
def __init__(self, sender="newsletter@ourcompiler.com"):
self.sender = sender
self.sent_count = 0
def send_newsletter(self, subscribers, template):
print(f"--- ๐ง Starting Newsletter Dispatch to {len(subscribers)} Subscribers ---")
for sub in subscribers:
personalized_body = template.replace("{{name}}", sub["name"]).replace("{{topic}}", sub["interest"])
print(f"๐จ Sent to: {sub['email']:26} | Subject: 'Weekly {sub['interest']} Digest'")
self.sent_count += 1
print(f"โ
Batch completed: {self.sent_count} emails delivered successfully.")
# Run Project 4 Demonstration:
dispatcher = BatchEmailDispatcher()
subscribers_list = [
{"name": "Balaji", "email": "balaji@example.com", "interest": "Python & AI"},
{"name": "Alex", "email": "alex@example.com", "interest": "Cloud & DevOps"},
{"name": "Chloe", "email": "chloe@example.com", "interest": "Data Science"}
]
email_template = "Hi {{name}}, here is your top curated {{topic}} tutorial of the week!"
dispatcher.send_newsletter(subscribers_list, email_template)
Demonstrates dynamic token replacement for personalized email campaigns.
A complete production-ready Docker container and GitHub Actions continuous integration workflow:
# =========================================================================
# PROJECT 5: PRODUCTION DOCKERFILE & CI/CD PIPELINE BLUEPRINT
# =========================================================================
dockerfile_content = """
# 1. Multi-Stage Production Dockerfile for Python Web App:
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# Final Lean Production Image:
FROM python:3.12-slim AS runner
WORKDIR /app
# Copy installed wheels from builder:
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
CMD ["gunicorn", "my_project.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]
"""
github_actions_ci = """
# 2. GitHub Actions Automated Testing & Linting CI Workflow (.github/workflows/ci.yml)
name: Python Application CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install ruff pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run Ruff Linter & Formatter Check
run: ruff check .
- name: Run Automated Pytest Suite
run: pytest --maxfail=1 --disable-warnings -q
"""
print("--- ๐ณ Production Dockerfile Configuration ---")
print(dockerfile_content.strip())
print("\n--- ๐ GitHub Actions Automated CI Pipeline ---")
print(github_actions_ci.strip())
Using a multi-stage Docker build leaves compilers and temporary build artifacts behind, reducing container image size from ~800 MB to under 95 MB!
Running application processes as root inside Docker creates severe container-breakout security vulnerabilities. Always define and switch to a non-root user (USER appuser) in your Dockerfile.
Instantiate PriceDropMonitor from Project 1 and check if a price update to โน89,999 triggers an alert for a product with target โน90,000.
monitor = PriceDropMonitor()
monitor.add_to_watchlist("P1", "Gaming Laptop", target_price=90000, initial_price=105000)
alert = monitor.check_price_update("P1", 89999)
print(alert)
Q What is CI/CD in modern software engineering?
CI (Continuous Integration) automatically runs tests and linters whenever developers push code. CD (Continuous Deployment) automatically packages and deploys passing code to production servers.
Q Why should I use Gunicorn inside Docker instead of running Python directly?
Gunicorn manages a master process with multiple worker processes, handling concurrency, automatic worker recycling on memory leaks, and high-throughput network connections.
Q What is the purpose of PYTHONUNBUFFERED=1 in Docker containers?
PYTHONUNBUFFERED=1 ensures Python output (logs and stdout) is sent directly to terminal streams without buffer delays, allowing real-time log monitoring in Docker and Kubernetes.