Skip to content

Commit 0892ae9

Browse files
authored
Merge pull request #5 from Linktur/lab04
Lab04
2 parents 6bdeabd + feb16e7 commit 0892ae9

42 files changed

Lines changed: 1486 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/python-ci.yml

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: Python CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- main
8+
- lab03
9+
paths:
10+
- 'Lab-1/app_python/**'
11+
- '.github/workflows/python-ci.yml'
12+
pull_request:
13+
branches:
14+
- master
15+
- main
16+
paths:
17+
- 'Lab-1/app_python/**'
18+
- '.github/workflows/python-ci.yml'
19+
20+
concurrency:
21+
group: python-ci-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
quality:
29+
name: Lint and tests (Python ${{ matrix.python-version }})
30+
runs-on: ubuntu-latest
31+
strategy:
32+
fail-fast: true
33+
matrix:
34+
python-version: ['3.11', '3.12']
35+
36+
defaults:
37+
run:
38+
working-directory: Lab-1/app_python
39+
40+
steps:
41+
- name: Checkout source
42+
uses: actions/checkout@v4
43+
44+
- name: Set up Python ${{ matrix.python-version }}
45+
uses: actions/setup-python@v5
46+
with:
47+
python-version: ${{ matrix.python-version }}
48+
cache: pip
49+
cache-dependency-path: |
50+
Lab-1/app_python/requirements.txt
51+
Lab-1/app_python/requirements-dev.txt
52+
53+
- name: Install dependencies
54+
run: pip install -r requirements.txt -r requirements-dev.txt
55+
56+
- name: Lint with Ruff
57+
run: ruff check .
58+
59+
- name: Run tests with coverage
60+
run: pytest --cov=. --cov-report=term-missing --cov-fail-under=70
61+
62+
security:
63+
name: Snyk dependency scan
64+
runs-on: ubuntu-latest
65+
needs: quality
66+
67+
steps:
68+
- name: Checkout source
69+
uses: actions/checkout@v4
70+
71+
- name: Set up Python 3.12
72+
uses: actions/setup-python@v5
73+
with:
74+
python-version: '3.12'
75+
76+
- name: Install dependencies
77+
working-directory: Lab-1/app_python
78+
run: pip install -r requirements.txt
79+
80+
- name: Run Snyk scan
81+
if: ${{ secrets.SNYK_TOKEN != '' }}
82+
uses: snyk/actions/python@master
83+
continue-on-error: true
84+
env:
85+
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
86+
with:
87+
command: test
88+
args: --file=Lab-1/app_python/requirements.txt --severity-threshold=high
89+
90+
- name: Snyk token is missing
91+
if: ${{ secrets.SNYK_TOKEN == '' }}
92+
run: echo "SNYK_TOKEN is not configured. Security scan skipped."
93+
94+
docker:
95+
name: Build and push Docker image
96+
runs-on: ubuntu-latest
97+
needs:
98+
- quality
99+
- security
100+
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main')
101+
102+
steps:
103+
- name: Checkout source
104+
uses: actions/checkout@v4
105+
106+
- name: Set up Docker Buildx
107+
uses: docker/setup-buildx-action@v3
108+
109+
- name: Log in to Docker Hub
110+
uses: docker/login-action@v3
111+
with:
112+
username: ${{ secrets.DOCKERHUB_USERNAME }}
113+
password: ${{ secrets.DOCKERHUB_TOKEN }}
114+
115+
- name: Generate CalVer tags
116+
run: |
117+
echo "CALVER=$(date -u +'%Y.%m.%d').${GITHUB_RUN_NUMBER}" >> "$GITHUB_ENV"
118+
echo "CALVER_MONTH=$(date -u +'%Y.%m')" >> "$GITHUB_ENV"
119+
120+
- name: Build and push image
121+
uses: docker/build-push-action@v6
122+
with:
123+
context: ./Lab-1/app_python
124+
file: ./Lab-1/app_python/Dockerfile
125+
push: true
126+
tags: |
127+
${{ secrets.DOCKERHUB_USERNAME }}/devops-lab2:${{ env.CALVER }}
128+
${{ secrets.DOCKERHUB_USERNAME }}/devops-lab2:${{ env.CALVER_MONTH }}
129+
${{ secrets.DOCKERHUB_USERNAME }}/devops-lab2:latest
130+
cache-from: type=gha
131+
cache-to: type=gha,mode=max

.github/workflows/terraform-ci.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Terraform Validate
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- main
8+
- lab04
9+
paths:
10+
- 'terraform/**'
11+
- '.github/workflows/terraform-ci.yml'
12+
pull_request:
13+
branches:
14+
- master
15+
- main
16+
paths:
17+
- 'terraform/**'
18+
- '.github/workflows/terraform-ci.yml'
19+
20+
concurrency:
21+
group: terraform-ci-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
validate:
29+
runs-on: ubuntu-latest
30+
strategy:
31+
fail-fast: true
32+
matrix:
33+
workdir:
34+
- terraform
35+
- terraform/github-import
36+
37+
steps:
38+
- name: Checkout source
39+
uses: actions/checkout@v4
40+
41+
- name: Setup Terraform
42+
uses: hashicorp/setup-terraform@v3
43+
with:
44+
terraform_version: 1.9.8
45+
46+
- name: Setup TFLint
47+
uses: terraform-linters/setup-tflint@v4
48+
49+
- name: Check Terraform formatting
50+
run: terraform fmt -check -recursive
51+
52+
- name: Terraform init
53+
working-directory: ${{ matrix.workdir }}
54+
run: terraform init -backend=false
55+
56+
- name: Terraform validate
57+
working-directory: ${{ matrix.workdir }}
58+
run: terraform validate
59+
60+
- name: Initialize TFLint plugins
61+
working-directory: ${{ matrix.workdir }}
62+
run: tflint --init
63+
64+
- name: Run TFLint
65+
working-directory: ${{ matrix.workdir }}
66+
run: tflint --format compact

