Skip to content
Open

Lab18 #4531

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5f5b815
feat: implement lab01 devops info service
Jan 28, 2026
83f6401
feat(lab02): add Docker containerization for Python app
Feb 4, 2026
08024a4
feat(ci): add python workflow with tests and docker calver tags
Feb 10, 2026
8e1a5a7
fix(ci): run tests on all branches
Feb 10, 2026
3a2113e
chore(ci): allow docker push from lab03
Feb 10, 2026
38b6414
fix(ci): login to Docker Hub
Feb 10, 2026
4fc4df1
chore(ci): rerun workflow with Snyk
Feb 10, 2026
a1453bf
Task 3: Snyk
Feb 10, 2026
76306cf
fix(ci): use env for snyk token and document cache speedup
Feb 10, 2026
790e3c9
fix(ci): snyk
Feb 10, 2026
4a11349
fix(ci): use snyk python action
Feb 10, 2026
9d93861
fix(ci): use snyk python action
Feb 10, 2026
3809b70
fix(ci): use snyk python action
Feb 11, 2026
edfef62
The final version of the report
Feb 11, 2026
24965ed
feat: add Lab 4 infrastructure as code (Terraform & Pulumi)
Feb 19, 2026
ea2a307
Lab05 - ansible fundamentals
Feb 24, 2026
305d8ba
Test task 4
Mar 12, 2026
f18eb92
Test task 4
Mar 12, 2026
66f937d
Test task 4
Mar 12, 2026
1a12740
Test task 4
Mar 12, 2026
ee27655
Lab 06
Mar 12, 2026
dd604ba
Lab 7
Mar 12, 2026
d9d80fa
Lab08: add Prometheus + Grafana dashboards
Mar 18, 2026
03d48b7
Lab08: add Prometheus + Grafana dashboards
Mar 18, 2026
7e12eeb
Lab 9
Mar 25, 2026
60cc19f
Lab 10
Apr 2, 2026
33e40f1
Lab11
Apr 9, 2026
d9974c8
Lab12
Apr 16, 2026
ee95eac
Add ArgoCD application manifest for lab13 task2
Apr 23, 2026
f8553df
Add ArgoCD application manifest for lab13 task2
Apr 23, 2026
6477475
Fix ArgoCD app sync by overriding nodePort to 30084
Apr 23, 2026
395bf43
Adjust ArgoCD prod app service type for Minikube health checks
Apr 23, 2026
ad301a1
Lab13
Apr 23, 2026
3d33bfa
Lab14
Apr 26, 2026
00ef17f
Lab15
May 1, 2026
a3962db
Lab16
May 2, 2026
ffff7e7
Lab17
May 14, 2026
4c8fcde
Lab 18: Nix flake, lock, app_python and submission template
May 14, 2026
a1482bc
Lab18
May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions .github/workflows/ansible-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Ansible Deployment

on:
workflow_dispatch:
push:
branches: [ main, master, lab06 ]
paths:
- "ansible/**"
- ".github/workflows/ansible-deploy.yml"
pull_request:
branches: [ main, master ]
paths:
- "ansible/**"
- ".github/workflows/ansible-deploy.yml"

permissions:
contents: read

env:
ANSIBLE_DIR: ansible
APP_PORT: "5000"

jobs:
lint:
name: Ansible Lint
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.ANSIBLE_DIR }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install Ansible and ansible-lint
run: |
python -m pip install --upgrade pip
pip install ansible ansible-lint
ansible-galaxy collection install -r requirements.yml

