From bc26e6c96d31e2327d953e12dd867c8960e08434 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Sun, 25 Jan 2026 19:21:18 +0300 Subject: [PATCH 01/33] feat: implement lab01 devops info service --- app_python/.gitignore | 12 + app_python/README.md | 41 +++ app_python/app.py | 162 +++++++++ app_python/docs/LAB01.md | 341 ++++++++++++++++++ .../docs/screenshots/01-main-endpoint.png | Bin 0 -> 45712 bytes .../docs/screenshots/02-health-check.png | Bin 0 -> 11296 bytes .../docs/screenshots/03-formatted-output.png | Bin 0 -> 55725 bytes app_python/requirements.txt | 2 + app_python/tests/__init__.py | 0 9 files changed, 558 insertions(+) create mode 100644 app_python/.gitignore create mode 100644 app_python/README.md create mode 100644 app_python/app.py create mode 100644 app_python/docs/LAB01.md create mode 100644 app_python/docs/screenshots/01-main-endpoint.png create mode 100644 app_python/docs/screenshots/02-health-check.png create mode 100644 app_python/docs/screenshots/03-formatted-output.png create mode 100644 app_python/requirements.txt create mode 100644 app_python/tests/__init__.py diff --git a/app_python/.gitignore b/app_python/.gitignore new file mode 100644 index 0000000000..4de420a8f7 --- /dev/null +++ b/app_python/.gitignore @@ -0,0 +1,12 @@ +# Python +__pycache__/ +*.py[cod] +venv/ +*.log + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store \ No newline at end of file diff --git a/app_python/README.md b/app_python/README.md new file mode 100644 index 0000000000..32d32ac023 --- /dev/null +++ b/app_python/README.md @@ -0,0 +1,41 @@ +# devops-info-service + +## Overview +`devops-info-service` is a lightweight HTTP service built with **FastAPI** that returns comprehensive runtime and system information. It exposes: +- service metadata (name, version, description, framework), +- system details (hostname, OS/platform, architecture, CPU count, Python version), +- runtime data (uptime, current UTC time), +- request details (client IP, user-agent, method, path), +- a list of available endpoints. + +## Prerequisites +- **Python:** 3.10+ (recommended 3.11+) +- **Dependencies:** listed in `requirements.txt` + +## Installation + +``` +python -m venv venv +source venv/bin/activate +pip install -r requirements.txt +``` + +## Running the Application +``` +python app.py +# Or with custom config +PORT=8080 python app.py +``` + +## API Endpoints +- `GET /` - Service and system information +- `GET /health` - Health check + +## Configuration + +The application is configured using environment variables. + +| Variable | Default | Description | Example | +|---------|---------|-------------|---------| +| `HOST` | `127.0.0.1` | Host interface to bind the server to | `0.0.0.0` | +| `PORT` | `8000` | Port the server listens on | `8080` | \ No newline at end of file diff --git a/app_python/app.py b/app_python/app.py new file mode 100644 index 0000000000..a1e16fe273 --- /dev/null +++ b/app_python/app.py @@ -0,0 +1,162 @@ +""" +DevOps Info Service +Main application module +""" +import logging +import os +import platform +import socket +from datetime import datetime, timezone + +import uvicorn +from fastapi import FastAPI, Request, status +from fastapi.responses import JSONResponse +from starlette.exceptions import HTTPException + +app = FastAPI() + +# Configuration +HOST = os.getenv("HOST", "0.0.0.0") +PORT = int(os.getenv("PORT", 5000)) +DEBUG = os.getenv("DEBUG", "False").lower() == "true" + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +# Application start time +start_time = datetime.now() + + +def get_service_info(): + """Get information about service.""" + logger.debug('Getting info about the service.') + return { + "name": "devops-info-service", + "version": "1.0.0", + "description": "DevOps course info service", + "framework": "FastAPI", + } + + +def get_system_info(): + """Get information about system.""" + logger.debug('Getting info about the system.') + return { + "hostname": socket.gethostname(), + "platform": platform.system(), + "platformVersion": platform.version(), + "architecture": platform.machine(), + "cpu_count": os.cpu_count(), + "python_version": platform.python_version(), + } + + +def get_uptime(): + """Get uptime.""" + logger.debug('Getting uptime.') + delta = datetime.now() - start_time + seconds = int(delta.total_seconds()) + hours = seconds // 3600 + minutes = (seconds % 3600) // 60 + return {"seconds": seconds, "human": f"{hours} hours, {minutes} minutes"} + + +def get_runtime_info(): + """Get information about runtime.""" + logger.debug('Getting runtime info.') + uptime = get_uptime() + uptime_seconds, uptime_human = uptime["seconds"], uptime["human"] + current_time = datetime.now(timezone.utc) + + return { + "uptime_seconds": uptime_seconds, + "uptime_human": uptime_human, + "current_time": current_time, + "timezone": "UTC", + } + + +def get_request_info(request: Request): + """Get information about request.""" + logger.debug('Getting info about request.') + return { + "client_ip": request.client.host, + "user_agent": request.headers.get("user-agent"), + "method": request.method, + "path": request.url.path, + } + + +def get_endpoints(): + """Get all existing ednpoints.""" + logger.debug('Getting list of all endpoints.') + return [ + {"path": "/", "method": "GET", "description": "Service information"}, + {"path": "/health", "method": "GET", "description": "Health check"}, + ] + + +@app.get("/", status_code=status.HTTP_200_OK) +async def root(request: Request): + """Main endpoint - service and system information.""" + logger.debug(f'Request: {request.method} {request.url.path}') + return { + "service": get_service_info(), + "system": get_system_info(), + "runtime": get_runtime_info(), + "request": get_request_info(request), + "endpoints": get_endpoints(), + } + + +@app.get("/health", status_code=status.HTTP_200_OK) +async def health(request: Request): + """Endpoint to check health.""" + logger.debug(f'Request: {request.method} {request.url.path}') + return { + "status": "healthy", + "timestamp": datetime.now(timezone.utc), + "uptime_seconds": get_uptime()["seconds"], + } + + +@app.exception_handler(HTTPException) +async def http_exception_handler(request: Request, exc: HTTPException): + """Exception 404 (Not found) that endpoint does not exists.""" + if exc.status_code == 404: + return JSONResponse( + status_code=404, + content={ + "error": "Not Found", + "message": "Endpoint does not exist", + }, + ) + return JSONResponse( + status_code=exc.status_code, + content={ + "error": "HTTP Error", + "message": exc.detail if exc.detail else "Request failed", + }, + ) + + +@app.exception_handler(Exception) +async def unhandled_exception_handler(request: Request, exc: Exception): + """Exception 500 (Internal Server Error) - For any unhandled errors.""" + return JSONResponse( + status_code=500, + content={ + "error": "Internal Server Error", + "message": "An unexpected error occurred", + }, + ) + + +if __name__ == "__main__": + """The entry point.""" + logger.info('Application starting...') + + uvicorn.run("app:app", host=HOST, port=PORT, reload=True) diff --git a/app_python/docs/LAB01.md b/app_python/docs/LAB01.md new file mode 100644 index 0000000000..3c073f4777 --- /dev/null +++ b/app_python/docs/LAB01.md @@ -0,0 +1,341 @@ +# 1. Framework selection. +## Choice +I have chose FastAPI because I have had an experience with it and have no experience with other frameworks. + +## Comparison with Alternatives + +| Criteria | FastAPI (chosen) | Flask | Django (DRF) | +|---------|-----------------|-------|--------------| +| Primary use | APIs / microservices | Lightweight web apps & APIs | Full-stack apps & large APIs | +| Performance model | ASGI (async-ready) | WSGI (sync by default) | WSGI/ASGI (heavier stack) | +| Built-in API docs | Yes (Swagger/OpenAPI) | No (manual/add-ons) | Yes (via DRF) | +| Validation / typing | Strong (type hints + Pydantic) | Manual or extensions | Strong (serializers) | +| Boilerplate | Low | Very low | Higher | +| Learning curve | Low–medium | Low | Medium–high | +| Best fit for this lab | Excellent | Good | Overkill | + +--- + +# 2. Best Practices Applied +## Clean Code Organization + +### 1) Clear Function Names +The code uses descriptive, intention-revealing function names that clearly communicate what each block returns: + +```python +def get_service_info(): + """Get information about service.""" + ... + +def get_system_info(): + """Get information about system.""" + ... + +def get_runtime_info(): + """Get information about runtime.""" + ... + +def get_request_info(request: Request): + """Get information about request.""" + ... +``` +**Why it matters**: Clear naming improves readability, reduces the need for extra comments, and makes the code easier to maintain and extend. + +### 2) Proper imports grouping +Imports are organized by category (standard library first, then third-party libraries), which is the common Python convention: +```python +import logging +import os +import platform +import socket +from datetime import datetime, timezone + +import uvicorn +from fastapi import FastAPI, Request, status +from fastapi.responses import JSONResponse +from starlette.exceptions import HTTPException +``` +**Why it matters**: Grouped imports make dependencies easier to understand at a glance, help keep the file structured, and align with typical linting rules. + +### 3) Comments only where needed +Instead of excessive inline comments, the code relies on clear names and short docstrings: +```python +""" +DevOps Info Service +Main application module +""" + +def get_uptime(): + """Get uptime.""" + ... +``` +**Why it matters**: Too many comments can become outdated. Minimal documentation plus clean naming keeps the codebase readable and accurate. + +### 4) Follow PEP 8 +The implementation follows common PEP 8 practices: +- consistent indentation and spacing, +- snake_case for variables and function names, +- configuration/constants placed near the top of the module (HOST, PORT, DEBUG), +- readable multi-line formatting for long calls: +```python +""" +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) +``` +**Why it matters**: PEP 8 improves consistency, supports teamwork, and makes the code compatible with linters/formatters such as `flake8`, `ruff`, and `black`. + +## Error Handling +The service implements centralized error handling using FastAPI/Starlette exception handlers. This ensures that errors are returned in a consistent JSON format and that clients receive meaningful messages instead of raw stack traces. + +### HTTP errors (e.g., 404 Not Found) +A dedicated handler processes HTTP-related exceptions and customizes the response for missing endpoints. + +```python +from starlette.exceptions import HTTPException + +@app.exception_handler(HTTPException) +async def http_exception_handler(request: Request, exc: HTTPException): + if exc.status_code == 404: + return JSONResponse( + status_code=404, + content={ + "error": "Not Found", + "message": "Endpoint does not exist", + }, + ) + + return JSONResponse( + status_code=exc.status_code, + content={ + "error": "HTTP Error", + "message": exc.detail if exc.detail else "Request failed", + }, + ) +``` +**Why it matters**: +- Provides a clear and user-friendly message for invalid routes. +- Keeps error responses consistent across the API. +- Avoids exposing internal implementation details to the client. + +### Unhandled exceptions (500 Internal Server Error) +A global handler catches any unexpected exceptions and returns a safe, standardized response. + +```python +@app.exception_handler(Exception) +async def unhandled_exception_handler(request: Request, exc: Exception): + return JSONResponse( + status_code=500, + content={ + "error": "Internal Server Error", + "message": "An unexpected error occurred", + }, + ) +``` +**Why it matters**: +- Prevents server crashes from unhandled errors. +- Ensures clients always receive valid JSON (important for automation/scripts). +- Helps keep production behavior predictable while preserving the option to log the exception internally. + +## 3. Logging +The service includes basic logging configuration to improve observability and simplify debugging. Logs are useful both during development (troubleshooting requests and behavior) and in production (monitoring, incident investigation). + +### Logging setup +A global logging configuration is defined at startup with a consistent log format: +```python +import logging + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) +logger = logging.getLogger(__name__) +``` +**Why it matters**: +- Provides timestamps and log levels for easier troubleshooting. +- A consistent format makes logs easier to parse in log aggregators (e.g., ELK, Loki). +- Centralized config avoids inconsistent logging across modules. + +### Startup logging +The application logs an informational message when it starts: +```python +if __name__ == "__main__": + logger.info("Application starting...") + uvicorn.run("app:app", host=HOST, port=PORT, reload=True) +``` +**Why it matters**: +- Confirms that the service started successfully. +- Helps identify restarts and uptime issues. + +### Request logging (debug level) +Each endpoint logs basic request information (method and path): +```python +@app.get("/", status_code=status.HTTP_200_OK) +async def root(request: Request): + logger.debug(f"Request: {request.method} {request.url.path}") + ... +``` +**Why it matters**: +- Helps trace API usage during development. +- Useful for debugging routing problems and unexpected client behavior. + +## 4. Dependencies (requirements.txt) +The project keeps dependencies minimal and focused on what is required to run a FastAPI service in production. +### requirements.txt +``` +fastapi>=0.110 +uvicorn[standard]>=0.27 +``` +**Why it matters**: +- Faster builds & simpler setup: fewer packages mean faster installation and fewer moving parts. +- Lower risk of conflicts: minimal dependencies reduce version incompatibilities and “dependency hell”. +- Better security posture: fewer third-party libraries reduce the overall attack surface. +- More predictable deployments: only installing what the service truly needs improves reproducibility across environments (local, CI, Docker, VM). + +## 5. Git Ignore (.gitignore) + +A `.gitignore` file is used to prevent committing temporary, machine-specific, or sensitive files into the repository. + +### Recommended `.gitignore` +```gitignore +# Python +__pycache__/ +*.py[cod] +venv/ +*.log + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +``` +**Why it matters**: +- Keeps the repository clean: avoids committing generated files (`__pycache__`, build outputs, logs). +- Improves portability: prevents OS- and IDE-specific files from polluting the project and causing noisy diffs. +- Protects secrets: ensures configuration files like `.env` (which may contain API keys or credentials) are not accidentally pushed. +- Reduces merge conflicts: fewer irrelevant files tracked by Git means fewer conflicts between contributors. + +# 3. API Documentation +The service exposes two endpoints: the main information endpoint and a health check endpoint. +## Request/response examples +### GET `/` — Service and System Information +**Description:** +Returns comprehensive metadata about the service, system, runtime, request details, and available endpoints. +**Request example:** +```bash +curl -i http://127.0.0.1:5000/ +``` +**Response example (200 OK):** +```json +{ + "service": { + "name": "devops-info-service", + "version": "1.0.0", + "description": "DevOps course info service", + "framework": "Flask" + }, + "system": { + "hostname": "my-laptop", + "platform": "Linux", + "platform_version": "Ubuntu 24.04", + "architecture": "x86_64", + "cpu_count": 8, + "python_version": "3.13.1" + }, + "runtime": { + "uptime_seconds": 3600, + "uptime_human": "1 hour, 0 minutes", + "current_time": "2026-01-07T14:30:00.000Z", + "timezone": "UTC" + }, + "request": { + "client_ip": "127.0.0.1", + "user_agent": "curl/7.81.0", + "method": "GET", + "path": "/" + }, + "endpoints": [ + {"path": "/", "method": "GET", "description": "Service information"}, + {"path": "/health", "method": "GET", "description": "Health check"} + ] +} +``` +### GET /health — Health Check +**Description:** +Returns a simple status response to confirm the service is running.**Request example:** +```bash +curl -i http://127.0.0.1:5000/health +``` +**Response example (200 OK):** +```json +{ + "status": "healthy", + "timestamp": "2024-01-15T14:30:00.000Z", + "uptime_seconds": 3600 +} +``` +## Testing commands +### Basic tests +```bash +curl http://127.0.0.1:5000/ +curl http://127.0.0.1:5000/health +``` +### Test 404 handling (unknown endpoint) +```bash +curl -i http://127.0.0.1:5000/does-not-exist +``` +Expected response (404): +```json +{ + "error": "Not Found", + "message": "Endpoint does not exist" +} +``` + +# 4. Testing Evidence +Check screenshots. + +# 5. Challenges & Solutions +I have no problems in this lab. + +# GitHub Community +**Why Stars Matter:** + +**Discovery & Bookmarking:** +- Stars help you bookmark interesting projects for later reference +- Star count indicates project popularity and community trust +- Starred repos appear in your GitHub profile, showing your interests + +**Open Source Signal:** +- Stars encourage maintainers (shows appreciation) +- High star count attracts more contributors +- Helps projects gain visibility in GitHub search and recommendations + +**Professional Context:** +- Shows you follow best practices and quality projects +- Indicates awareness of industry tools and trends + +**Why Following Matters:** + +**Networking:** +- See what other developers are working on +- Discover new projects through their activity +- Build professional connections beyond the classroom + +**Learning:** +- Learn from others' code and commits +- See how experienced developers solve problems +- Get inspiration for your own projects + +**Collaboration:** +- Stay updated on classmates' work +- Easier to find team members for future projects +- Build a supportive learning community + +**Career Growth:** +- Follow thought leaders in your technology stack +- See trending projects in real-time +- Build visibility in the developer community \ No newline at end of file diff --git a/app_python/docs/screenshots/01-main-endpoint.png b/app_python/docs/screenshots/01-main-endpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..2b5ad4b17fe1c5d8a4dfb28c9437474f4aff5f03 GIT binary patch literal 45712 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 WC9Q1i55R&_C_GesP{U literal 0 HcmV?d00001 diff --git a/app_python/docs/screenshots/02-health-check.png b/app_python/docs/screenshots/02-health-check.png new file mode 100644 index 0000000000000000000000000000000000000000..321da884509116354b02fdef84398862741ade84 GIT binary patch literal 11296 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 literal 0 HcmV?d00001 diff --git a/app_python/docs/screenshots/03-formatted-output.png b/app_python/docs/screenshots/03-formatted-output.png new file mode 100644 index 0000000000000000000000000000000000000000..bd76d10670db1ebaaa117ef4380dd37987cd0289 GIT binary patch literal 55725 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.110 +uvicorn[standard]>=0.27 \ No newline at end of file diff --git a/app_python/tests/__init__.py b/app_python/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 2601ee15ecd8b90c049f9e844b67718717e5b1c4 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Sun, 25 Jan 2026 20:03:17 +0300 Subject: [PATCH 02/33] fix: minor fixes --- app_python/README.md | 8 ++++---- app_python/app.py | 6 +++--- app_python/docs/LAB01.md | 18 +++++++++--------- app_python/requirements.txt | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app_python/README.md b/app_python/README.md index 32d32ac023..74ffca1c2b 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -35,7 +35,7 @@ PORT=8080 python app.py The application is configured using environment variables. -| Variable | Default | Description | Example | -|---------|---------|-------------|---------| -| `HOST` | `127.0.0.1` | Host interface to bind the server to | `0.0.0.0` | -| `PORT` | `8000` | Port the server listens on | `8080` | \ No newline at end of file +| Variable | Default | Description | Example | +|---------|---------|-------------|-------------| +| `HOST` | `0.0.0.0` | Host interface to bind the server to | `127.0.0.1` | +| `PORT` | `8000` | Port the server listens on | `8080` | \ No newline at end of file diff --git a/app_python/app.py b/app_python/app.py index a1e16fe273..8cd20e0680 100644 --- a/app_python/app.py +++ b/app_python/app.py @@ -17,7 +17,7 @@ # Configuration HOST = os.getenv("HOST", "0.0.0.0") -PORT = int(os.getenv("PORT", 5000)) +PORT = int(os.getenv("PORT", 8000)) DEBUG = os.getenv("DEBUG", "False").lower() == "true" logging.basicConfig( @@ -47,7 +47,7 @@ def get_system_info(): return { "hostname": socket.gethostname(), "platform": platform.system(), - "platformVersion": platform.version(), + "platform_version": platform.version(), "architecture": platform.machine(), "cpu_count": os.cpu_count(), "python_version": platform.python_version(), @@ -156,7 +156,7 @@ async def unhandled_exception_handler(request: Request, exc: Exception): if __name__ == "__main__": - """The entry point.""" + # The entry point logger.info('Application starting...') uvicorn.run("app:app", host=HOST, port=PORT, reload=True) diff --git a/app_python/docs/LAB01.md b/app_python/docs/LAB01.md index 3c073f4777..1d43f6863d 100644 --- a/app_python/docs/LAB01.md +++ b/app_python/docs/LAB01.md @@ -183,9 +183,9 @@ async def root(request: Request): ## 4. Dependencies (requirements.txt) The project keeps dependencies minimal and focused on what is required to run a FastAPI service in production. ### requirements.txt -``` -fastapi>=0.110 -uvicorn[standard]>=0.27 +```txt +fastapi==0.122.0 +uvicorn[standard]==0.38.0 ``` **Why it matters**: - Faster builds & simpler setup: fewer packages mean faster installation and fewer moving parts. @@ -226,7 +226,7 @@ The service exposes two endpoints: the main information endpoint and a health ch Returns comprehensive metadata about the service, system, runtime, request details, and available endpoints. **Request example:** ```bash -curl -i http://127.0.0.1:5000/ +curl -i http://127.0.0.1:8000/ ``` **Response example (200 OK):** ```json @@ -235,7 +235,7 @@ curl -i http://127.0.0.1:5000/ "name": "devops-info-service", "version": "1.0.0", "description": "DevOps course info service", - "framework": "Flask" + "framework": "FastAPI" }, "system": { "hostname": "my-laptop", @@ -267,7 +267,7 @@ curl -i http://127.0.0.1:5000/ **Description:** Returns a simple status response to confirm the service is running.**Request example:** ```bash -curl -i http://127.0.0.1:5000/health +curl -i http://127.0.0.1:8000/health ``` **Response example (200 OK):** ```json @@ -280,12 +280,12 @@ curl -i http://127.0.0.1:5000/health ## Testing commands ### Basic tests ```bash -curl http://127.0.0.1:5000/ -curl http://127.0.0.1:5000/health +curl http://127.0.0.1:8000/ +curl http://127.0.0.1:8000/health ``` ### Test 404 handling (unknown endpoint) ```bash -curl -i http://127.0.0.1:5000/does-not-exist +curl -i http://127.0.0.1:8000/does-not-exist ``` Expected response (404): ```json diff --git a/app_python/requirements.txt b/app_python/requirements.txt index c0d860c195..94a41a1968 100644 --- a/app_python/requirements.txt +++ b/app_python/requirements.txt @@ -1,2 +1,2 @@ -fastapi>=0.110 -uvicorn[standard]>=0.27 \ No newline at end of file +fastapi==0.122.0 +uvicorn[standard]==0.38.0 From 1bde0adbfa60149fe525a77b1c7e2f0c66b5d5d4 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Sun, 25 Jan 2026 20:34:54 +0300 Subject: [PATCH 03/33] feat: lab01 bonus task completed --- app_go/.gitignore | 18 ++ app_go/README.md | 43 +++ app_go/docs/GO.md | 5 + app_go/docs/LAB01.md | 217 ++++++++++++++ app_go/docs/screenshots/01-main-endpoint.png | Bin 0 -> 44356 bytes app_go/docs/screenshots/02-health-check.png | Bin 0 -> 8540 bytes .../docs/screenshots/03-formatted-output.png | Bin 0 -> 14355 bytes app_go/go.mod | 3 + app_go/main.go | 277 ++++++++++++++++++ 9 files changed, 563 insertions(+) create mode 100644 app_go/.gitignore create mode 100644 app_go/README.md create mode 100644 app_go/docs/GO.md create mode 100644 app_go/docs/LAB01.md create mode 100644 app_go/docs/screenshots/01-main-endpoint.png create mode 100644 app_go/docs/screenshots/02-health-check.png create mode 100644 app_go/docs/screenshots/03-formatted-output.png create mode 100644 app_go/go.mod create mode 100644 app_go/main.go diff --git a/app_go/.gitignore b/app_go/.gitignore new file mode 100644 index 0000000000..d6c75d54e3 --- /dev/null +++ b/app_go/.gitignore @@ -0,0 +1,18 @@ +# Go binaries / build output +devops-info-service +*.exe +*.out +*.test +bin/ +dist/ + +# IDE/editor +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# Logs +*.log \ No newline at end of file diff --git a/app_go/README.md b/app_go/README.md new file mode 100644 index 0000000000..e53cc9a7e6 --- /dev/null +++ b/app_go/README.md @@ -0,0 +1,43 @@ +# devops-info-service (Go) + +## Overview +`devops-info-service` is a lightweight HTTP service written in Go. It returns: +- service metadata (name, version, description, framework), +- system information (hostname, OS/platform, architecture, CPU count, Go version), +- runtime information (uptime, current UTC time), +- request information (client IP, user-agent, method, path), +- a list of available endpoints. + +This is useful for DevOps labs and basic observability: quick environment inspection and health checks. + +--- + +## Prerequisites +- **Go:** 1.22+ (recommended) +- No external dependencies (standard library only) + +--- + +## Installation +```bash +cd app_go +go mod tidy +``` + +## Running the Application +```bash +go run . +``` + +## API Endpoints +- `GET /` - Service and system information +- `GET /health` - Health check + +## Configuration + +The application is configured using environment variables. + +| Variable | Default | Description | Example | +|---------|---------|-------------|---------| +| `HOST` | `0.0.0.0` | Host interface to bind the server to | `0.0.0.0` | +| `PORT` | `8080` | Port the server listens on | `8080` | \ No newline at end of file diff --git a/app_go/docs/GO.md b/app_go/docs/GO.md new file mode 100644 index 0000000000..39785012a7 --- /dev/null +++ b/app_go/docs/GO.md @@ -0,0 +1,5 @@ +### Why Go? +- **Compiled binary**: produces a single executable (useful for multi-stage Docker builds). +- **Fast startup and low overhead**: good for microservices. +- **Standard library is enough**: `net/http` covers routing and HTTP server without external frameworks. +- **Great DevOps fit**: simple deployment, small runtime requirements. diff --git a/app_go/docs/LAB01.md b/app_go/docs/LAB01.md new file mode 100644 index 0000000000..52920f06bc --- /dev/null +++ b/app_go/docs/LAB01.md @@ -0,0 +1,217 @@ +# Lab 1 (Bonus) — DevOps Info Service in Go + +## 1. Language / Framework Selection + +### Choice +I implemented the bonus service in **Go** using the standard library **net/http** package. + +### Why Go? +- **Compiled binary**: produces a single executable (useful for multi-stage Docker builds). +- **Fast startup and low overhead**: good for microservices. +- **Standard library is enough**: `net/http` covers routing and HTTP server without external frameworks. +- **Great DevOps fit**: simple deployment, small runtime requirements. + +### Comparison with Alternatives + +| Criteria | Go (net/http) (chosen) | Rust | Java (Spring Boot) | C# (ASP.NET Core) | +|---------|--------------------------|------|---------------------|-------------------| +| Build artifact | Single binary | Single binary | JVM app + deps | .NET app + deps | +| Startup time | Fast | Fast | Usually slower | Medium | +| Runtime deps | None | None | JVM required | .NET runtime | +| HTTP stack | stdlib | frameworks (Axum/Actix) | Spring ecosystem | ASP.NET stack | +| Complexity | Low | Medium–high | Medium | Medium | +| Best fit for this lab | Excellent | Good | Overkill | Good | + +--- + +## 2. Best Practices Applied + +### 2.1 Clean Code Organization +- Clear data models (`ServiceInfo`, `Service`, `System`, `RuntimeInfo`, `RequestInfo`, `Endpoint`). +- Helper functions for concerns separation: + - `runtimeInfo()`, `requestInfo()`, `uptime()`, `isoUTCNow()`, `clientIP()`, `writeJSON()`. + +### 2.2 Configuration via Environment Variables +The service is configurable via environment variables: +- `HOST` (default `0.0.0.0`) +- `PORT` (default `8080`) +- `DEBUG` (default `false`) + +Implementation uses a simple helper: +```go +func getenv(key, def string) string { + v := os.Getenv(key) + if v == "" { + return def + } + return v +} +``` + +### 2.3 Logging Middleware +Request logging is implemented as middleware: +```go +func withLogging(logger *log.Logger) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + next.ServeHTTP(w, r) + logger.Printf("%s %s (%s) from %s in %s", + r.Method, r.URL.Path, r.Proto, r.RemoteAddr, time.Since(start)) + }) + } +} +``` + +### 2.4 Error Handling +#### 404 Not Found +Unknown endpoints return a consistent JSON error: +```json +{ + "error": "Not Found", + "message": "Endpoint does not exist" +} +``` +This is implemented via a wrapper that enforces valid paths: +```go +func withNotFound(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" && r.URL.Path != "/health" { + writeJSON(w, http.StatusNotFound, ErrorResponse{ + Error: "Not Found", + Message: "Endpoint does not exist", + }) + return + } + next.ServeHTTP(w, r) + }) +} +``` +#### 500 Internal Server Error (panic recovery) +A recover middleware prevents crashes and returns a safe JSON response: +```go +func withRecover(logger *log.Logger) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer func() { + if rec := recover(); rec != nil { + logger.Printf("panic recovered: %v", rec) + writeJSON(w, http.StatusInternalServerError, ErrorResponse{ + Error: "Internal Server Error", + Message: "An unexpected error occurred", + }) + } + }() + next.ServeHTTP(w, r) + }) + } +} +``` +### 2.5 Production-Friendly HTTP Server Settings +The service uses `http.Server` with timeouts: +```go +srv := &http.Server{ + Addr: addr, + Handler: handler, + ReadHeaderTimeout: 5 * time.Second, +} +``` +## 3. API Documentation +### 3.1 GET / — Service and System Information +**Description**: Returns service metadata, system info, runtime info, request info, and available endpoints. + +**Request**: +```bash +curl -i http://127.0.0.1:8080/ +``` +**Response (200 OK) example**: +```json +{ + "service": { + "name": "devops-info-service", + "version": "1.0.0", + "description": "DevOps course info service", + "framework": "Go net/http" + }, + "system": { + "hostname": "DESKTOP-KUN1CI4", + "platform": "windows", + "platform_version": "unknown", + "architecture": "amd64", + "cpu_count": 8, + "go_version": "go1.25.6" + }, + "runtime": { + "uptime_seconds": 6, + "uptime_human": "0 hours, 0 minutes", + "current_time": "2026-01-25T17:17:32.248Z", + "timezone": "UTC" + }, + "request": { + "client_ip": "::1", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0", + "method": "GET", + "path": "/" + }, + "endpoints": [ + { + "path": "/", + "method": "GET", + "description": "Service information" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check" + } + ] +} +``` +### 3.2 GET /health — Health Check +**Description**: Description: Simple health endpoint used for monitoring and probes. + +**Request**: +```bash +curl -i http://127.0.0.1:8080/health +``` +**Response (200 OK) example**: +```json +{ + "status": "healthy", + "timestamp": "2026-01-25T17:19:02.582Z", + "uptime_seconds": 96 +} +``` +### 3.3 404 Behavior +**Request**: +```bash +curl -i http://127.0.0.1:8080/does-not-exist +``` +**Response (404 Not Found)**: +```json +{ + "error": "Not Found", + "message": "Endpoint does not exist" +} +``` + +## 4. Build & Run Instructions +### 4.1 Run locally (no build) +```bash +go run main.go +``` +### 4.2 Build binary +```bash +go build -o devops-info-service main.go +``` +Run: +```bash +./devops-info-service +``` +### 4.3 Environment variables examples +```bash +HOST=127.0.0.1 PORT=3000 ./devops-info-service +DEBUG=true PORT=8081 ./devops-info-service +``` +## 5. Challenges & Solutions +I don't know how `go` works. diff --git a/app_go/docs/screenshots/01-main-endpoint.png b/app_go/docs/screenshots/01-main-endpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f1b2ed5c567e9a28506ba411e332f351df7a73 GIT binary patch literal 44356 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 literal 0 HcmV?d00001 diff --git a/app_go/docs/screenshots/02-health-check.png b/app_go/docs/screenshots/02-health-check.png new file mode 100644 index 0000000000000000000000000000000000000000..aed7a379187856f47ca59651519055fd113e1221 GIT binary patch literal 8540 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 Date: Sun, 1 Feb 2026 13:39:27 +0300 Subject: [PATCH 04/33] feat: LAB02 done --- app_python/.dockerignore | 22 ++++ app_python/Dockerfile | 14 +++ app_python/README.md | 27 ++++- app_python/docs/LAB02.md | 243 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 app_python/.dockerignore create mode 100644 app_python/Dockerfile create mode 100644 app_python/docs/LAB02.md diff --git a/app_python/.dockerignore b/app_python/.dockerignore new file mode 100644 index 0000000000..44fa25304b --- /dev/null +++ b/app_python/.dockerignore @@ -0,0 +1,22 @@ +# 🐙 Version control +.git +.gitignore + +# 🐍 Python +__pycache__ +*.pyc +*.pyo +venv/ +.venv/ + +# 🔐 Secrets (NEVER include!) +.env +*.pem +secrets/ + +# 📝 Documentation +*.md +docs/ + +# 🧪 Tests (if not needed in container) +tests/ \ No newline at end of file diff --git a/app_python/Dockerfile b/app_python/Dockerfile new file mode 100644 index 0000000000..0364cfd9a7 --- /dev/null +++ b/app_python/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3.12-slim + +RUN useradd --create-home --shell /bin/bash appuser + +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY app.py . + +EXPOSE 8000 + +USER appuser + +CMD ["python", "app.py"] \ No newline at end of file diff --git a/app_python/README.md b/app_python/README.md index 74ffca1c2b..2475567ab9 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -38,4 +38,29 @@ The application is configured using environment variables. | Variable | Default | Description | Example | |---------|---------|-------------|-------------| | `HOST` | `0.0.0.0` | Host interface to bind the server to | `127.0.0.1` | -| `PORT` | `8000` | Port the server listens on | `8080` | \ No newline at end of file +| `PORT` | `8000` | Port the server listens on | `8080` | + +# Docker + +## Building the image locally +Command pattern: +```bash +docker build -t : +``` + +## Running a container +Command pattern: +```bash +docker run --rm -p : : +``` + +## Pulling from Docker Hub +Command pattern: +```bash +docker pull /: +``` +Then run: +```bash +docker run --rm -p : /: +``` + diff --git a/app_python/docs/LAB02.md b/app_python/docs/LAB02.md new file mode 100644 index 0000000000..977e742f10 --- /dev/null +++ b/app_python/docs/LAB02.md @@ -0,0 +1,243 @@ +# Docker Best Practices Applied + +## 1. Non-root user +**What I did:** +Created a dedicated user (`appuser`) and ran the container as that user. + +**Why it matters**: +Running as root in a container increases the impact of a container escape or a vulnerable dependency. A non-root user reduces privileges and limits potential damage. + +**Dockerfile snippet:** +```dockerfile +RUN useradd --create-home --shell /bin/bash appuser +USER appuser +``` + +## 2. Layer caching +**What I did:** +Copied `requirements.txt` first and installed dependencies before copying the rest of the source code. + +**Why it matters**: +Docker caches layers. Dependencies change less frequently than application code, so separating them allows rebuilds to reuse the cached dependency layer and rebuild faster. + +**Dockerfile snippet:** +```dockerfile +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY app.py . +``` + +## 3. .dockerignore +**What I did:** +Added .dockerignore to exclude local artifacts such as venvs, caches, and IDE folders. + +**Why it matters**: +Docker sends the build context to the daemon. Excluding unnecessary files makes builds faster, reduces image bloat, and prevents leaking local secrets/files into the build. + +**.dockerignore snippet:** +```.dockerignore +# 🐙 Version control +.git +.gitignore + +# 🐍 Python +__pycache__ +*.pyc +*.pyo +venv/ +.venv/ + +# 🔐 Secrets (NEVER include!) +.env +*.pem +secrets/ + +# 📝 Documentation +*.md +docs/ + +# 🧪 Tests (if not needed in container) +tests/ +``` + +## 4. Minimal base image +**What I did:** +Used `python:3.12-slim`. + +**Why it matters**: +Smaller images generally mean fewer packages, fewer vulnerabilities, less bandwidth and faster pulls/deployments. + +**dockerfile snippet:** +```dockerfile +FROM python:3.12-slim +``` + +# Image Information & Decisions +## Base image chosen and justification (why this specific version?) +**Base image**: +`python:3.12-slim` + +**Justification**: +- Python 3.12 matches the project runtime requirements. +- slim variant keeps image smaller and reduces OS packages. +- Official Python images are widely used and well maintained. + +## Final image size and my assessment +**Image size**: +`195MB` + +**My assessment**: +Further optimization is possible (multi-stage build, wheels caching, removing build deps), but for this lab the size is acceptable. + +## Layer structure explanation +1. Base image layer (`python:3.12-slim`) +2. User creation layer +3. `WORKDIR` and `requirements.txt` copy layer +4. pip install dependencies layer (largest and most valuable for caching) +5. Application source copy layer +6. EXPOSE, USER, and CMD metadata layers + +## Optimization choices +- Used dependency-first copying to maximize caching. +- Used `--no-cache-dir` with pip to reduce layer size. +- Used slim base image to reduce OS footprint. +- Added `.dockerignore` to reduce build context. + +# Build & Run Process +## Complete terminal output from build process +```bash + docker build -t python_app:1.0 . +[+] Building 5.4s (12/12) FINISHED docker:desktop-linux + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 277B 0.0s + => [internal] load metadata for docker.io/library/python:3.12-slim 3.7s + => [auth] library/python:pull token for registry-1.docker.io 0.0s + => [internal] load .dockerignore 0.0s + => => transferring context: 289B 0.0s + => [1/6] FROM docker.io/library/python:3.12-slim@sha256:5e2dbd4bbdd9c0e67412aea9463906f74a22c60f89e 0.0s + => [internal] load build context 0.1s + => => transferring context: 62.28kB 0.1s + => CACHED [2/6] RUN useradd --create-home --shell /bin/bash appuser 0.0s + => CACHED [3/6] WORKDIR /app 0.0s + => CACHED [4/6] COPY requirements.txt . 0.0s + => CACHED [5/6] RUN pip install --no-cache-dir -r requirements.txt 0.0s + => [6/6] COPY app.py . 0.8s + => exporting to image 0.4s + => => exporting layers 0.3s + => => writing image sha256:a3d1dd41a468a1bb53d02edd846964c240eb160f49fd28e9f6ad90fc15677c52 0.0s + => => naming to docker.io/library/python_app:1.0 0.0s + +View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/djiu836gkk9g7syuakivz5ynt +``` + +## Terminal output showing container running +```bash + docker run --rm -p 8000:8000 python_app:1.0 +2026-01-31 18:29:56,977 - __main__ - INFO - Application starting... +INFO: Will watch for changes in these directories: ['/app'] +INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) +INFO: Started reloader process [1] using WatchFiles +INFO: Started server process [8] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +## Terminal output from testing endpoints +```bash +curl http://localhost:8000/ + + StatusCode : 200 +StatusDescription : OK +Content : {"service":{"name":"devops-info-service","version":"1.0.0","description":"DevOps cours + e info service","framework":"FastAPI"},"system":{"hostname":"3a77a23940f7","platform": + "Linux","platform_version":"... +RawContent : HTTP/1.1 200 OK + Content-Length: 755 + Content-Type: application/json + Date: Sat, 31 Jan 2026 18:31:18 GMT + Server: uvicorn + +Forms : {} +Headers : {[Content-Length, 755], [Content-Type, application/json], [Date, Sat, 31 Jan 2026 18:3 + 1:18 GMT], [Server, uvicorn]} Images : {} InputFields : {} Links : {} +ParsedHtml : mshtml.HTMLDocumentClass +RawContentLength : 755 +``` + +```bash +curl http://localhost:8000/health + + +StatusCode : 200 +StatusDescription : OK +Content : {"status":"healthy","timestamp":"2026-01-31T18:31:26.924513+00:00","uptime_seconds":89 + } +RawContent : HTTP/1.1 200 OK + Content-Length: 87 + Content-Type: application/json + Date: Sat, 31 Jan 2026 18:31:26 GMT + Server: uvicorn + + {"status":"healthy","timestamp":"2026-01-31T18:31:26.924513+00:00","uptime_... +Forms : {} +Headers : {[Content-Length, 87], [Content-Type, application/json], [Date, Sat, 31 Jan 2026 18:31 + :26 GMT], [Server, uvicorn]} +Images : {} +InputFields : {} +Links : {} +ParsedHtml : mshtml.HTMLDocumentClass +RawContentLength : 87 +``` + +## Terminal output showing successful push: +```bash +docker push newspec/python_app:1.0 + +The push refers to repository [docker.io/newspec/python_app] +8422fdf98022: Pushed +56a7b3684a2c: Pushed +410b7369101c: Pushed +4e7298e95b69: Pushed +b68196304589: Pushed +343fbb74dfa7: Pushed +cfdc6d123592: Pushed +ff565e4de379: Pushed +e50a58335e13: Pushed +1.0: digest: sha256:9084f1513bc5af085a268ee9e8b165af82f7224e442da0790cf81f07b67ab10e size: 2203 + +``` + +## Docker Hub repository URL +`https://hub.docker.com/repository/docker/newspec/python_app` + +## My tagging strategy +`:1.0`(major/minor) + +# Technical analysis +## Why does your Dockerfile work the way it does? +- The image is based on a minimal Python runtime. +- Dependencies are installed before application code to leverage Docker layer caching. +- The app runs as a non-root user for better security. + +## What would happen if you changed the layer order? +If the Dockerfile copied the entire project (`COPY . .`) before installing requirements, then any code change would invalidate the cache for the dependency install layer. That would force `pip install` to run again on every rebuild, making builds much slower. + +## What security considerations did you implement? +- Non-root execution reduces privilege. +- Smaller base image reduces attack surface. +- `.dockerignore` prevents accidentally shipping local files (including potential secrets) into the image. + +## How does .dockerignore improve your build? +- Reduces build context size (faster build, less IO). +- Avoids copying local venvs and cache files into the image. +- Prevents leaking IDE configs, git history, logs, and other irrelevant files. + +## Challenges & Solutions +# 1. “I cannot open my application” after `docker run` +**Fix**: Published the port with `-p 8000:8000` + +# What I Learned +- Containers need explicit port publishing to be accessible from the host. +- Layer ordering dramatically affects build speed due to caching. +- Running as non-root is a simple but important security improvement. +- .dockerignore is crucial to keep images clean and builds fast. \ No newline at end of file From 26a6262c41cc98767451a8016ba79a51ea54d67d Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Sun, 1 Feb 2026 15:14:18 +0300 Subject: [PATCH 05/33] feat: lab02 bonus task is done --- app_go/.dockerignore | 9 ++ app_go/Dockerfile | 14 +++ app_go/docs/LAB02.md | 215 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 app_go/.dockerignore create mode 100644 app_go/Dockerfile create mode 100644 app_go/docs/LAB02.md diff --git a/app_go/.dockerignore b/app_go/.dockerignore new file mode 100644 index 0000000000..52c65fe81d --- /dev/null +++ b/app_go/.dockerignore @@ -0,0 +1,9 @@ +.git +*.md +docs/ +bin/ +dist/ +tmp/ +.idea/ +.vscode/ +.DS_Store \ No newline at end of file diff --git a/app_go/Dockerfile b/app_go/Dockerfile new file mode 100644 index 0000000000..6dd906a964 --- /dev/null +++ b/app_go/Dockerfile @@ -0,0 +1,14 @@ +# 🔨 Stage 1: Builder +FROM golang:1.22-alpine AS builder +WORKDIR /app +COPY go.mod ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o myapp + +# 🚀 Stage 2: Runtime +FROM gcr.io/distroless/static-debian12:nonroot +WORKDIR /app +COPY --from=builder /app/myapp . +EXPOSE 8080 +CMD ["./myapp"] \ No newline at end of file diff --git a/app_go/docs/LAB02.md b/app_go/docs/LAB02.md new file mode 100644 index 0000000000..ee98527851 --- /dev/null +++ b/app_go/docs/LAB02.md @@ -0,0 +1,215 @@ +# Multi-stage build strategy +## Stage 1 - Builder +**Purpose:** compile the Go application using a full Go toolchain image. + +**Key points:** +- Uses `golang:1.22-alpine` to keep the builder stage smaller than Debian-based images. +- Copies `go.mod` first and runs `go mod download` to maximize Docker layer caching. +- Builds a Linux binary with `CGO_ENABLED=0` (static binary), which allows a minimal runtime image. + +**Dockerfile snippet:** +```dockerfile +FROM golang:1.22-alpine AS builder +WORKDIR /app +COPY go.mod ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o myapp +``` + +## Stage 2 - Runtime +**Purpose:** run only the compiled binary in a minimal image with a non-root user. + +**Key points:** +- Uses `gcr.io/distroless/static-debian12:nonroot`. +- Distroless images contain only what is required to run the app (no package manager, no shell), reducing image size and attack surface. +- Runs as a **non-root** user (provided by the `:nonroot` tag). + +**Dockerfile snippet:** +```dockerfile +FROM gcr.io/distroless/static-debian12:nonroot +WORKDIR /app +COPY --from=builder /app/myapp . +EXPOSE 8080 +CMD ["./myapp"] +``` + +# Size comparison with analysis (builder vs final image) +## Builder +```bash +docker images newspec/app_go:builder +REPOSITORY TAG IMAGE ID CREATED SIZE +newspec/app_go builder 21b01f8c6103 37 minutes ago 305MB +``` +## Final +```bash +docker images newspec/app_go:1.0 +REPOSITORY TAG IMAGE ID CREATED SIZE +newspec/app_go 1.0 a944205e6030 59 minutes ago 9.32MB +``` +## Analysis +The builder image contains the Go toolchain and build dependencies, so it is significantly larger. +The final image contains only the static binary, which is much smaller and safer. + +# Why multi-stage builds matter for compiled languages + +Compiled languages (like Go, Rust, Java with native images, etc.) typically require a **heavy build environment**: compilers, linkers, SDKs, package managers, and temporary build artifacts. If you ship that same environment as your runtime container, the final image becomes unnecessarily large and less secure. + +Multi-stage builds solve this by separating concerns: + +### 1) Smaller final images (faster pull & deploy) +- The **builder stage** includes the full toolchain (large). +- The **runtime stage** contains only the compiled output (usually just a single binary). +This dramatically reduces image size, which improves: +- CI/CD speed (less time to push/pull) +- Startup speed (faster distribution in clusters) +- Bandwidth/storage usage + +### 2) Better security (smaller attack surface) +The runtime image no longer contains: +- compilers (go, gcc, build tools) +- package managers +- shells and utilities (especially with distroless/scratch) + +Fewer components, so fewer potential vulnerabilities (CVEs) and fewer tools available to an attacker if the container is compromised. + +### 3) Cleaner separation of build vs runtime +Multi-stage builds enforce a clear boundary: +- build dependencies exist only where needed (builder stage) +- runtime image stays minimal and focused on execution + +This makes the container easier to reason about and maintain. + +### 4) Reproducible and cache-friendly builds +When the Dockerfile copies dependency descriptors first (e.g., `go.mod`/`go.sum`) and downloads dependencies before copying source code: +- Docker can reuse cached layers if dependencies are unchanged +- rebuilds after code changes are significantly faster + +### 5) Enables ultra-minimal runtime images +Compiled apps can often run in very small base images: +- `distroless` (secure and minimal) +- `scratch` (almost empty) + +This is usually impossible for interpreted languages without bundling an interpreter runtime. + +**Summary:** For compiled languages, multi-stage builds provide the best of both worlds — a full build environment when you need it, and a minimal secure runtime image when you deploy. + +# Terminal output showing build process +## Builder +```bash +docker build --target builder -t newspec/app_go:builder . +[+] Building 2.4s (12/12) FINISHED docker:desktop-linux + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 349B 0.0s + => [internal] load metadata for docker.io/library/golang:1.22-alpine 2.1s + => [auth] library/golang:pull token for registry-1.docker.io 0.0s + => [internal] load .dockerignore 0.1s + => => transferring context: 105B 0.0s + => [builder 1/6] FROM docker.io/library/golang:1.22-alpine@sha256:1699c10032ca2582ec89a24a1312d986a3f094aed3d5c1147b19880afe40e052 0.0s + => [internal] load build context 0.0s + => => transferring context: 146B 0.0s + => CACHED [builder 2/6] WORKDIR /app 0.0s + => CACHED [builder 3/6] COPY go.mod ./ 0.0s + => CACHED [builder 4/6] RUN go mod download 0.0s + => CACHED [builder 5/6] COPY . . 0.0s + => CACHED [builder 6/6] RUN CGO_ENABLED=0 go build -o myapp 0.0s + => exporting to image 0.0s + => => exporting layers 0.0s + => => writing image sha256:21b01f8c61038149b9130afe7881765d625b2eb6622b6b46f42682d26b10ae2b 0.0s + => => naming to docker.io/newspec/app_go:builder 0.0s + +View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/wvw3g1yzoqu1uput2mz8me7zx +``` + +## Final +```bash +docker build -t newspec/app_go:1.0 . +[+] Building 1.5s (15/15) FINISHED docker:desktop-linux + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 349B 0.0s + => [internal] load metadata for gcr.io/distroless/static-debian12:nonroot 1.0s + => [internal] load metadata for docker.io/library/golang:1.22-alpine 0.7s + => [internal] load .dockerignore 0.0s + => => transferring context: 105B 0.0s + => [builder 1/6] FROM docker.io/library/golang:1.22-alpine@sha256:1699c10032ca2582ec89a24a1312d986a3f094aed3d5c1147b19880afe40e052 0.0s + => [stage-1 1/3] FROM gcr.io/distroless/static-debian12:nonroot@sha256:cba10d7abd3e203428e86f5b2d7fd5eb7d8987c387864ae4996cf97191b33764 0.0s + => [internal] load build context 0.0s + => => transferring context: 146B 0.0s + => CACHED [builder 2/6] WORKDIR /app 0.0s + => CACHED [builder 3/6] COPY go.mod ./ 0.0s + => CACHED [builder 4/6] RUN go mod download 0.0s + => CACHED [builder 5/6] COPY . . 0.0s + => CACHED [builder 6/6] RUN CGO_ENABLED=0 go build -o myapp 0.0s + => CACHED [stage-1 2/3] WORKDIR /app 0.0s + => CACHED [stage-1 3/3] COPY --from=builder /app/myapp . 0.0s + => exporting to image 0.1s + => => exporting layers 0.0s + => => writing image sha256:c9ff1572d8a13240f00ef7d66683264e0fbf4fa77c12790dc3f3428972819321 0.0s + => => naming to docker.io/newspec/app_go:1.0 0.0s + +View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/nvdyhylzo1hzpemy23lt42ll1 +``` +# Technical explanation of each stage's purpose +### Stage 1 — Builder (Compile Environment) +**Goal:** Produce a Linux executable from Go source code in a controlled build environment. + +**Why this stage exists:** +- Go compilation requires the Go toolchain (compiler, linker) which is large and should not be shipped in the final runtime image. +- The builder image provides everything needed to compile the application. + +**What happens technically:** +1. **Set working directory** + - `WORKDIR /app` defines where source code and build steps run inside the container. + +2. **Copy dependency definition first** + - `COPY go.mod ./` is done before copying the whole source tree. + - This allows Docker to cache the dependency download layer. + - Even if code changes, dependencies may not, so rebuilds are faster. + +3. **Download modules** + - `RUN go mod download` fetches required modules. + - In this project there are no external module dependencies, so Go prints: + `go: no module dependencies to download` + - The step is still good practice and keeps the Dockerfile consistent for future changes. + +4. **Copy application source code** + - `COPY . .` brings in the Go source files. + - This layer changes most often, so it comes after dependency caching steps. + +5. **Compile a static binary** + - `RUN CGO_ENABLED=0 go build -o myapp` + - `CGO_ENABLED=0` disables C bindings so the binary is statically linked. + - A static binary does not require libc or other runtime shared libraries, enabling minimal runtime images. + +**Output of the stage:** a compiled executable (`/app/myapp`). + +--- + +### Stage 2 — Runtime (Execution Environment) +**Goal:** Run only the compiled binary in a minimal and secure container image. + +**Why this stage exists:** +- The runtime stage should not contain compilers, source code, or build tools. +- A smaller runtime image reduces attack surface and improves deployment speed. + +**What happens technically:** +1. **Choose a minimal base image** + - `FROM gcr.io/distroless/static-debian12:nonroot` + - Distroless images contain only the minimum required runtime files. + - The `:nonroot` variant runs as a non-root user by default. + +2. **Set working directory** + - `WORKDIR /app` provides a predictable location for the binary. + +3. **Copy only the build artifact** + - `COPY --from=builder /app/myapp .` + - This copies only the compiled binary from the builder stage. + - No source code, no Go toolchain, no dependency caches are included. + +4. **Run the application** + - `CMD ["./myapp"]` starts the service. + - The application reads `HOST` and `PORT` environment variables: + - defaults: `HOST=0.0.0.0`, `PORT=8080` + - When running the container, port mapping must match the internal listening port (e.g., `-p 8000:8080`). + +**Output of the stage:** a minimal runtime container that executes the Go binary as a non-root user. \ No newline at end of file From 940215538279ae070100593644f5854fffc0b474 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:32:17 +0300 Subject: [PATCH 06/33] feat: lab03 task2 workflow ready --- .github/workflows/python-ci.yml | 0 app_python/docs/LAB03.md | 109 ++++++++++++++++++++++++++++++++ app_python/requirements.txt | 2 + app_python/tests/conftest.py | 14 ++++ app_python/tests/test_errors.py | 52 +++++++++++++++ app_python/tests/test_health.py | 18 ++++++ app_python/tests/test_root.py | 70 ++++++++++++++++++++ 7 files changed, 265 insertions(+) create mode 100644 .github/workflows/python-ci.yml create mode 100644 app_python/docs/LAB03.md create mode 100644 app_python/tests/conftest.py create mode 100644 app_python/tests/test_errors.py create mode 100644 app_python/tests/test_health.py create mode 100644 app_python/tests/test_root.py diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app_python/docs/LAB03.md b/app_python/docs/LAB03.md new file mode 100644 index 0000000000..aff1f98b7b --- /dev/null +++ b/app_python/docs/LAB03.md @@ -0,0 +1,109 @@ +# Unit Testing + +## Testing framework choice and why +After reviewing popular Python testing frameworks (such as `unittest` and `pytest`), I chose **pytest** because it makes writing, maintaining, and scaling tests easier and faster for both small and large projects. + +### 1) Less boilerplate, faster to write tests +With `pytest`, you don’t need to create test classes or inherit from special base classes (which is common in `unittest`). +Simple functions named `test_*` are enough, which keeps tests clean and easy to read. + +### 2) Powerful fixture system +`pytest` provides a strong **fixture** mechanism for setting up test data and environments: +- reusable setup/teardown logic; +- flexible scopes (`function`, `module`, `session`); +- dependency injection by simply adding parameters to test functions. + +This reduces duplication and improves test structure. + +### 3) Easy test parametrization +`pytest` makes it simple to run the same test with multiple input datasets using parametrization. +That improves coverage without copying and pasting similar tests. + +### 4) Clear, helpful failure output +When a test fails, `pytest` produces detailed and readable error messages (including smart value comparisons). +This speeds up debugging and helps quickly identify what went wrong. + +### 5) Rich plugin ecosystem and CI integration +`pytest` has a large ecosystem of plugins and integrates well with: +- coverage tools, +- linters, +- CI/CD systems (GitHub Actions, GitLab CI, etc.), +- reporting tools. + +This is useful if the project grows or needs automation. + +### 6) Flexibility and compatibility +`pytest` can also run tests written in the `unittest` style, so it’s easier to adopt gradually. +At the same time, `pytest` offers more modern and flexible features for everyday testing. + +--- + +**Conclusion:** I chose **pytest** because it reduces boilerplate, provides powerful fixtures and parametrization, offers excellent debugging output, and scales well with plugins and CI workflows. + +## Test structure explanation + +All tests are located in `app_python/tests/` and are written with **pytest** using FastAPI’s `TestClient`. + +### Directory layout +```text +app_python/ + app.py + tests/ + conftest.py + test_root.py + test_health.py + test_errors.py +``` + +### What each file contains +- `conftest.py` + - Defines shared pytest fixtures (e.g., `client`) used across multiple test files. + - The `client` fixture creates a `TestClient(app)` so tests can call the API endpoints without running a real server. +- `test_root.py` + - tests the main endpoint `GET /`. + - Verifies: + - HTTP status code is `200` + - JSON response contains required top-level fields (`service`, `system`, `runtime`, `request`, `endpoints`) + - Nested fields exist and have reasonable types/values (e.g., `uptime_seconds` is an `integer`, `timezone` is `"UTC"`) + - The endpoints list contains expected endpoints (`/` and `/health`) +- `test_health.py` + - Tests `GET /health`. + - Verifies: + - HTTP status code is `200` + - JSON response contains required fields (`status`, `timestamp`, `uptime_seconds`) + - status is `"healthy"` and `timestamp` is serialized as an ISO string +- test_errors.py + - Tests custom error handling: + - **500 Internal Server Error**: adds a temporary endpoint that raises `RuntimeError` and checks that the response JSON matches the global exception handler. + - **404 Not Found**: requests a non-existent endpoint and checks the custom 404 JSON. + - **Non-404 HTTPException**: adds a temporary endpoint that raises `HTTPException(418)` and checks the JSON returned by the `HTTPException` handler. + - Temporary test routes are removed in `finally` blocks to avoid affecting other tests. + +### Naming conventions +- Test files are named test_*.py +- Test functions are named test_* +- This allows pytest to automatically discover and run the test suite. + +## How to run tests locally +Use command: +```bash +pytest +``` + +## Terminal output showing all tests passing +```bash +pytest +========================================== test session starts =========================================== +platform win32 -- Python 3.12.4, pytest-8.4.2, pluggy-1.6.0 +rootdir: C:\Users\malov\PycharmProjects\DevOps-Core-Course +plugins: anyio-4.11.0, asyncio-1.3.0, cov-7.0.0 +asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function +collected 7 items + +app_python\tests\test_errors.py ... [ 42%] +app_python\tests\test_health.py .. [ 71%] +app_python\tests\test_root.py .. [100%] + +=========================================== 7 passed in 0.48s ============================================ +(.venv) PS C:\Users\malov\PycharmProjects\DevOps-Core-Course> +``` \ No newline at end of file diff --git a/app_python/requirements.txt b/app_python/requirements.txt index 94a41a1968..3ea66f4957 100644 --- a/app_python/requirements.txt +++ b/app_python/requirements.txt @@ -1,2 +1,4 @@ fastapi==0.122.0 uvicorn[standard]==0.38.0 +pytest==8.4.2 +flake8==7.3.0 diff --git a/app_python/tests/conftest.py b/app_python/tests/conftest.py new file mode 100644 index 0000000000..d1bf72913b --- /dev/null +++ b/app_python/tests/conftest.py @@ -0,0 +1,14 @@ +import pytest +from fastapi.testclient import TestClient + +from app import app + + +@pytest.fixture() +def client(): + return TestClient(app) + + +@pytest.fixture() +def client_no_raise(): + return TestClient(app, raise_server_exceptions=False) diff --git a/app_python/tests/test_errors.py b/app_python/tests/test_errors.py new file mode 100644 index 0000000000..076f70dff6 --- /dev/null +++ b/app_python/tests/test_errors.py @@ -0,0 +1,52 @@ +from fastapi import HTTPException + +from app import app + + +def test_500_returns_custom_json(client_no_raise): + @app.get("/__test_crash__") + async def __test_crash__(): + raise RuntimeError("boom") + + try: + r = client_no_raise.get("/__test_crash__") + assert r.status_code == 500 + assert r.json() == { + "error": "Internal Server Error", + "message": "An unexpected error occurred", + } + finally: + app.router.routes = [ + route for route in app.router.routes + if getattr(route, "path", None) != "/__test_crash__" + ] + + +def test_http_exception_handler_404_custom_json(client): + r = client.get("/this-endpoint-does-not-exist") + + assert r.status_code == 404 + assert r.json() == { + "error": "Not Found", + "message": "Endpoint does not exist", + } + + +def test_http_exception_handler_non_404_returns_http_error_json(client): + @app.get("/__test_http_418__") + async def __test_http_418__(): + raise HTTPException(status_code=418, detail="I'm a teapot") + + try: + r = client.get("/__test_http_418__") + + assert r.status_code == 418 + assert r.json() == { + "error": "HTTP Error", + "message": "I'm a teapot", + } + finally: + app.router.routes = [ + route for route in app.router.routes + if getattr(route, "path", None) != "/__test_http_418__" + ] diff --git a/app_python/tests/test_health.py b/app_python/tests/test_health.py new file mode 100644 index 0000000000..1d2b4f9dcd --- /dev/null +++ b/app_python/tests/test_health.py @@ -0,0 +1,18 @@ +def test_health_status_code(client): + r = client.get("/health") + assert r.status_code == 200 + + +def test_health_response_structure(client): + r = client.get("/health") + data = r.json() + + for key in ["status", "timestamp", "uptime_seconds"]: + assert key in data, f"Missing health field: {key}" + + assert data["status"] == "healthy" + assert isinstance(data["uptime_seconds"], int) + assert data["uptime_seconds"] >= 0 + + assert isinstance(data["timestamp"], str) + assert "T" in data["timestamp"] diff --git a/app_python/tests/test_root.py b/app_python/tests/test_root.py new file mode 100644 index 0000000000..9ca61460fa --- /dev/null +++ b/app_python/tests/test_root.py @@ -0,0 +1,70 @@ +def test_root_status_code(client): + r = client.get("/") + assert r.status_code == 200 + + +def test_root_json_structure_and_required_fields(client): + r = client.get("/") + data = r.json() + + for key in ["service", "system", "runtime", "request", "endpoints"]: + assert key in data, f"Missing top-level field: {key}" + + service = data["service"] + for key in ["name", "version", "description", "framework"]: + assert key in service, f"Missing service field: {key}" + assert service["name"] == "devops-info-service" + assert service["framework"] == "FastAPI" + + system = data["system"] + for key in [ + "hostname", + "platform", + "platform_version", + "architecture", + "cpu_count", + "python_version", + ]: + assert key in system, f"Missing system field: {key}" + + assert isinstance(system["hostname"], str) and system["hostname"] + assert isinstance(system["platform"], str) and system["platform"] + assert isinstance(system["architecture"], str) and system["architecture"] + assert ((system["cpu_count"] is None) or + isinstance(system["cpu_count"], int)) + + runtime = data["runtime"] + for key in ["uptime_seconds", "uptime_human", "current_time", "timezone"]: + assert key in runtime, f"Missing runtime field: {key}" + + assert isinstance(runtime["uptime_seconds"], int) + assert runtime["uptime_seconds"] >= 0 + assert isinstance(runtime["uptime_human"], str) and runtime["uptime_human"] + assert runtime["timezone"] == "UTC" + + assert isinstance(runtime["current_time"], str) + assert "T" in runtime["current_time"] + + req = data["request"] + for key in ["client_ip", "user_agent", "method", "path"]: + assert key in req, f"Missing request field: {key}" + + assert req["method"] == "GET" + assert req["path"] == "/" + assert isinstance(req["client_ip"], str) and req["client_ip"] + assert ("user_agent" in req) + + endpoints = data["endpoints"] + assert isinstance(endpoints, list) + assert len(endpoints) >= 2 + + paths = {(e.get("path"), e.get("method")) for e in endpoints} + assert ("/", "GET") in paths + assert ("/health", "GET") in paths + + for e in endpoints: + for key in ["path", "method", "description"]: + assert key in e + assert isinstance(e["path"], str) and e["path"].startswith("/") + assert e["method"] in {"GET", "POST", "PUT", "DELETE", "PATCH"} + assert isinstance(e["description"], str) and e["description"] From fe8455c5fa673d5a3f0b1b6d103b4e75ae18981a Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:37:08 +0300 Subject: [PATCH 07/33] feat: workflow added --- .github/workflows/python-ci.yml | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index e69de29bb2..d8f42aebe9 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -0,0 +1,48 @@ +name: Python Tests + +"on": + push: + branches: ["lab03"] + paths: + - 'app_python/**' + - '.github/workflows/python-ci.yml' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + + - name: Install dependencies + run: pip install -r app_python/requirements.txt + + - name: Run linter + run: flake8 + + - name: Run tests + run: pytest + + docker: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Generate version + run: echo "VERSION=$(date -u +%Y.%m.%d)" >> $GITHUB_ENV + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./app_python + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/python_app:${{ env.VERSION }} + ${{ secrets.DOCKER_USERNAME }}/python_app:latest From 6fddd3432f72f1f1482ba53d4de15944c8eec5dd Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:39:11 +0300 Subject: [PATCH 08/33] feat: workflow added --- app_python/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/app_python/requirements.txt b/app_python/requirements.txt index 3ea66f4957..170f1dfdce 100644 --- a/app_python/requirements.txt +++ b/app_python/requirements.txt @@ -2,3 +2,4 @@ fastapi==0.122.0 uvicorn[standard]==0.38.0 pytest==8.4.2 flake8==7.3.0 +httpx==0.28.1 From 04fc643662b3e1a9caa917c8a8f8e0cc2247d0b5 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:44:05 +0300 Subject: [PATCH 09/33] feat: workflow updated --- .github/workflows/python-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index d8f42aebe9..e8a898bc27 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -45,4 +45,5 @@ jobs: push: true tags: | ${{ secrets.DOCKER_USERNAME }}/python_app:${{ env.VERSION }} + ${{ secrets.DOCKER_USERNAME }}/python_app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/python_app:latest From 90a3723e5e60e118c4d19bd2b649f36c4cf2c7de Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:48:52 +0300 Subject: [PATCH 10/33] fix: minor workflow fix --- .github/workflows/python-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index e8a898bc27..f58aa9d21d 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -1,6 +1,6 @@ name: Python Tests -"on": +on: push: branches: ["lab03"] paths: From db7c90f59ff2793d416a9b5c11535ed2aa6fef0a Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 13:53:15 +0300 Subject: [PATCH 11/33] fix: change the name of the workflow --- .github/workflows/python-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index f58aa9d21d..fab1caca82 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -1,4 +1,4 @@ -name: Python Tests +name: Python ci on: push: From 20c09a6b2eb825b9543ebf9fdd70943837f32c3f Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 15:07:05 +0300 Subject: [PATCH 12/33] feat: add caching in workflow --- .github/workflows/python-ci.yml | 4 ++++ app_python/docs/screenshots/green-checkmark.png | Bin 0 -> 9074 bytes 2 files changed, 4 insertions(+) create mode 100644 app_python/docs/screenshots/green-checkmark.png diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index fab1caca82..433c851109 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -13,6 +13,10 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 + with: + python-version: 3.12 + cache: "pip" + cache-dependency-path: app_python/requirements.txt - name: Install dependencies run: pip install -r app_python/requirements.txt diff --git a/app_python/docs/screenshots/green-checkmark.png b/app_python/docs/screenshots/green-checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd752024b40fd48d17aca25109aeb4a8f72ea72 GIT binary patch literal 9074 zcmdUUcTkgEw{HLe5djeeMT+=JZ;D{(i6Bh`BGQq7BE1A@flz`XMUmd5_l|%x4OPWg znt&k)hCq-K0tpZx6lvi`&v)nEKi;`B=bLlS%=zb8&$IVldzD%1x7S|J3y85E$0`0( z004l)K>xNW0Kf>LzaO7up+7Z&OO^n@Un&N-ZT>(=m#d%s_zEUH}bX`8ht;>n5~t7%Dft7V6% zbx!1$ccq>^z38g(g%S-R=oA@^i7CdEy!NVsbC4;&w9zR<0HMUV@0P^+$Dbqy_t<41 zc=^%xDR>h9-!#eG5$5Pq0mfdjH))o8Q{Pd${^NemG&6J>i61&<96rm8~qTkbXP9#X-97<_x!arx z-I{(H3|x&)r~v+|FQGPh_3CuPeDvm4Mu=HwFe7>GO?Xc8BxhK%4Sp(v+9WsGr{LtS z0T-TsC@1mZxh^_*gafZx6->K+BQX*RY=%L5JZ^HXjp$Men_g{9{;EAo$&Q?n491p@ zNVRfY5ZfZU=es12XzW#^0QO zfye;?Ii#Hq0sPO25>4?dL@m=0ft5&HR|l`V-)IzW{1UKgvBh!z{zpoVwb&u*d1Br> z^v@<6*&O@z#4I(Cm8PLXw^`gP&D9td(D$may25Y$s=M--DiP+pV z;(Ou`QUJw(GMBD*>`$j1=lAz23mKPmOP}V#M=2=B46(mKz1qFV51%$54t*bCk4;fY znB5Uw;x<`XUiVPL(_U|ICaKyIs7V!gNrkFs^=QzE0b_0Q{`gKte zpXV1+s^UxeBb)CfF-W~n+6ToLn;tK46hwq;r=r-`Q^T8Yy&N{d8%Hl4M8%1}S2H;Y z$$IM#n|=;B|Da?4;E3sKv?MflF~m7MF(~$WCKYMib|$+ZF1U9Y9~Dd`icfpBVWyo9 z4r;&ZX0V7-P5{{#UAT{ArV0D(5bOwhpRVbU%CFVuSe7r7d8Mr%-d`WwLG5E+1y7ct}59d|1u09V*V>D`xSpsRJ?0_0nu1^g|7JPdW3p7PB zSC$6cC@}Oyauj#EZtNOsehH^!YHz`#)PENAW{qgjtnaK8bAwKpF>=1dGc>P zZ%#@8h&qoXyI**9IVsEe!In1M1^p;tc%)S@)fEuig><&nG-hi3Q~*;9q6rSXyz9dz zn@ZT-y*_h;-!(zW&lbw) z>u;mmTeU8S>M>nBMQNhrUxTP9!$61O%@7NP7v0}Jonja$Z2(ErkYdO2&}kcN{}nnqENzOH*G02;C;52j9*6($HlJ190c4 zv6xJsO8J6S+52MV!)Yv%1An84Y&+fGzr~QcXH%sH*V3##i1e)q4PLw9lAT|Xi5`s3f8ooYZ$HT7 z;ryQCtI1kswKoj9E#2s_sqBL2uWf1UJ}9kiFEZn$JaG}W)3~QQv?+(z6Us=rG(Jd_ zg$>MI5^ux#E~5BW|IU$myc0Ct5T7dP!TFNPJI(4eBm=|t$CWltPJ83>W1QNWYByWo z%=#4WTG|~>$90W!X_LY-_-}o(HBMza>kirpW~lCvQ5^dFXZXz|d_o)= zPe>fWN@KpT*@wGcTZ}=Jf8CD1RyMH;{B~jGXkHVwv1q&Sx&JuLMDyq_t+zRAb1h_} zA>~$7mMg?h%S6W+At4imBwjWn&FHP}&N+allg#S19M=z2a2hFWuaX_laop$<_N?b* zuAH}T9`vKM_WQB6E&O8E7~+7`=YPYfEhOa!-ZBcQG{B=lNK^S4X%Nh_$u^^2UHUkC z9Xjd%Gk@Mu7!$w{eCr)kGSn5J3i0( z-ShG%r~^oQ?z_S_c34NzShw0`p^#%`=3BD<53eE86&Jg1?+%_$fcAxA4?80XsUd~M zx5R8CRJU|0LcfjuMOmp$C&M3{69-TG>3U-^vcfBB(la$nN!cU(g!0VxvT{PlRA-wF z?U1`Zrds>W?!(Th#wxo6@eWG_W7__Tl>f+=t67%eUs3l?`e=5qKLOgqg=>BxC>Ln@&1YEE`S;SlCgIVoD#wR6&UH7f!KwBBD4U)eqyE z$-@UO!R5UlRl&i^d~%K_<*$SPrZ{ZVew>g<4Kt_o3sTp7g{CNEa%y+CBeYusVs03} zYjPnlZdW<0AP3!k?k+W2$YnS%L8pUNY8Mc27-z9ZG;(oTOI6xzTIHJpoIgDq3=&qB zMsCEOvPuN@*AUyB_U^A8rdEv5!}jLjl-}?_H|b&L^IbzOz6IC4dZ%ZcG9;EOLBr+U zfbYfb2C|^A>054?9>YtWBgDQQg}|+=)`bZH@DXNg7^R2g=bbr#nt!}622@08pzb?O z8$3aT=}n`|Ctv+sJfUiiJm6`65_cvbcdAJ3yZ~QytIO7EBTDBiV;YiaA}MGJ;1JaB z5wRJwZllJZ&XIulVazJNifxsDwmi8Y((xP+Kqx$=!{Y>X(ta#q1O)RqjV@pt*X}Fa$Q=UmS)e5Sh#7GD&$`fLel)zaMzcg7Kjbaaqkm~n|iCpmxyg#)X!kmXj-jr zvd@ZEP`pc=kBVLZq`O&Z2Xz7$uUUI$g$FI5dkK2Tu*kcI8_3MwaSiS~!7J1UDcn8w;6cHvsCU_pa}gpRj^}MK(^B| zF7Q(Jt6x%kNql30(u<+SG*FldCA zH0y~(=txiZDAQ zOQ`bmJPT8g%J2rYX(s0(px-aTSNIAnqnz3@Y(MK3;5uq=SNO(Djr;Dz;F8lkSF$+s zS&c^x_>gtm8FP~~B`Du6kzDS~A5OU#$u|65>+x~qT0d^lA~Ao$~B{Ai5RGa9?7 z#@0`eY@M+3u8^s)d2zNx=7tK` z?Nd)sRzq@@^T8QZc~gyHTYJ+9EgnbviX{kX7d*5j{0O+yJ{w zw+a5jw#U=uO}>NLE(`KPYSMo202NFI2qFvgs!q+Zunf_F5DAusTZ%0!jscBpTkv9G zFtVjsH+&t}N(|nt#&XMp5^cFTIjs7+4k^ zMFw%(Opx!j9Sr#_Jz-1}k^_o6FTDx3AF#yNd24>@&s|+xH;3U2szNs>6bvSa+1y*9 z8GE^@7t4#OSNGmCd{|GO0FbO-Z-}I4vK{1>ryL_H}cu&Kz$o|B56OhmT`^)jv3uYU@1B|6pme3ZEzu z%A*1RoEBx~E)4xO^8Deo+2c=4fQX{vLVET6L4OWKyfIUsQKO+z6}-+_C~^5e-NE?B zdj0>|`taq1h*w`KeMj;2ze%s+!RVCx5hOaMw|%j2bJY;eqgU4eNb_lBuv^#Bj_vaD za`OF_c;nb&@!x$ET}Bn=N=nzk@N!gJ&_?mt&E~!rBm^-_;`Z&^pC8?<0F-TLr>(sp zt*vF$)yXZdtkB1A%h>pFLih!Xw|w$BP4_?g{#hFcVN6R5ZxG<-=6?G_aO_XB=Gxi+ zyaP_VN4yO0KX>KIl}FcAB^d4;Tgn*`RTmx`X|I5A+P|gWq)S&-&(p-o1Q>a3e*fFh zw`y16_xgJ|_ajDUtKM#R@Z=X?(*3>Gf>oe!>zBQ~eL-$zT?LViuAN>Q-DFtT-j|E4 zue{IwR`<0iScJ}Rb0DGkb(Lf|MV~~QGXB=3xa`Dlm)tgFgV5(c?4@3I{+emh%Kg<$_GdME9ZI$h$|xGE0F zHl;SjjmM%NM{Dk2sf^p)FMgunPBX4b92&g$TfavivnBxn`&rgf*JLG=07}pQ=*K>M z$SMK4>{*-E9 zR8jiyVIACJU{}v1B?Jn~s9THM#2T`HCrfTFZG1&wg#0FI+K_h|pq}vNN5;QrBgndFthM@$=->G-)LAj&G?cyc88$T0ZrJuet)5}$i# zey`MofG((R*uLx4P2QUwc=Cm6ocQf2t9bOgfHn)Gk+X&SSmZm_f$2q2*ii~=Vi0*X zHRSNy?ccE{qs)F4Y?Q2*=v>~})pzo*-h!lprH2iebl)6dPei>E7*(GKAUwZttT6>p zdZTU|F+h_s54D|KVUWVn#F-_;zp2#!3D79drza{+_h@15rCkS&{(|tBChw5`<2w<~ zdq*?XKG(IG%aN1kPh{3vZc}xRCFEO!a4%Sd=L05i2z?oa=azG_xDmwLuv)nWu1{{iHDf<()2||2mTe({)TwxeKiyn8tKeEUC%0*|Qq;=W^_q%EON7NqD{g z6DMTYXHt1@HcYLoOZ;JYQO?eh9zD`-Q-%Me>3y+(Ol3Xih<(>o8SMC(f&{vNAdY_} zwQL07`(<2slhxwaiMkXody-qs<0BY8$%{O_Oa_@^xd#b@;~&usFEN z{!M^RoaW4SaQ(=!tI@f(F_~AlM;|mP|60@lFDurY=tm^K)I7%cTN)01(iitqiqm$a z*Hmj~339x;3j2o>0cYOCYo%vLB^yt=^TvGXV3p|9{GcyBp~`PuWgX%FU4}FMghT}6 z<^TSHs?!i$A|<6=Ds%AH%&^ZGsC%=2ZRru9>ej?Zz80g=vGI#F$y)a)Ie0yH-UvXH zBs+vCm!H`kHY>Cz&vhh$#vOYlH`}em*6|kE1zcjcOXH2A%3XZ^&$&oR%}`NEBW)>+|77I-riUjX4n4CRaZbabt4+SjiWTNi+qX7Q z_Vb%9spJ+e49uNzY`mntmmi8DhpYYdYmeXv)3N0GHtRO#YEr@7b@^c8Yevf1ZNyhI zYl!vgUA6rM^^0m>?7Xods_IVTCEP+N#WgEgKeG}K7Kw_d;~17Rg;K4asmS-lV`Wl7 zm_N)!g^YRyD;4 zaFcEKz+9PwZzmy^)n%a;RjWHA#K%_qci_T0U(MAsKh`* z!cf3*z(F0Jnx^RAa-yDc*fY9BVwn}H#M{L^Ug-=eJ9vpecUtl$7Ko=8nDuR;;~vB7 zQ9>G!pVYVNf~!wQJ56szjKW*j>|m826AGDPLtJvvT%w4|mD>T4in-*zngYuSwf`{U zoBPfWn~OE>uz5-IBzmWonnxQNF|Y<&Gv~#BFE(rmG0C#=uC7(XN~`fzJ2`u$jD#rU zJYh0x$wg~eHAyXeO_$l8S(Hxz4F7>mdJ6GZBM<|I@4Io_gaIx3C+9R zRcw&?@o53YR;qO7AkuEzkw}ceL*2|d>sCtS z)7YWfBm}jE6B2MIlY*e%_*%Vy!Xnob$b+@{MyZ`e(Fr?=4 zk+OzSoVNB#yjp(1Gt5H}*v@e%ducKjI^y#_KpKd3-(b#wC}&%5=ng zFsnoW93j(o;+1-xP~n3y-?wfT_b;8r^f>R!&lGPfOp(GaES%Dh$|4v7tItyNj#K*5F6lxRH!M={-K!q`rRv2Q^n$*>YB0zS`G zZNU?n5~uPU{zi%XztJLXah#7PIliuY6qDJ=B?%~HI7(-T`gX8T)1B#FXzvIf(t4Zn z2U)5a(`cq$I68bOedyXZ+?(tkR^VlYe0XhNTGb7&Iv^Xqwdv19*l%faY{e;7Sxe~p zcJ4gfH!_ddL?1JM?f|9r|LBFK2&-SeAHF@RK(jrmuhhorUw>cZG|uV%{{d(Y2;gts zx&Xyo(ta1?I&(E z-#lgR&a12HRzug3&fQ!w(yA0r);KAs!I_#&lwg7k75jQL-;`~73oK*yNgZE|?_zW|z1 B@0S1o literal 0 HcmV?d00001 From 5be24fabe2e6169a94696f47088137c7a8101340 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 15:13:03 +0300 Subject: [PATCH 13/33] feat: add caching in workflow(check improvement) --- .github/workflows/python-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 433c851109..0dd36e174a 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -1,5 +1,6 @@ name: Python ci + on: push: branches: ["lab03"] From b257c59d9e9a28d2432a4ef0c4130ad1e730997d Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 15:47:33 +0300 Subject: [PATCH 14/33] feat: snyk added into workflow --- .github/workflows/python-ci.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 0dd36e174a..9b2316c94c 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -3,7 +3,7 @@ name: Python ci on: push: - branches: ["lab03"] + branches: [ "lab03" ] paths: - 'app_python/**' - '.github/workflows/python-ci.yml' @@ -28,6 +28,18 @@ jobs: - name: Run tests run: pytest + security: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run Snyk (dependencies) + uses: snyk/actions/python@master + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --severity-threshold=high --file + docker: needs: test runs-on: ubuntu-latest From a576f84a472f05d965d603015e7a429f437720bf Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 15:49:35 +0300 Subject: [PATCH 15/33] fix: snyk --- .github/workflows/python-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 9b2316c94c..7d613a3654 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -38,7 +38,7 @@ jobs: env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - args: --severity-threshold=high --file + args: --severity-threshold=high docker: needs: test From 8dc6f9f20cb5aed08bb292373308f19c21e97f70 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 17:45:08 +0300 Subject: [PATCH 16/33] fix: snyk added --file path --- .github/workflows/python-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 7d613a3654..0076df8c00 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -38,7 +38,7 @@ jobs: env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - args: --severity-threshold=high + args: --severity-threshold=high --file=app_python/requirements.txt docker: needs: test From ba08efb36af77b5525244a9140903b7f456e68d4 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 17:47:55 +0300 Subject: [PATCH 17/33] fix: snyk added dependencies --- .github/workflows/python-ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 0076df8c00..43ddae1841 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -33,6 +33,15 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: 3.12 + cache: "pip" + cache-dependency-path: app_python/requirements.txt + + - name: Install dependencies + run: pip install -r app_python/requirements.txt + - name: Run Snyk (dependencies) uses: snyk/actions/python@master env: From 9a4ab4f5a597f7e69d396eb81cc52ff6e2781939 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 17:54:03 +0300 Subject: [PATCH 18/33] fix: snyk --- .github/workflows/python-ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 43ddae1841..a53fba0905 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -33,24 +33,26 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: - python-version: 3.12 + python-version: "3.12" cache: "pip" cache-dependency-path: app_python/requirements.txt - name: Install dependencies run: pip install -r app_python/requirements.txt + - name: Setup Snyk CLI + uses: snyk/actions/setup@master + - name: Run Snyk (dependencies) - uses: snyk/actions/python@master + working-directory: app_python env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - with: - args: --severity-threshold=high --file=app_python/requirements.txt + run: snyk test --severity-threshold=high docker: - needs: test + needs: [test, security] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From b6ec2c981bdf1b4a4d4dfbb5a99d848b8588efcc Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:28:08 +0300 Subject: [PATCH 19/33] feat (workflow): docker caching ebable --- .github/workflows/python-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index a53fba0905..ea61e9b553 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -57,6 +57,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub uses: docker/login-action@v3 with: @@ -75,3 +78,5 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:${{ env.VERSION }} ${{ secrets.DOCKER_USERNAME }}/python_app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/python_app:latest + сgache-from: type=gha + cache-to: type=gha,mode=max From 9272242634e87ac31cde189c86d1b92f6775f85e Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:30:16 +0300 Subject: [PATCH 20/33] fix (workflow): docker --- .github/workflows/python-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index ea61e9b553..bf53bffbca 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -70,7 +70,7 @@ jobs: run: echo "VERSION=$(date -u +%Y.%m.%d)" >> $GITHUB_ENV - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ./app_python push: true @@ -78,5 +78,5 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:${{ env.VERSION }} ${{ secrets.DOCKER_USERNAME }}/python_app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/python_app:latest - сgache-from: type=gha + сache-from: type=gha cache-to: type=gha,mode=max From 053b9638602052c4f2acba4aedff7587402fa2cf Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:33:09 +0300 Subject: [PATCH 21/33] fix (workflow): docker --- .github/workflows/python-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index bf53bffbca..376eb727b6 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -78,5 +78,5 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:${{ env.VERSION }} ${{ secrets.DOCKER_USERNAME }}/python_app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/python_app:latest - сache-from: type=gha + cache-from: type=gha cache-to: type=gha,mode=max From a382d1d6da46cdc1d133dbedb98a6f3b56e0a204 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:35:25 +0300 Subject: [PATCH 22/33] feat: check how caching works --- .github/workflows/python-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 376eb727b6..f6edc3c654 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -52,7 +52,7 @@ jobs: run: snyk test --severity-threshold=high docker: - needs: [test, security] + needs: [ test, security ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -80,3 +80,4 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:latest cache-from: type=gha cache-to: type=gha,mode=max + From 89270d4d939f9b7a35c23aaf524c07cb0422778b Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:47:37 +0300 Subject: [PATCH 23/33] cold run --- .github/workflows/python-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index f6edc3c654..3ed6ab94d8 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -80,4 +80,3 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:latest cache-from: type=gha cache-to: type=gha,mode=max - From ef0c471974d86064123cbefc2084c366d52b7705 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 20:49:20 +0300 Subject: [PATCH 24/33] warm run --- .github/workflows/python-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 3ed6ab94d8..f6edc3c654 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -80,3 +80,4 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/python_app:latest cache-from: type=gha cache-to: type=gha,mode=max + From 8a8eb351b0271c937cf97670fbc25bc7d7e5fe84 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 22:10:14 +0300 Subject: [PATCH 25/33] feat: lab03 completed --- .github/workflows/python-ci.yml | 8 +- app_python/README.md | 7 + app_python/docs/LAB03.md | 221 +++++++++++------- app_python/docs/screenshots/cache_hit.png | Bin 0 -> 57987 bytes app_python/docs/screenshots/cache_miss.png | Bin 0 -> 58760 bytes .../docs/screenshots/green-checkmark.png | Bin 9074 -> 0 bytes 6 files changed, 155 insertions(+), 81 deletions(-) create mode 100644 app_python/docs/screenshots/cache_hit.png create mode 100644 app_python/docs/screenshots/cache_miss.png delete mode 100644 app_python/docs/screenshots/green-checkmark.png diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index f6edc3c654..c7cd4a5081 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -3,7 +3,12 @@ name: Python ci on: push: - branches: [ "lab03" ] + branches: [ "lab03", "master" ] + paths: + - 'app_python/**' + - '.github/workflows/python-ci.yml' + pull_request: + branches: [ "lab03", "master" ] paths: - 'app_python/**' - '.github/workflows/python-ci.yml' @@ -54,6 +59,7 @@ jobs: docker: needs: [ test, security ] runs-on: ubuntu-latest + if: github.event_name == 'push' && (github.ref == 'refs/heads/lab03' || github.ref == 'refs/heads/master') steps: - uses: actions/checkout@v4 diff --git a/app_python/README.md b/app_python/README.md index 2475567ab9..4eb3540441 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -1,3 +1,5 @@ +[![Python CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml?query=branch%3Alab03) + # devops-info-service ## Overview @@ -64,3 +66,8 @@ Then run: docker run --rm -p : /: ``` +# Testing +To run test locally use command: +```bash +pytest +``` diff --git a/app_python/docs/LAB03.md b/app_python/docs/LAB03.md index aff1f98b7b..09c3e39c28 100644 --- a/app_python/docs/LAB03.md +++ b/app_python/docs/LAB03.md @@ -1,96 +1,58 @@ -# Unit Testing +# LAB03 — Unit Testing + CI/CD + Security -## Testing framework choice and why -After reviewing popular Python testing frameworks (such as `unittest` and `pytest`), I chose **pytest** because it makes writing, maintaining, and scaling tests easier and faster for both small and large projects. +## 1. Overview -### 1) Less boilerplate, faster to write tests -With `pytest`, you don’t need to create test classes or inherit from special base classes (which is common in `unittest`). -Simple functions named `test_*` are enough, which keeps tests clean and easy to read. +### Testing framework used and why you chose it -### 2) Powerful fixture system -`pytest` provides a strong **fixture** mechanism for setting up test data and environments: -- reusable setup/teardown logic; -- flexible scopes (`function`, `module`, `session`); -- dependency injection by simply adding parameters to test functions. +I chose **pytest** after comparing common Python testing frameworks (`unittest`, `pytest`, etc.). +Pytest requires less boilerplate, has powerful fixtures and parametrization, produces clear failure +output, and scales well with plugins and CI workflows. -This reduces duplication and improves test structure. +### What endpoints/functionality your tests cover -### 3) Easy test parametrization -`pytest` makes it simple to run the same test with multiple input datasets using parametrization. -That improves coverage without copying and pasting similar tests. +All tests are located in `app_python/tests/` and use FastAPI’s `TestClient`. The test suite covers: -### 4) Clear, helpful failure output -When a test fails, `pytest` produces detailed and readable error messages (including smart value comparisons). -This speeds up debugging and helps quickly identify what went wrong. +- **GET /** + Verifies status code `200`, JSON structure, required top-level + sections (`service`, `system`, `runtime`, `request`, `endpoints`), and important nested + fields/types. +- **GET /health** + Verifies status code `200`, required fields (`status`, `timestamp`, `uptime_seconds`), and basic + format checks. +- **Error cases** + - **404 Not Found** returns the custom + JSON `{ "error": "Not Found", "message": "Endpoint does not exist" }` + - **Non-404 HTTPException** returns `{ "error": "HTTP Error", "message": "" }` + - **500 Internal Server Error** + returns `{ "error": "Internal Server Error", "message": "An unexpected error occurred" }` -### 5) Rich plugin ecosystem and CI integration -`pytest` has a large ecosystem of plugins and integrates well with: -- coverage tools, -- linters, -- CI/CD systems (GitHub Actions, GitLab CI, etc.), -- reporting tools. +### CI workflow trigger configuration (when does it run?) -This is useful if the project grows or needs automation. +The GitHub Actions workflow runs on **push** and **pull requests** to `lab03` and `master`, but only +when changes affect: -### 6) Flexibility and compatibility -`pytest` can also run tests written in the `unittest` style, so it’s easier to adopt gradually. -At the same time, `pytest` offers more modern and flexible features for everyday testing. +- `app_python/**` +- `.github/workflows/python-ci.yml` ---- +This avoids unnecessary CI runs for unrelated edits. Docker images are built and pushed only on * +*push** events (not on pull requests). -**Conclusion:** I chose **pytest** because it reduces boilerplate, provides powerful fixtures and parametrization, offers excellent debugging output, and scales well with plugins and CI workflows. +### Versioning strategy chosen and rationale -## Test structure explanation +I use **CalVer (Calendar Versioning)** with format `YYYY.MM.DD` because this project is updated +frequently and doesn’t require manual git release tags. Date-based versions are simple, +human-readable, and work well for continuous delivery. -All tests are located in `app_python/tests/` and are written with **pytest** using FastAPI’s `TestClient`. +--- -### Directory layout -```text -app_python/ - app.py - tests/ - conftest.py - test_root.py - test_health.py - test_errors.py -``` +## 2. Workflow Evidence -### What each file contains -- `conftest.py` - - Defines shared pytest fixtures (e.g., `client`) used across multiple test files. - - The `client` fixture creates a `TestClient(app)` so tests can call the API endpoints without running a real server. -- `test_root.py` - - tests the main endpoint `GET /`. - - Verifies: - - HTTP status code is `200` - - JSON response contains required top-level fields (`service`, `system`, `runtime`, `request`, `endpoints`) - - Nested fields exist and have reasonable types/values (e.g., `uptime_seconds` is an `integer`, `timezone` is `"UTC"`) - - The endpoints list contains expected endpoints (`/` and `/health`) -- `test_health.py` - - Tests `GET /health`. - - Verifies: - - HTTP status code is `200` - - JSON response contains required fields (`status`, `timestamp`, `uptime_seconds`) - - status is `"healthy"` and `timestamp` is serialized as an ISO string -- test_errors.py - - Tests custom error handling: - - **500 Internal Server Error**: adds a temporary endpoint that raises `RuntimeError` and checks that the response JSON matches the global exception handler. - - **404 Not Found**: requests a non-existent endpoint and checks the custom 404 JSON. - - **Non-404 HTTPException**: adds a temporary endpoint that raises `HTTPException(418)` and checks the JSON returned by the `HTTPException` handler. - - Temporary test routes are removed in `finally` blocks to avoid affecting other tests. - -### Naming conventions -- Test files are named test_*.py -- Test functions are named test_* -- This allows pytest to automatically discover and run the test suite. - -## How to run tests locally -Use command: -```bash -pytest -``` +### ✅ Successful workflow run (GitHub Actions link) + +- https://github.com/newspec/DevOps-Core-Course/actions/runs/21822195126 + +### ✅ Tests passing locally (terminal output) -## Terminal output showing all tests passing ```bash pytest ========================================== test session starts =========================================== @@ -98,12 +60,111 @@ platform win32 -- Python 3.12.4, pytest-8.4.2, pluggy-1.6.0 rootdir: C:\Users\malov\PycharmProjects\DevOps-Core-Course plugins: anyio-4.11.0, asyncio-1.3.0, cov-7.0.0 asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function -collected 7 items +collected 7 items app_python\tests\test_errors.py ... [ 42%] app_python\tests\test_health.py .. [ 71%] app_python\tests\test_root.py .. [100%] =========================================== 7 passed in 0.48s ============================================ -(.venv) PS C:\Users\malov\PycharmProjects\DevOps-Core-Course> -``` \ No newline at end of file +``` + +### ✅ Docker image on Docker Hub (link to your image) + +- https://hub.docker.com/repository/docker/newspec/python_app/general + +### ✅ Status badge working in README + +Check the top page of README.md + +## 3. Best Practices Implemented + +- **Fail Fast**: If a step fails, the job stops immediately, saving CI time and making failures + obvious. + +- **Job Dependencies** : Docker push depends on successful `test` and `security` jobs, preventing + publishing broken/insecure builds. + +- **Dependency Caching (pip)**: `setup-python` caches pip downloads so installs are faster on + repeated runs. + +- **Docker Layer Caching**: Buildx + GHA cache reuses Docker layers across runs, reducing Docker + build time significantly. + +- **Secrets Management**: Tokens (Docker Hub + Snyk) are stored in GitHub Secrets and never + committed. + +### Caching: time saved (before vs after) + +Measured by comparing two workflow runs: + +- **Cold run (cache miss)**: 80s total + - tests: 14s + - security: 29s + - docker build: 41s + +- **Warm run (cache hit)**: 64s total + - tests: 11s + - security: 22s + - docker build: 30s + +**Improvement**: + +- Total time saved: **16s** +- Docker build time saved: **11s** +- Percent improvement: **~20%** + +Evidence (screenshots): + +- First run (no cache): ![cache_miss.png](screenshots/cache_miss.png) +- Second run (cache hit): ![cache_hit.png](screenshots/cache_hit.png) + +### Snyk: vulnerabilities found? action taken + +Snyk is executed in a separate `security` job using: + +```bash +snyk test --severity-threshold=high +``` + +- If `high` (or above) vulnerabilities are found, the security job fails. +- Because Docker depends on `security`, the image will **not be pushed** until vulnerabilities are + fixed or the threshold is adjusted. + +**Snyk result**: 0 high/critical vulnerabilities (build passed) + +## Key Decisions + +### Versioning Strategy: SemVer or CalVer? Why did you choose it for your app? + +I chose **CalVer** (`YYYY.MM.DD`) because the application is built frequently and does not follow +formal release cycles. Date-based versioning is easy to automate in CI and provides clear +information about when an image was built. + +### Docker Tags: What tags does your CI create? (e.g., latest, version number, etc.) + +The CI publishes the Docker image with these tags: + +- `YYYY.MM.DD` (CalVer date tag) — e.g., `2026.02.09` +- `${{ github.sha }}` (commit SHA tag) — uniquely identifies the build source commit +- `latest` — points to the most recent image build from the `lab03` or `master` branch + +### Workflow Triggers: Why did you choose those triggers? + +The workflow runs on push and pull request to `lab03` and `master` and only when relevant files +change. This avoids running CI for unrelated edits. Docker images are built and pushed only on push +events (not on pull requests) for `lab03` and `master`. + +### Test Coverage: What's tested vs not tested? + +**Tested**: + +- Successful responses for `GET /` and `GET /health` +- Response JSON structure and required fields +- Custom error handling for 404, non-404 `HTTPException`, and 500 errors + +**Not tested**: + +- Performance/load behavior +- External integrations (none in this app) +- Detailed validation of dynamic fields beyond basic format/type checks (e.g., exact timestamps) \ No newline at end of file diff --git a/app_python/docs/screenshots/cache_hit.png b/app_python/docs/screenshots/cache_hit.png new file mode 100644 index 0000000000000000000000000000000000000000..cf23e1e1a94a6dca973a6406e23b24f187a1483b GIT binary patch literal 57987 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 literal 0 HcmV?d00001 diff --git a/app_python/docs/screenshots/cache_miss.png b/app_python/docs/screenshots/cache_miss.png new file mode 100644 index 0000000000000000000000000000000000000000..a03f43a091fd18d8bd3ac17a9ca2455d112fca25 GIT binary patch literal 58760 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 B@0S1o From 55afb8da031104278bd2afaf9de2cacf550c0bd3 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 22:34:54 +0300 Subject: [PATCH 26/33] only go file changed --- .github/workflows/go-ci.yml | 97 +++++++++++++++++++++++++++++++++++++ app_go/README.md | 2 + 2 files changed, 99 insertions(+) create mode 100644 .github/workflows/go-ci.yml diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml new file mode 100644 index 0000000000..8ba9be0578 --- /dev/null +++ b/.github/workflows/go-ci.yml @@ -0,0 +1,97 @@ +name: Go ci + +on: + push: + branches: ["lab03", "master"] + paths: + - "app_go/**" + - ".github/workflows/go-ci.yml" + pull_request: + branches: ["lab03", "master"] + paths: + - "app_go/**" + - ".github/workflows/go-ci.yml" + +jobs: + test: + runs-on: ubuntu-latest + defaults: + run: + working-directory: app_go + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: "1.22" + cache: true + + - name: Go fmt check + run: | + test -z "$(gofmt -l .)" + + - name: Run tests with coverage + run: go test -coverprofile=coverage.out ./... + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: go-coverage + path: app_go/coverage.out + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: app_go/coverage.out + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + lint: + runs-on: ubuntu-latest + defaults: + run: + working-directory: app_go + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: "1.22" + cache: true + + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: v1.61.0 + working-directory: app_go + + docker: + needs: [test, lint] + runs-on: ubuntu-latest + if: github.event_name == 'push' && (github.ref == 'refs/heads/lab03' || github.ref == 'refs/heads/master') + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Generate version + run: echo "VERSION=$(date -u +%Y.%m.%d)" >> $GITHUB_ENV + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./app_go + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/go_app:${{ env.VERSION }} + ${{ secrets.DOCKER_USERNAME }}/go_app:${{ github.sha }} + ${{ secrets.DOCKER_USERNAME }}/go_app:latest + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/app_go/README.md b/app_go/README.md index e53cc9a7e6..d2b0230888 100644 --- a/app_go/README.md +++ b/app_go/README.md @@ -1,3 +1,5 @@ +[![Go CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml?query=branch%3Alab03) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course) # devops-info-service (Go) ## Overview From be33caeb656ddd3737bd48fc09f437e3651a6213 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 22:39:41 +0300 Subject: [PATCH 27/33] Only python file changed --- .github/workflows/python-ci.yml | 10 +++++++++- app_python/README.md | 1 + app_python/requirements.txt | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index c7cd4a5081..54eacc9e95 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -31,7 +31,15 @@ jobs: run: flake8 - name: Run tests - run: pytest + run: pytest --cov=. --cov-report=xml:coverage.xml --cov-report=term + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + files: app_python/coverage.xml + fail_ci_if_error: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} security: runs-on: ubuntu-latest diff --git a/app_python/README.md b/app_python/README.md index 4eb3540441..76ebbf74c5 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -1,4 +1,5 @@ [![Python CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml?query=branch%3Alab03) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course) # devops-info-service diff --git a/app_python/requirements.txt b/app_python/requirements.txt index 170f1dfdce..c6245af3cf 100644 --- a/app_python/requirements.txt +++ b/app_python/requirements.txt @@ -3,3 +3,4 @@ uvicorn[standard]==0.38.0 pytest==8.4.2 flake8==7.3.0 httpx==0.28.1 +pytest-cov==7.0.0 From 1f09d67786bca475ae376ef9e8eb89925b048441 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 22:45:16 +0300 Subject: [PATCH 28/33] only python files changes --- .github/workflows/python-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 54eacc9e95..8c5cec5f4b 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -31,6 +31,7 @@ jobs: run: flake8 - name: Run tests + working-directory: app_python run: pytest --cov=. --cov-report=xml:coverage.xml --cov-report=term - name: Upload coverage to Codecov From ff1f215a3863cb45eebdace34c44cb0b94a4c23a Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 22:49:16 +0300 Subject: [PATCH 29/33] both python and go files changed --- app_go/README.md | 2 +- app_python/README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app_go/README.md b/app_go/README.md index d2b0230888..6d97b75bc3 100644 --- a/app_go/README.md +++ b/app_go/README.md @@ -42,4 +42,4 @@ The application is configured using environment variables. | Variable | Default | Description | Example | |---------|---------|-------------|---------| | `HOST` | `0.0.0.0` | Host interface to bind the server to | `0.0.0.0` | -| `PORT` | `8080` | Port the server listens on | `8080` | \ No newline at end of file +| `PORT` | `8080` | Port the server listens on | `8080` | diff --git a/app_python/README.md b/app_python/README.md index 76ebbf74c5..4853c7205a 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -72,3 +72,4 @@ To run test locally use command: ```bash pytest ``` + From 8e5eecec72e628db6a6e4a5e5bbd8977d47a153f Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 23:03:44 +0300 Subject: [PATCH 30/33] fix (codecov): report links and flags --- .github/workflows/go-ci.yml | 1 + .github/workflows/python-ci.yml | 1 + app_go/README.md | 2 +- app_python/README.md | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 8ba9be0578..841fc460ba 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -38,6 +38,7 @@ jobs: with: name: go-coverage path: app_go/coverage.out + flags: go - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 8c5cec5f4b..7847aee837 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -39,6 +39,7 @@ jobs: with: files: app_python/coverage.xml fail_ci_if_error: true + flags: python env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/app_go/README.md b/app_go/README.md index 6d97b75bc3..507bda3303 100644 --- a/app_go/README.md +++ b/app_go/README.md @@ -1,5 +1,5 @@ [![Go CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml?query=branch%3Alab03) -[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course?flag=go) # devops-info-service (Go) ## Overview diff --git a/app_python/README.md b/app_python/README.md index 4853c7205a..98483a5a73 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -1,5 +1,5 @@ [![Python CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml?query=branch%3Alab03) -[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course?flag=python) # devops-info-service From 88ca03ed63e482cfcc00a62b43bc142ae4bafb2d Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 23:11:58 +0300 Subject: [PATCH 31/33] fix (codecod): paths --- .github/workflows/go-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 841fc460ba..41295a924c 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -31,6 +31,7 @@ jobs: test -z "$(gofmt -l .)" - name: Run tests with coverage + working-directory: app_go run: go test -coverprofile=coverage.out ./... - name: Upload coverage artifact From 0bdb02420a40ebfa32f17262de9ff930b2a357cb Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 23:25:47 +0300 Subject: [PATCH 32/33] fixes --- .github/workflows/go-ci.yml | 4 +-- .github/workflows/python-ci.yml | 2 +- app_go/main_test.go | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 app_go/main_test.go diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 41295a924c..3fdc914fb8 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -39,12 +39,12 @@ jobs: with: name: go-coverage path: app_go/coverage.out - flags: go - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: app_go/coverage.out + flags: go env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 7847aee837..f0ed5ca75c 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -35,7 +35,7 @@ jobs: run: pytest --cov=. --cov-report=xml:coverage.xml --cov-report=term - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v5 with: files: app_python/coverage.xml fail_ci_if_error: true diff --git a/app_go/main_test.go b/app_go/main_test.go new file mode 100644 index 0000000000..a273d1f240 --- /dev/null +++ b/app_go/main_test.go @@ -0,0 +1,56 @@ +package main + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" +) + +func TestRootOK(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/", nil) + rr := httptest.NewRecorder() + + mainHandler(rr, req) + + if rr.Code != http.StatusOK { + t.Fatalf("expected 200, got %d", rr.Code) + } + + var data map[string]any + if err := json.Unmarshal(rr.Body.Bytes(), &data); err != nil { + t.Fatalf("invalid json: %v", err) + } + + // top-level keys + for _, k := range []string{"service", "system", "runtime", "request", "endpoints"} { + if _, ok := data[k]; !ok { + t.Fatalf("missing key: %s", k) + } + } +} + +func TestHealthOK(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/health", nil) + rr := httptest.NewRecorder() + + healthHandler(rr, req) + + if rr.Code != http.StatusOK { + t.Fatalf("expected 200, got %d", rr.Code) + } + + var data map[string]any + if err := json.Unmarshal(rr.Body.Bytes(), &data); err != nil { + t.Fatalf("invalid json: %v", err) + } + + for _, k := range []string{"status", "timestamp", "uptime_seconds"} { + if _, ok := data[k]; !ok { + t.Fatalf("missing key: %s", k) + } + } + if data["status"] != "healthy" { + t.Fatalf("expected status healthy, got %v", data["status"]) + } +} From 6ae7df78ba815adea0a866a180e0ae3481ee5a12 Mon Sep 17 00:00:00 2001 From: Maksim Malov Date: Mon, 9 Feb 2026 23:59:11 +0300 Subject: [PATCH 33/33] feat: lab03 bonus task completed --- app_go/README.md | 4 +- app_go/docs/LAB03.md | 86 ++++++++++++++++++ app_go/docs/screenshots/coverage.png | Bin 0 -> 42943 bytes .../screenshots/proof_of_path_validations.png | Bin 0 -> 45844 bytes app_python/README.md | 3 +- 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 app_go/docs/LAB03.md create mode 100644 app_go/docs/screenshots/coverage.png create mode 100644 app_go/docs/screenshots/proof_of_path_validations.png diff --git a/app_go/README.md b/app_go/README.md index 507bda3303..f2870f9688 100644 --- a/app_go/README.md +++ b/app_go/README.md @@ -1,5 +1,7 @@ [![Go CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/go-ci.yml?query=branch%3Alab03) -[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course?flag=go) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg?flag=go)](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03?flag=go) + + # devops-info-service (Go) ## Overview diff --git a/app_go/docs/LAB03.md b/app_go/docs/LAB03.md new file mode 100644 index 0000000000..e039089a71 --- /dev/null +++ b/app_go/docs/LAB03.md @@ -0,0 +1,86 @@ +# LAB03 (Go) — Bonus: Multi-App CI + Path Filters + Coverage + +## 1) Second workflow implementation (Go CI) + language-specific best practices + +A separate workflow file is added for the Go application: + +- `.github/workflows/go-ci.yml` + +It implements Go-specific CI best practices: + +- **Setup Go toolchain** via `actions/setup-go` (Go 1.22+) +- **Formatting check**: `gofmt -l .` must return empty output +- **Linting**: `golangci-lint` (industry-standard Go linter aggregator) +- **Unit tests**: `go test ./...` +- **Coverage generation**: `go test -coverprofile=coverage.out ./...` +- **Docker build/push**: multi-stage Docker build using the existing `app_go/Dockerfile` (builder stage + distroless runtime) + +Docker image tagging follows the same CalVer strategy as Python: + +- `YYYY.MM.DD` (CalVer) +- `${GITHUB_SHA}` (commit SHA) +- `latest` + +## 2) Path filter configuration + testing proof + +The Go workflow is triggered only when Go-related files change: + +- `app_go/**` +- `.github/workflows/go-ci.yml` + +This prevents unnecessary CI runs for unrelated parts of the monorepo. + +### Proof (selective triggering) + +Provide evidence with 2 small commits: + +1) **Change only Go files** + - https://github.com/newspec/DevOps-Core-Course/actions/runs/21837847722 + +2) **Change only Python files** + - https://github.com/newspec/DevOps-Core-Course/actions/runs/21838134121 + +## 3) Benefits analysis — why path filters matter in monorepos + +Path filters are important in monorepos because they: + +- **Save CI time and compute**: no need to run Go CI when only Python changes (and vice versa) +- **Reduce noise in PR checks**: fewer irrelevant checks, faster feedback for reviewers +- **Improve developer experience**: faster iteration and fewer “unrelated failures” +- **Scale better** as more apps/labs are added to the same repository + +## 4) Example showing workflows running independently + +Example scenario: + +- Commit A modifies only `app_go/**` → only Go CI runs +- Commit B modifies only `app_python/**` → only Python CI runs +- Commit C modifies both `app_go/**` and `app_python/**` → both workflows run in parallel + +![screenshots/proof_of_path_validations.png](screenshots/proof_of_path_validations.png) + +## 5) Terminal output / Actions evidence (selective triggering) + +See links and screenshot above. + +## 6) Coverage integration (dashboard link / screenshot) +![screenshots/coverage.png](screenshots/coverage.png) + +## 7) Coverage analysis (current percentage, covered/not covered, threshold) + +### Current coverage + +Current Go coverage: 44% +Current Python coverage 99% + +### What is covered (Go) +- `GET /` handler (`mainHandler`) returns status `200` and contains required top-level JSON keys: + `service`, `system`, `runtime`, `request`, `endpoints` +- `GET /health` handler (`healthHandler`) returns status `200` and contains required keys: + `status`, `timestamp`, `uptime_seconds` + +### What is not covered (Go) +- Middleware behavior (`withRecover`, `withLogging`, `withNotFound`) +- Negative/error scenarios (e.g., unknown path via middleware, panic recovery) +- Strict validation of dynamic fields (timestamps formatting beyond basic checks) + diff --git a/app_go/docs/screenshots/coverage.png b/app_go/docs/screenshots/coverage.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9c2434ef5561d8ad71219c0dd60feb65326e66 GIT binary patch literal 42943 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

BBx%uin@b>EWKGniiHK5;jhWWKC?xA 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 a_MW7XxpG;vG%fy2K3y}m1mg@{qy7VkqgyBd literal 0 HcmV?d00001 diff --git a/app_go/docs/screenshots/proof_of_path_validations.png b/app_go/docs/screenshots/proof_of_path_validations.png new file mode 100644 index 0000000000000000000000000000000000000000..00df9e79978dfaf9c6aba5e0b623f4f8dced5fc8 GIT binary patch literal 45844 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 SNCCksz)*XprBtS18T2o!0y0wo literal 0 HcmV?d00001 diff --git a/app_python/README.md b/app_python/README.md index 98483a5a73..170f1cac89 100644 --- a/app_python/README.md +++ b/app_python/README.md @@ -1,5 +1,6 @@ [![Python CI](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml/badge.svg?branch=lab03)](https://github.com/newspec/DevOps-Core-Course/actions/workflows/python-ci.yml?query=branch%3Alab03) -[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg)](https://codecov.io/gh/newspec/DevOps-Core-Course?flag=python) +[![Coverage](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03/graph/badge.svg?flag=python)](https://codecov.io/gh/newspec/DevOps-Core-Course/branch/lab03?flag=python) + # devops-info-service