.gitignore

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,34 @@
1-
test
1+
test
2+
3+
# Terraform
4+
*.tfstate
5+
*.tfstate.*
6+
.terraform/
7+
.terraform.lock.hcl
8+
terraform.tfvars
9+
*.tfvars
10+
crash.log
11+
override.tf
12+
override.tf.json
13+
*_override.tf
14+
*_override.tf.json
15+
16+
# Pulumi
17+
.pulumi/
18+
Pulumi.*.yaml
19+
pulumi/venv/
20+
21+
# Python caches
22+
.pytest_cache/
23+
.ruff_cache/
24+
.coverage
25+
**/__pycache__/
26+
**/*.pyc
27+
28+
# Credentials and keys
29+
*.pem
30+
*.key
31+
*.p12
32+
*.jks
33+
*.json
34+
credentials

Lab-1/app_python/.coverage

52 KB
Binary file not shown.

Lab-1/app_python/.dockerignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
__pycache__/
2+
*.py[cod]
3+
*.log
4+
.env
5+
venv/
6+
.venv/
7+
.git/
8+
.gitignore
9+
.vscode/
10+
.idea/
11+
docs/
12+
tests/
13+
README.md

Lab-1/app_python/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
venv/
5+
*.log
6+
.env
7+
8+
# IDE
9+
.vscode/
10+
.idea/
11+
12+
# OS
13+
.DS_Store

Lab-1/app_python/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM python:3.13-slim
2+
3+
ENV PYTHONDONTWRITEBYTECODE=1 \
4+
PYTHONUNBUFFERED=1
5+
6+
WORKDIR /app
7+
8+
RUN addgroup --system app && adduser --system --ingroup app app
9+
10+
COPY requirements.txt .
11+
RUN pip install --no-cache-dir -r requirements.txt
12+
13+
COPY app.py .
14+
15+
EXPOSE 5000
16+
17+
USER app
18+
19+
CMD ["python", "app.py"]

Lab-1/app_python/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# DevOps Info Service (Flask)
2+
[![Python CI/CD](https://github.com/Linktur/DevOps-Core-Course/actions/workflows/python-ci.yml/badge.svg?branch=master)](https://github.com/Linktur/DevOps-Core-Course/actions/workflows/python-ci.yml)
3+
4+
## Overview
5+
A small Flask web service that reports service metadata, system information, runtime details, and request context. It also exposes a health check endpoint and Swagger UI.
6+
7+
## Prerequisites
8+
- Python 3.11+
9+
- pip
10+
11+
## Installation
12+
```bash
13+
python -m venv venv
14+
# Linux/macOS
15+
source venv/bin/activate
16+
# Windows PowerShell
17+
.\venv\Scripts\Activate.ps1
18+
19+
pip install -r requirements.txt
20+
```
21+
22+
## Configuration via .env (optional)
23+
Create a `.env` file in `app_python/`:
24+
```env
25+
HOST=0.0.0.0
26+
PORT=5000
27+
DEBUG=false
28+
```
29+
30+
## Running the Application
31+
```bash
32+
python app.py
33+
```
34+
35+
With custom configuration:
36+
```bash
37+
PORT=8080 python app.py
38+
HOST=127.0.0.1 PORT=3000 DEBUG=true python app.py
39+
```
40+
41+
Windows PowerShell:
42+
```powershell
43+
$env:PORT=8080; python app.py
44+
$env:HOST='127.0.0.1'; $env:PORT=3000; $env:DEBUG='true'; python app.py
45+
```
46+
47+
## Docker
48+
Build image (pattern):
49+
```bash
50+
docker build -t linktur/devops-lab2:v1 .
51+
```
52+
53+
Run container (pattern):
54+
```bash
55+
docker run --rm -p 5000:5000 --name devops-lab2 linktur/devops-lab2:v1
56+
```
57+
58+
Pull from Docker Hub (pattern):
59+
```bash
60+
docker pull linktur/devops-lab2:v1
61+
```
62+
63+
## API Endpoints
64+
- `GET /` - Service and system information
65+
- `GET /health` - Health check
66+
- `GET /swagger.json` - OpenAPI spec
67+
- `GET /docs` - Swagger UI
68+
69+
## Local Quality Checks
70+
Install development dependencies:
71+
```bash
72+
pip install -r requirements.txt -r requirements-dev.txt
73+
```
74+
75+
Run linter:
76+
```bash
77+
ruff check .
78+
```
79+
80+
Run unit tests:
81+
```bash
82+
pytest
83+
```
84+
85+
Run tests with coverage threshold (same as CI):
86+
```bash
87+
pytest --cov=. --cov-report=term-missing --cov-fail-under=70
88+
```
89+
90+
## Configuration
91+
| Variable | Default | Description |
92+
|---|---|---|
93+
| `HOST` | `0.0.0.0` | Bind address |
94+
| `PORT` | `5000` | HTTP port |
95+
| `DEBUG` | `False` | Flask debug mode (`true`/`false`) |

0 commit comments

Comments
 (0)