501 — Build a DevOps Automation CLI Tool

Advanced

Bring every pattern from Modules 1–4 together in a single production-quality tool: devops-report, a command-line program that queries the GitHub REST API, formats results as JSON or YAML, writes a report to disk or stdout using pathlib, and handles errors with meaningful exit codes and structured logging. Each step builds one integration layer — argparse, token loading, API calls, report assembly, formatting, and output routing — before the final step assembles everything into devops-report.py: a complete runnable CLI that integrates venv, argparse, logging, exit codes, pathlib, os.environ, requests, Bearer auth, json.dumps, yaml.dump, and python-dotenv.

Learning Objectives

1
Install and verify all project dependencies in lesson-501 and confirm requests, PyYAML, and python-dotenv are available
2
Define the devops-report CLI interface with argparse: --org, --repo, --format, --output, and --verbose flags
3
Load GITHUB_TOKEN from .env with load_dotenv() and implement a fail-fast validation check that exits before any network calls when the token is missing
4
Fetch repository metadata from the GitHub REST API — open_issues_count, default_branch, description — using requests with Bearer token auth and timeout=10
5
Retrieve the last 5 commits from the GitHub REST API and extract sha, first-line message, author name, and date
6
Assemble the report dict from API responses and add a UTC timestamp using datetime.datetime.now(datetime.timezone.utc)
7
Format the report as JSON with json.dumps or YAML with yaml.dump, then route output to a file via pathlib or to stdout
8
Build devops-report.py: a complete CLI that integrates all Module 1–4 patterns with structured logging, HTTPError/Timeout/ConnectionError handling, and sys.exit(1) on API failure
Step 1

Set up the lesson directory and install dependencies

Create the lesson-501 working directory, copy .env and .gitignore from lesson 404, and confirm that all three third-party packages the tool needs — requests, PyYAML, and python-dotenv — are installed and importable alongside the stdlib modules.

Commands to Run

mkdir -p ~/devops-python/lesson-501
cd ~/devops-python/lesson-501
source ~/devops-python/lesson-101/devops-env/bin/activate
cp ~/devops-python/lesson-404/.env ~/devops-python/lesson-501/.env
cp ~/devops-python/lesson-404/.gitignore ~/devops-python/lesson-501/.gitignore
pip install requests PyYAML python-dotenv
pip show requests PyYAML python-dotenv | grep '^Name\|^Version'
python3 -c "import requests, yaml, datetime, pathlib, json, logging, argparse; from dotenv import load_dotenv; print('All imports OK'); print('  requests', requests.__version__); print('  PyYAML', yaml.__version__)"

What This Does

All three packages were installed in earlier lessons (requests in 401, PyYAML in 302, python-dotenv in 303), so pip install will print 'Requirement already satisfied' for each.

Running the command again is idempotent and confirms the exact installed versions.

The import check at the end verifies that requests, PyYAML, python-dotenv, datetime, pathlib, json, logging, and argparse are all importable in the devops-env virtualenv — all eight are needed in devops-report.py.

Lesson 402 introduced GITHUB_TOKEN as the standard credential env var; lesson 404 inherits that .env from lesson 403 and then appends WEBHOOK_SECRET.

Copying .env from lesson 404 is therefore safe: it already contains GITHUB_TOKEN, and devops-report.py simply ignores WEBHOOK_SECRET.

Only GITHUB_TOKEN is used in this lesson.

Expected Outcome

pip install prints 'Requirement already satisfied' for requests, PyYAML, and python-dotenv. pip show lists Name and Version for all three — expect requests 2.x, PyYAML 6.x, python-dotenv 1.x.

The import check prints 'All imports OK' followed by the requests and PyYAML version numbers — no ImportError.

Pro Tips

  • 1
    If pip show shows requests below 2.31, upgrade with: pip install 'requests>=2.31'. The API calls in this lesson work with any 2.x release, but 2.31+ includes security backports.
  • 2
    Keeping all lesson directories self-contained with their own .env copies makes it easy to set different environment variables per lesson without affecting earlier work.

Common Mistakes to Avoid

  • ⚠️Forgetting to activate the virtual environment — if devops-env is not active, 'import requests' raises ModuleNotFoundError even though it is installed in the venv. Always run 'source ~/devops-python/lesson-101/devops-env/bin/activate' first.
  • ⚠️Assuming lesson 404's .env is incompatible with lesson 501 — lesson 404 inherits GITHUB_TOKEN from lesson 403 and then adds WEBHOOK_SECRET. Copying it is safe; devops-report.py ignores WEBHOOK_SECRET and uses only GITHUB_TOKEN.
Was this step helpful?

All Steps (0 / 8 completed)