From 9330fe6cfd0a5d1c761ef08cef5bf48702ea3815 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 26 Oct 2025 01:33:49 +0300 Subject: [PATCH 01/17] Add README and .gitignore --- .gitignore | 160 +---------------------------------------------------- README.md | 6 +- 2 files changed, 7 insertions(+), 159 deletions(-) diff --git a/.gitignore b/.gitignore index 68bc17f9f..c55dc97f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,160 +1,4 @@ -# Byte-compiled / optimized / DLL files __pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments +*.pyc .env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.venv/ \ No newline at end of file diff --git a/README.md b/README.md index d19dfd95a..85636eb79 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# devops-programme \ No newline at end of file +# AboutMe +# Name: Stefan Lalev +# Role:** Application administrator +# Learning Goals: +# Improve my skills and better understand the whole process from building to deploying application automaticaly From b84e2436ae62e75250f14cb53091fad27802226b Mon Sep 17 00:00:00 2001 From: cyrixrr Date: Sun, 26 Oct 2025 01:58:57 +0300 Subject: [PATCH 02/17] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 85636eb79..141f1aea3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # AboutMe # Name: Stefan Lalev -# Role:** Application administrator -# Learning Goals: -# Improve my skills and better understand the whole process from building to deploying application automaticaly +# Role: Application administrator +# Learning Goals: Improve my skills and better understand the whole process from building to deploying application automaticaly From 06c99b36f89da9a589cddd042e9c7b3917e45a34 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 26 Oct 2025 02:11:57 +0300 Subject: [PATCH 03/17] Added bio.md with Professional background --- bio.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 bio.md diff --git a/bio.md b/bio.md new file mode 100644 index 000000000..901b0c8b8 --- /dev/null +++ b/bio.md @@ -0,0 +1,4 @@ +# Professional Background + +I have experience in IT support and system administration. +Currently learning DevOps practices such as CI/CD, Docker, and cloud automation. From 3d464a98614d22d08256986e26050888fb277d40 Mon Sep 17 00:00:00 2001 From: Iliyan Vutov Date: Wed, 29 Oct 2025 20:05:28 +0200 Subject: [PATCH 04/17] Add requirements.txt --- requirements.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..9d440edf1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +flask==3.0.0 ; python_version >= "3.10" and python_version < "4.0" +itsdangerous==2.1.2 ; python_version >= "3.10" and python_version < "4.0" +jinja2==3.1.2 ; python_version >= "3.10" and python_version < "4.0" +markupsafe==2.1.3 ; python_version >= "3.10" and python_version < "4.0" +werkzeug==3.0.0 ; python_version >= "3.10" and python_version < "4.0" + From 69d0b94a93a048f70bc959c8f54ebfb6eab44a4f Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Wed, 29 Oct 2025 20:47:17 +0200 Subject: [PATCH 05/17] Add Dockerfile --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..ebd9cd4be --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM ubuntu:22.04 +RUN apt-get update && apt-get install -y python3 python3-pip +WORKDIR /app +COPY app/ /app/ +RUN pip install -r requirements.txt +EXPOSE 5000 +CMD ["python3", "app.py"] \ No newline at end of file From 2402a139eeddd715f839d4fe03626b871270d4a9 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Wed, 29 Oct 2025 21:48:22 +0200 Subject: [PATCH 06/17] Added Dockerfile --- requirements.txt => app/requirements.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename requirements.txt => app/requirements.txt (100%) diff --git a/requirements.txt b/app/requirements.txt similarity index 100% rename from requirements.txt rename to app/requirements.txt From d71e2ef45a4872e9d794fd9d2f159ca98f0bdae3 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sat, 8 Nov 2025 22:07:53 +0200 Subject: [PATCH 07/17] Add Ansible playbook and update requirements --- playbook.yml | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 +- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 playbook.yml diff --git a/playbook.yml b/playbook.yml new file mode 100644 index 000000000..e5f8b8683 --- /dev/null +++ b/playbook.yml @@ -0,0 +1,96 @@ +--- +- name: Build, push, and run the Python app container + hosts: localhost + connection: local + gather_facts: true + + collections: + - community.docker + + vars: + # === Your homework variables === + image_name: "cyrixrr/python-app" + image_tag: "v2" + listen_port: 8000 + + # === Optional (only needed for push) === + docker_registry: "docker.io" + docker_username: "" # set when you want to push + docker_password: "" # set when you want to push + + # Build context (repo root that has the Dockerfile) + app_dir: "{{ playbook_dir }}" + + tasks: + # --- Pick the correct Docker socket (Linux / Docker Desktop / Rancher Desktop) --- + - name: Detect Rancher Desktop Docker socket + ansible.builtin.stat: + path: "{{ ansible_env.HOME }}/.rd/run/docker.sock" + register: rd_sock + + - name: Detect Docker Desktop Docker socket + ansible.builtin.stat: + path: "{{ ansible_env.HOME }}/.docker/run/docker.sock" + register: dd_sock + + - name: Choose effective docker_host + ansible.builtin.set_fact: + effective_docker_host: >- + {{ + ('unix://' + ansible_env.HOME + '/.rd/run/docker.sock') if rd_sock.stat.exists else + ('unix://' + ansible_env.HOME + '/.docker/run/docker.sock') if dd_sock.stat.exists else + 'unix:///var/run/docker.sock' + }} + + # --- Optional login for push --- + - name: Log in to container registry (if credentials provided) + when: + - docker_username | length > 0 + - docker_password | length > 0 + community.docker.docker_login: + registry_url: "{{ docker_registry }}" + username: "{{ docker_username }}" + password: "{{ docker_password }}" + reauthorize: true + docker_host: "{{ effective_docker_host }}" + + # --- Build image --- + - name: Build the Docker image + community.docker.docker_image: + name: "{{ image_name }}" + tag: "{{ image_tag }}" + build: + path: "{{ app_dir }}" + pull: true + source: build + docker_host: "{{ effective_docker_host }}" + + # --- Push image (only if logged in) --- + - name: Push the Docker image (if logged in) + when: + - docker_username | length > 0 + - docker_password | length > 0 + community.docker.docker_image: + name: "{{ image_name }}" + tag: "{{ image_tag }}" + push: true + docker_host: "{{ effective_docker_host }}" + + # --- Run container --- + - name: Remove existing container (idempotent cleanup) + community.docker.docker_container: + name: "devops-programme-app" + state: absent + docker_host: "{{ effective_docker_host }}" + + - name: Run the container with PORT env and port binding + community.docker.docker_container: + name: "devops-programme-app" + image: "{{ image_name }}:{{ image_tag }}" + env: + PORT: "{{ listen_port | string }}" + published_ports: + - "{{ listen_port }}:{{ listen_port }}" + restart_policy: unless-stopped + state: started + docker_host: "{{ effective_docker_host }}" diff --git a/requirements.txt b/requirements.txt index 9d440edf1..7b9104f2f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ itsdangerous==2.1.2 ; python_version >= "3.10" and python_version < "4.0" jinja2==3.1.2 ; python_version >= "3.10" and python_version < "4.0" markupsafe==2.1.3 ; python_version >= "3.10" and python_version < "4.0" werkzeug==3.0.0 ; python_version >= "3.10" and python_version < "4.0" - +ansible==9.2.0 From db36cb6e0afd4e1dd6e5d1e5bdbf5d5086ea6074 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sat, 8 Nov 2025 22:31:15 +0200 Subject: [PATCH 08/17] Fix ansible playbook --- playbook.yml | 78 +++++++--------------------------------------------- 1 file changed, 10 insertions(+), 68 deletions(-) diff --git a/playbook.yml b/playbook.yml index e5f8b8683..9071349f4 100644 --- a/playbook.yml +++ b/playbook.yml @@ -1,96 +1,38 @@ --- -- name: Build, push, and run the Python app container +- name: Build and run Python app container hosts: localhost connection: local - gather_facts: true - - collections: - - community.docker vars: - # === Your homework variables === image_name: "cyrixrr/python-app" image_tag: "v2" listen_port: 8000 - # === Optional (only needed for push) === - docker_registry: "docker.io" - docker_username: "" # set when you want to push - docker_password: "" # set when you want to push - - # Build context (repo root that has the Dockerfile) - app_dir: "{{ playbook_dir }}" + collections: + - community.docker tasks: - # --- Pick the correct Docker socket (Linux / Docker Desktop / Rancher Desktop) --- - - name: Detect Rancher Desktop Docker socket - ansible.builtin.stat: - path: "{{ ansible_env.HOME }}/.rd/run/docker.sock" - register: rd_sock - - - name: Detect Docker Desktop Docker socket - ansible.builtin.stat: - path: "{{ ansible_env.HOME }}/.docker/run/docker.sock" - register: dd_sock - - - name: Choose effective docker_host - ansible.builtin.set_fact: - effective_docker_host: >- - {{ - ('unix://' + ansible_env.HOME + '/.rd/run/docker.sock') if rd_sock.stat.exists else - ('unix://' + ansible_env.HOME + '/.docker/run/docker.sock') if dd_sock.stat.exists else - 'unix:///var/run/docker.sock' - }} - # --- Optional login for push --- - - name: Log in to container registry (if credentials provided) - when: - - docker_username | length > 0 - - docker_password | length > 0 - community.docker.docker_login: - registry_url: "{{ docker_registry }}" - username: "{{ docker_username }}" - password: "{{ docker_password }}" - reauthorize: true - docker_host: "{{ effective_docker_host }}" - - # --- Build image --- - name: Build the Docker image community.docker.docker_image: name: "{{ image_name }}" tag: "{{ image_tag }}" build: - path: "{{ app_dir }}" - pull: true + path: "{{ playbook_dir }}" source: build - docker_host: "{{ effective_docker_host }}" - # --- Push image (only if logged in) --- - - name: Push the Docker image (if logged in) - when: - - docker_username | length > 0 - - docker_password | length > 0 - community.docker.docker_image: - name: "{{ image_name }}" - tag: "{{ image_tag }}" - push: true - docker_host: "{{ effective_docker_host }}" - - # --- Run container --- - - name: Remove existing container (idempotent cleanup) + - name: Remove existing container if present community.docker.docker_container: - name: "devops-programme-app" + name: python-app state: absent - docker_host: "{{ effective_docker_host }}" - - name: Run the container with PORT env and port binding + - name: Run the Docker container community.docker.docker_container: - name: "devops-programme-app" + name: python-app image: "{{ image_name }}:{{ image_tag }}" env: - PORT: "{{ listen_port | string }}" + PORT: "{{ listen_port }}" published_ports: - "{{ listen_port }}:{{ listen_port }}" - restart_policy: unless-stopped state: started - docker_host: "{{ effective_docker_host }}" + restart_policy: unless-stopped From 37a89b75909e275ed56e4bf03d907d2e9958a055 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sat, 8 Nov 2025 22:50:11 +0200 Subject: [PATCH 09/17] Added explanations of what each step do in playbook.yml --- playbook.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/playbook.yml b/playbook.yml index 9071349f4..f549a09ff 100644 --- a/playbook.yml +++ b/playbook.yml @@ -6,10 +6,10 @@ vars: image_name: "cyrixrr/python-app" image_tag: "v2" - listen_port: 8000 + listen_port: 8000 # Here we set our variables collections: - - community.docker + - community.docker # Here we gave acces to Docker modules tasks: @@ -19,12 +19,12 @@ tag: "{{ image_tag }}" build: path: "{{ playbook_dir }}" - source: build + source: build #This would like this in shell "docker build -t cyrixrr/python-app:v2 ."" - name: Remove existing container if present community.docker.docker_container: name: python-app - state: absent + state: absent #That will make it idempotent as we spoke in cource - name: Run the Docker container community.docker.docker_container: @@ -35,4 +35,4 @@ published_ports: - "{{ listen_port }}:{{ listen_port }}" state: started - restart_policy: unless-stopped + restart_policy: unless-stopped #All this would like this in shell "docker run -d --name python-app -e PORT=8000 -p 8000:8000 cyrixrr/python-app:v2" From 2a28b66d59ffce299033c4c41a1a5e5b29ce3661 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sat, 8 Nov 2025 23:10:46 +0200 Subject: [PATCH 10/17] Edited playbook to be fully idempotent as last version was broken because the port was already used. This was the error: Bind for 0.0.0.0:8000 failed: port is already allocated. Hope this time it will be fully idempotent :) --- playbook.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/playbook.yml b/playbook.yml index f549a09ff..ef3d01491 100644 --- a/playbook.yml +++ b/playbook.yml @@ -7,6 +7,7 @@ image_name: "cyrixrr/python-app" image_tag: "v2" listen_port: 8000 # Here we set our variables + host_port: "{{ listen_port }}" # New variable – this is the port we check and remove other containers from collections: - community.docker # Here we gave acces to Docker modules @@ -19,7 +20,30 @@ tag: "{{ image_tag }}" build: path: "{{ playbook_dir }}" - source: build #This would like this in shell "docker build -t cyrixrr/python-app:v2 ."" + source: build #This would like this in shell "docker build -t cyrixrr/python-app:v2 . + + # ---------------- NEW BLOCK START ---------------- + - name: Get Docker host info (list of all containers) # New – we gather container info so we can check used ports + community.docker.docker_host_info: + containers: true + register: host_info + + - name: Remove ANY container using the host port # New – this removes any container that is using listen_port + community.docker.docker_container: + name: "{{ (item.Names is string) | ternary(item.Names, (item.Names | first | regex_replace('^/', ''))) }}" + state: absent + loop: "{{ host_info.containers | default([]) }}" + when: > + item.Ports is defined and + ( + item.Ports + | selectattr('PublicPort','defined') + | selectattr('PublicPort','equalto', host_port | int) + | list | length + ) > 0 + # This loop checks every container, and if it is using 8000 on the host, + # we remove it. This makes the playbook idempotent and avoids port conflicts. + # ---------------- NEW BLOCK END ------------------ - name: Remove existing container if present community.docker.docker_container: @@ -31,8 +55,8 @@ name: python-app image: "{{ image_name }}:{{ image_tag }}" env: - PORT: "{{ listen_port }}" + PORT: "{{ listen_port | string }}" published_ports: - - "{{ listen_port }}:{{ listen_port }}" + - "{{ host_port }}:{{ listen_port }}" # Updated to use host_port so we can remove others first state: started restart_policy: unless-stopped #All this would like this in shell "docker run -d --name python-app -e PORT=8000 -p 8000:8000 cyrixrr/python-app:v2" From 163906a78a5a5575a710a5acd95b31fecc39bb78 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sat, 8 Nov 2025 23:23:02 +0200 Subject: [PATCH 11/17] Added Readme.md with full instructions and explanations --- README.md | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 141f1aea3..bbf45f967 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,102 @@ -# AboutMe -# Name: Stefan Lalev -# Role: Application administrator -# Learning Goals: Improve my skills and better understand the whole process from building to deploying application automaticaly +# FIRST SORRY FOR MAKING THIS PULL REQUESTS WITH DELAY, BUT I WAS SICK. +# Ansible Playbook --- Build & Run Python App (Docker) + +This playbook builds a Docker image for the Python application, removes +any running containers that use the configured host port, and starts the +container with the PORT environment variable that the app requires. + +The playbook uses **Ansible modules only** (`community.docker`) and is +**fully idempotent**. + +## What the playbook does + +1. **Builds** the Docker image using your local `Dockerfile`.\ +2. **Finds and removes** any container currently using the configured + host port.\ +3. **Removes** the previous `python-app` container if present + (idempotent).\ +4. **Runs** the container with: + - the correct environment variable (`PORT`)\ + - port mapping (`host_port:listen_port`)\ + - `restart_policy: unless-stopped` + +## Requirements + +- Python ≥ 3.8\ +- Docker installed and running\ +- Ansible installed\ +- The `community.docker` collection installed + +Install dependencies: + + pip install -r requirements.txt + ansible-galaxy collection install community.docker + +## Variables + + ------------------------------------------------------------------------------------- + Variable Description Default + --------------- ---------------------------------------------- ---------------------- + `image_name` The Docker image name (no tag). `cyrixrr/python-app` + + `image_tag` The tag for the Docker image. `v2` + + `listen_port` The internal port that the Python app listens `8000` + on. + + `host_port` The port on the host that will be published `{{ listen_port }}` + and checked for conflicts. + ------------------------------------------------------------------------------------- + +You can override them when running the playbook: + + ansible-playbook playbook.yml -e image_tag=v3 + ansible-playbook playbook.yml -e host_port=8001 + +## How to run + +From the project root: + + ansible-playbook playbook.yml + +Test the application: + + curl http://localhost:8000/ + +## Idempotency + +This playbook is **fully idempotent**: + +- If no container uses the configured host port, nothing is removed.\ +- If the image has not changed, it will not rebuild.\ +- If the `python-app` container is already running with the correct + settings, no changes occur.\ +- If a different container is occupying the selected host port, it + will be removed automatically. + +## Troubleshooting + +### Port already in use + +This playbook automatically removes Docker containers that use +`host_port`. + +If a **non-Docker** process is using the port: + + sudo lsof -i :8000 -nP + sudo kill -9 + +### Environment variable must be a string + +`PORT` must be passed as a string: + + PORT: "{{ listen_port | string }}" + +## Summary + +This playbook demonstrates: - Use of Ansible variables\ +- Docker image building via `docker_image`\ +- Running containers via `docker_container`\ +- Idempotent cleanup logic\ +- Environment variable injection\ +- Port mapping and collision handling \ No newline at end of file From eb04de44596486cb2b43141455a03af1fcec103a Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 9 Nov 2025 19:59:01 +0200 Subject: [PATCH 12/17] Added simple workflow which triggers when a PR is made --- .github/pr-lint.yml | 26 ++++++++++++++++++++++++++ Dockerfile | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 .github/pr-lint.yml diff --git a/.github/pr-lint.yml b/.github/pr-lint.yml new file mode 100644 index 000000000..3e540da18 --- /dev/null +++ b/.github/pr-lint.yml @@ -0,0 +1,26 @@ +name: PR Lint + +on: + pull_request: # run on every pull request event targeting this repo + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install lint dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + + - name: Run flake8 on app + run: | + flake8 app || echo "Lint warnings (non-fatal for now)" diff --git a/Dockerfile b/Dockerfile index ebd9cd4be..07fd85226 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,4 +4,4 @@ WORKDIR /app COPY app/ /app/ RUN pip install -r requirements.txt EXPOSE 5000 -CMD ["python3", "app.py"] \ No newline at end of file +CMD ["python3", "app.py"] From e7ea426b8d097f7e6cfeba1444b1769c27341d42 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 9 Nov 2025 20:01:42 +0200 Subject: [PATCH 13/17] pr-lint.yml was in wrong directory, not in .github/workflows --- .github/workflows/pr-lint.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/pr-lint.yml diff --git a/.github/workflows/pr-lint.yml b/.github/workflows/pr-lint.yml new file mode 100644 index 000000000..3e540da18 --- /dev/null +++ b/.github/workflows/pr-lint.yml @@ -0,0 +1,26 @@ +name: PR Lint + +on: + pull_request: # run on every pull request event targeting this repo + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install lint dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + + - name: Run flake8 on app + run: | + flake8 app || echo "Lint warnings (non-fatal for now)" From a428d198ee4663f12f9d95265b5e9db6f63d8437 Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 9 Nov 2025 20:08:22 +0200 Subject: [PATCH 14/17] Remove old workflow file from wrong location --- .github/pr-lint.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/pr-lint.yml diff --git a/.github/pr-lint.yml b/.github/pr-lint.yml deleted file mode 100644 index 3e540da18..000000000 --- a/.github/pr-lint.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: PR Lint - -on: - pull_request: # run on every pull request event targeting this repo - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install lint dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 - - - name: Run flake8 on app - run: | - flake8 app || echo "Lint warnings (non-fatal for now)" From 4f715a8a1b046cb9fd428ebf5bef88e8e84f8b2e Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 9 Nov 2025 20:26:11 +0200 Subject: [PATCH 15/17] Test change for PR workflow --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bbf45f967..be89358d9 100644 --- a/README.md +++ b/README.md @@ -99,4 +99,4 @@ This playbook demonstrates: - Use of Ansible variables\ - Running containers via `docker_container`\ - Idempotent cleanup logic\ - Environment variable injection\ -- Port mapping and collision handling \ No newline at end of file +- Port mapping and collision handling From 502f3298128ada6dee06ce6a8c3a04fc4f969e1e Mon Sep 17 00:00:00 2001 From: Stefan Lalev Date: Sun, 9 Nov 2025 21:13:04 +0200 Subject: [PATCH 16/17] Added second workflow that trigers only when a file is changed --- .github/workflows/pr-lint-filtered.yml | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/pr-lint-filtered.yml diff --git a/.github/workflows/pr-lint-filtered.yml b/.github/workflows/pr-lint-filtered.yml new file mode 100644 index 000000000..d3f17fb5b --- /dev/null +++ b/.github/workflows/pr-lint-filtered.yml @@ -0,0 +1,32 @@ +name: PR Lint (only when specific files are changed) + +on: + pull_request: + paths: + - 'app/**' + - 'Dockerfile' + - 'playbook.yml' + - '.github/workflows/**' + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install lint dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + + - name: Run flake8 on app + run: | + flake8 app || echo "Lint warnings (non-fatal for now)" + From fd05b90ab1e0422b55b359f6110e73314514ae4e Mon Sep 17 00:00:00 2001 From: cyrixrr Date: Wed, 10 Dec 2025 21:14:34 +0200 Subject: [PATCH 17/17] Remove unnecessary apology from README Removed apology message from the README. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index be89358d9..35861a840 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -# FIRST SORRY FOR MAKING THIS PULL REQUESTS WITH DELAY, BUT I WAS SICK. # Ansible Playbook --- Build & Run Python App (Docker) This playbook builds a Docker image for the Python application, removes