Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e0fd247
feat: complete lab-01
peplxx Jan 28, 2026
a6f85dd
feat: complete lab-01 bonus task
peplxx Jan 28, 2026
bcc72fa
feat: complete lab-01 + bonus
peplxx Jan 28, 2026
8ac8690
feat: complete lab02 base tasks
peplxx Feb 4, 2026
45fe9e0
feat: get ziggy with it
peplxx Feb 4, 2026
5e36b06
feat: upload screenshots
peplxx Feb 4, 2026
4a63ef0
Merge pull request #2 from peplxx/feat/lab02
peplxx Feb 4, 2026
98f6ecf
feat: complete lab3
peplxx Feb 11, 2026
d92359e
Merge pull request #3 from peplxx/feat/lab3
peplxx Feb 11, 2026
9880b11
feat: complete task1 (terraform)
peplxx Feb 19, 2026
bd5584d
chore: move docs dir upload screenshots
peplxx Feb 19, 2026
2237a0e
feat: add pulumi finalize lab
peplxx Feb 19, 2026
75fd41d
chore: add yandex provider version
peplxx Feb 19, 2026
0c32a7f
Merge pull request #4 from peplxx/feat/lab4
peplxx Feb 19, 2026
9d18202
feat: complete lab5
peplxx Feb 25, 2026
7451e76
merge: complete lab5
peplxx Feb 25, 2026
20d1dee
Merge branch 'inno-devops-labs:master' into master
peplxx Feb 25, 2026
edcc838
feat: complete lab6 task
peplxx Mar 5, 2026
769f22c
feat: add docs for lab6
peplxx Mar 5, 2026
b298595
merge: complete lab6
peplxx Mar 5, 2026
b4fabc1
feat: finalize lab
peplxx Mar 5, 2026
a43189d
Merge pull request #7 from peplxx/feat/lab6
peplxx Mar 5, 2026
ec16bd9
feat: complete fist part
peplxx Mar 12, 2026
127134b
feat: complete last part + screenshots
peplxx Mar 12, 2026
2d50703
Merge pull request #8 from peplxx/feat/lab7
peplxx Mar 12, 2026
888f34a
feat: complete lab08
peplxx Mar 19, 2026
4533f84
Merge pull request #9 from peplxx/feat/lab08
peplxx Mar 19, 2026
54e6a20
feat: complete lab08
peplxx Mar 19, 2026
961b0ca
Merge pull request #10 from peplxx/feat/lab08
peplxx Mar 19, 2026
80cca11
feat: complete lab9
peplxx Mar 26, 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
134 changes: 134 additions & 0 deletions .github/workflows/ansible-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Ansible Deployment

on:
push:
branches: [main, master]
paths:
- "project/ansible/**"
- ".github/workflows/ansible-deploy.yml"
pull_request:
branches: [main, master]
paths:
- "project/ansible/**"
workflow_dispatch:
inputs:
deploy_target:
description: "Deployment target"
required: true
default: "provision and deploy"
type: choice
options:
- "provision only"
- "deploy only"
- "provision and deploy"
- "wipe and deploy"

jobs:
lint:
name: Ansible Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

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

- name: Install dependencies
run: |
pip install ansible ansible-lint

- name: Run ansible-lint
run: |
cd project/ansible
ansible-lint playbooks/*.yml roles/**/tasks/*.yml --exclude roles/**/templates/ || true

deploy:
name: Deploy Application
needs: lint
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'

steps:
- name: Checkout code
uses: actions/checkout@v4

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

- name: Install Ansible and dependencies
run: |
pip install ansible docker

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

- name: Create vault password file
run: |
echo "${{ secrets.ANSIBLE_VAULT_PASSWORD }}" > /tmp/vault_pass
chmod 600 /tmp/vault_pass

- name: Update inventory with actual host
run: |
cd project/ansible
cat > inventory/hosts.ini << EOF
[webservers]
my-vm ansible_host=${{ secrets.VM_HOST }} ansible_user=${{ secrets.VM_USER }}