- name: Run ansible-lint
run: |
ansible-lint playbooks/*.yml \
-x yaml[truthy],yaml[line-length],yaml[empty-lines],var-naming,key-order,name,ignore-errors,no-changed-when,fqcn,command-instead-of-module

deploy:
name: Deploy Application
needs: lint
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ env.ANSIBLE_DIR }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Validate required deploy secrets
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
VM_HOST: ${{ secrets.VM_HOST }}
VM_USER: ${{ secrets.VM_USER }}
run: |
missing=0
[ -z "$SSH_PRIVATE_KEY" ] && echo "Missing secret: SSH_PRIVATE_KEY" && missing=1
[ -z "$VM_HOST" ] && echo "Missing secret: VM_HOST" && missing=1
[ -z "$VM_USER" ] && echo "Missing secret: VM_USER" && missing=1
if [ "$missing" -eq 1 ]; then
echo "Required deploy secrets are not configured."
exit 1
fi

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install Ansible and collections
run: |
python -m pip install --upgrade pip
pip install ansible
ansible-galaxy collection install -r requirements.yml

- name: Setup SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
VM_HOST: ${{ secrets.VM_HOST }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H "$VM_HOST" >> ~/.ssh/known_hosts

- name: Prepare Ansible Vault password file (optional)
env:
ANSIBLE_VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }}
run: |
if [ -n "$ANSIBLE_VAULT_PASSWORD" ]; then
echo "$ANSIBLE_VAULT_PASSWORD" > /tmp/vault_pass
fi

- name: Deploy with Ansible
env:
VM_HOST: ${{ secrets.VM_HOST }}
VM_USER: ${{ secrets.VM_USER }}
run: |
if [ -f /tmp/vault_pass ]; then
ansible-playbook playbooks/deploy.yml \
-i inventory/hosts.ini \
--vault-password-file /tmp/vault_pass
else
ansible-playbook playbooks/deploy.yml \
-i inventory/hosts.ini
fi

- name: Cleanup Vault password file
if: always()
run: |
rm -f /tmp/vault_pass

- name: Verify Deployment
env:
VM_HOST: ${{ secrets.VM_HOST }}
run: |
sleep 10
curl -f "http://${VM_HOST}:${APP_PORT}/" >/dev/null
curl -f "http://${VM_HOST}:${APP_PORT}/health" >/dev/null

107 changes: 107 additions & 0 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Python CI (app_python)

on:
push:
# Run tests on any branch when Python app or workflow changes
branches:
- "**"
paths:
- "app_python/**"
- ".github/workflows/python-ci.yml"
pull_request:
branches:
- "**"
paths:
- "app_python/**"
- ".github/workflows/python-ci.yml"

permissions:
contents: read

env:
PYTHON_APP_DIR: app_python
IMAGE_NAME: devops-info-service

jobs:
test:
name: Lint & Test (pytest)
runs-on: ubuntu-latest
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
defaults:
run:
working-directory: ${{ env.PYTHON_APP_DIR }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: |
app_python/requirements.txt
app_python/requirements-dev.txt

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt

- name: Security scan (Snyk)
if: ${{ env.SNYK_TOKEN != '' }}
uses: snyk/actions/python@master
with:
command: test
args: --file=app_python/requirements.txt --package-manager=pip --skip-unresolved=true

- name: Lint (ruff)
run: |
ruff check .

- name: Unit tests (pytest)
run: |
pytest

docker:
name: Docker build & push (CalVer)
runs-on: ubuntu-latest
needs: test
# Only publish images from main/master/lab03 branches on push
if: >
github.event_name == 'push' &&
(github.ref == 'refs/heads/master' ||
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/lab03')
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Compute CalVer tags (UTC)
id: calver
run: |
echo "date=$(date -u +'%Y.%m.%d')" >> "$GITHUB_OUTPUT"
echo "month=$(date -u +'%Y.%m')" >> "$GITHUB_OUTPUT"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: ./${{ env.PYTHON_APP_DIR }}
file: ./${{ env.PYTHON_APP_DIR }}/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}:${{ steps.calver.outputs.date }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}:${{ steps.calver.outputs.month }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}:latest
27 changes: 26 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
test
# Terraform (root-level convenience; also see terraform/.gitignore)
*.tfstate
*.tfstate.*
.terraform/
.terraform.lock.hcl
terraform.tfvars
*.tfvars
*.tfvars.json

# Credentials / keys (keep patterns narrow to avoid hiding legit JSON)
*.pem
*.key
credentials
terraform/*.json
terraform/**/*.json

# Pulumi
pulumi/venv/
Pulumi.*.yaml
.pulumi/

# Ansible
*.retry
.vault_pass
ansible/inventory/*.pyc
__pycache__/
Loading