[webservers:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_private_key_file=~/.ssh/id_rsa
EOF

- name: Run Ansible Playbook - Provision
if: github.event.inputs.deploy_target != 'deploy only'
run: |
cd project/ansible
ansible-playbook playbooks/provision.yml \
--vault-password-file /tmp/vault_pass \
-v

- name: Run Ansible Playbook - Wipe (if requested)
if: github.event.inputs.deploy_target == 'wipe and deploy'
run: |
cd project/ansible
ansible-playbook playbooks/deploy.yml \
--vault-password-file /tmp/vault_pass \
-e "web_app_wipe=true" \
--tags web_app_wipe \
-v

- name: Run Ansible Playbook - Deploy
if: github.event.inputs.deploy_target != 'provision only'
run: |
cd project/ansible
ansible-playbook playbooks/deploy.yml \
--vault-password-file /tmp/vault_pass \
-v

- name: Cleanup vault password
if: always()
run: rm -f /tmp/vault_pass

- name: Verify Deployment
if: github.event.inputs.deploy_target != 'provision only'
run: |
sleep 15
curl -f http://${{ secrets.VM_HOST }}:5000/ || echo "Main endpoint check failed"
curl -f http://${{ secrets.VM_HOST }}:5000/health || echo "Health check failed"

- name: Deployment Summary
run: |
echo "## Deployment Complete! 🚀" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Target Host:** ${{ secrets.VM_HOST }}" >> $GITHUB_STEP_SUMMARY
echo "- **Application URL:** http://${{ secrets.VM_HOST }}:5000" >> $GITHUB_STEP_SUMMARY
echo "- **Health Check:** http://${{ secrets.VM_HOST }}:5000/health" >> $GITHUB_STEP_SUMMARY
50 changes: 50 additions & 0 deletions .github/workflows/docker-build-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Docker Build Check

on:
push:
branches: [master]
pull_request:
branches: [master]

env:
PYTHON_CONTEXT: ./project/app_python
ZIG_CONTEXT: ./project/app_zig

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- name: python
context: ./project/app_python
file: ./project/app_python/Dockerfile
tag: devops-info-service-python:test
- name: zig
context: ./project/app_zig
file: ./project/app_zig/Dockerfile
tag: devops-info-service-zig:test
steps:
- uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64

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

- name: Build Image (no push)
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
file: ${{ matrix.file }}
platforms: linux/amd64,linux/arm64
push: false
tags: ${{ matrix.tag }}
cache-from: type=gha
cache-to: type=gha,mode=max
42 changes: 42 additions & 0 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Release Image Build

on:
push:
tags: ["v*.*.*"]

env:
BUILD_CONTEXT: ./project/app_python
DOCKERHUB_REPO: devops-info-service

jobs:
image-release:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64

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

- name: Build and push (multi-arch)
uses: docker/build-push-action@v6
with:
context: ${{ env.BUILD_CONTEXT }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_REPO }}:${{ github.ref_name }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_REPO }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
57 changes: 57 additions & 0 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Python CI (app_python)

on:
push:
branches: [master]
pull_request:
branches: [master]

permissions:
contents: read

env:
APP_DIR: project/app_python

jobs:
test:
name: Lint + tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
python-version: ["3.11", "3.12"]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
working-directory: ${{ env.APP_DIR }}

- name: Install dependencies
working-directory: ${{ env.APP_DIR }}
run: |
uv sync --locked --dev

- name: Lint (ruff)
working-directory: ${{ env.APP_DIR }}
run: |
uv run ruff --version
uv run ruff check app tests

- name: Unit tests (pytest)
working-directory: ${{ env.APP_DIR }}
run: |
uv run pytest --cov=app --cov-report=term-missing --cov-report=xml

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.python-version }}
path: ${{ env.APP_DIR }}/coverage.xml
if-no-files-found: ignore
64 changes: 64 additions & 0 deletions .github/workflows/terraform-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Terraform CI (IaC validation)

on:
pull_request:
branches: [master]
paths:
- "project/terraform/**"
- ".github/workflows/terraform-ci.yml"

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
env:
TF_IN_AUTOMATION: "true"
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Select Terraform directory
id: tfdir
shell: bash
run: |
set -euo pipefail

if [[ -d "project/terraform" ]]; then
echo "dir=project/terraform" >> "$GITHUB_OUTPUT"
elif [[ -d "terraform" ]]; then
echo "dir=terraform" >> "$GITHUB_OUTPUT"
else
echo "No terraform directory found (expected project/terraform or terraform)" >&2
exit 1
fi

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.14.0"

- name: Terraform fmt (check)
working-directory: ${{ steps.tfdir.outputs.dir }}
run: terraform fmt -check -recursive

- name: Terraform init (no backend)
working-directory: ${{ steps.tfdir.outputs.dir }}
run: terraform init -backend=false

- name: Terraform validate
working-directory: ${{ steps.tfdir.outputs.dir }}
run: terraform validate

- name: Setup TFLint
uses: terraform-linters/setup-tflint@v3
with:
tflint_version: latest

- name: TFLint
working-directory: ${{ steps.tfdir.outputs.dir }}
run: |
tflint --version
tflint --init
tflint --format compact
23 changes: 22 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
test
.DS_Store

# Terraform
**/.terraform/
**/*.tfstate
**/*.tfstate.*
**/terraform.tfvars
**/*.tfvars
**/.terraform.lock.hcl

# Pulumi
**/node_modules/
**/dist/
**/Pulumi.*.yaml

# Credentials / keys (keep project files explicit)
**/*.pem
**/*.key
**/*.p12
**/*.pfx
**/*credentials*
**/*secret*
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![Labs](https://img.shields.io/badge/Labs-18-blue)](#labs)
[![Exam](https://img.shields.io/badge/Exam-Optional-green)](#exam-alternative)
[![Duration](https://img.shields.io/badge/Duration-18%20Weeks-lightgrey)](#course-roadmap)
[![Docker Hub](https://img.shields.io/badge/Docker%20Hub-peplxx%2Fdevops--info--service-2496ED?logo=docker&logoColor=white)](https://hub.docker.com/repository/docker/peplxx/devops-info-service/general)

Master **production-grade DevOps practices** through hands-on labs. Build, containerize, deploy, monitor, and scale applications using industry-standard tools.

Expand Down
Loading