From 1c8438cbb95586d10533c200f9c69dea54c6fbd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 10:39:38 +0100 Subject: [PATCH 01/29] Create CI/CD actions file --- .github/workflows/ci-cd.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/ci-cd.yml diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..9a251fb --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1 @@ +name: CI/CD pipeline \ No newline at end of file From a915d3583140adb1bd345c325e8bb364d7b784eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 12:00:43 +0100 Subject: [PATCH 02/29] Add vulnerability scanning and security analysis to CI/CD pipeline using pip-audit and bandit --- .github/workflows/ci-cd.yml | 58 ++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 9a251fb..88d4133 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1 +1,57 @@ -name: CI/CD pipeline \ No newline at end of file +name: CI/CD pipeline + +on: + push: + branches: + [ main, develop] + pull_request: + branches: + - main + +jobs: + vulnerability-scan: + name: source vulnerability scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.x' # use latest python 3 version + + # use pip-audit to scan dependencies + - name: pip-audit install + run: pip install pip-audit + + - name: back-end audit + run: pip-audit -r back-end/requirements.txt --desc # add description to output + + - name: front-end audit + run: pip-audit -r front-end/requirements.txt --desc + + + # use bandit to scan source code, output in sarif format + - name: bandit install + run: pip install bandit + + - name: back-end bandit + run: bandit -r back-end/ sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports + + - name: upload backend bandit report + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: bandit-backend.sarif + category: 'bandit backend' + + - name: front-end bandit + run: bandit -r front-end/ sarif -o bandit-frontend.sarif --exit-zero + + - name : upload frontend bandit report + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: bandit-frontend.sarif + category: 'bandit frontend' + From d13b38a238e6bc89912fe604e6383da74d277e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 16:22:27 +0100 Subject: [PATCH 03/29] Added linting and testing to CI/CD --- .github/workflows/ci-cd.yml | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 88d4133..b853161 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -54,4 +54,69 @@ jobs: with: sarif_file: bandit-frontend.sarif category: 'bandit frontend' + lint: + name: code linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: install flake8 + run: pip install flake8 + + - name: lint back-end + run: | + flake8 back-end/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 back-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: lint front-end + run: | + flake8 front-end/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 front-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + + + test-backend: + name: back-end tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: install dependencies + working-directory: ./back-end + run: | + pip install -r requirements.txt + pip install -r requirements_test.txt + + - name: run tests + working-directory: ./back-end + run: pytest test_app.py -v + test-frontend: + name: front-end tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: install dependencies + working-directory: ./front-end + run: | + pip install -r requirements.txt + pip install -r requirements_test.txt + - name: run tests + working-directory: ./front-end + run: pytest test_app.py -v From 9a5d74fe4e5d60590f7d0a7baef061beb2457090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 20:08:42 +0100 Subject: [PATCH 04/29] Fix branch names --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index b853161..8185192 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -3,10 +3,10 @@ name: CI/CD pipeline on: push: branches: - [ main, develop] + [master, develop] pull_request: branches: - - main + [master, develop] jobs: vulnerability-scan: From 914fa85c7b675d47781f82e4f7f367eb8ac43e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 21:57:22 +0100 Subject: [PATCH 05/29] Add Dockerfile for backend --- back-end/Dockerfile | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/back-end/Dockerfile b/back-end/Dockerfile index effa773..9d5cf65 100644 --- a/back-end/Dockerfile +++ b/back-end/Dockerfile @@ -1 +1,26 @@ -# ADD YOUR OWN DOCKERFILE \ No newline at end of file +FROM python:3.13-slim + +WORKDIR /app + +ENV PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 + +RUN apt-get update && \ +apt-get install -y --no-install-recommends \ +curl && \ +rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . + +RUN pip install --upgrade pip && \ + pip install -r requirements.txt + +COPY . . + +EXPOSE 5000 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:5000/liveness || exit 1 + +CMD ["python", "app.py"] \ No newline at end of file From 0e29e65635808cfc704277642ae485daccf8d804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Mon, 27 Oct 2025 22:02:47 +0100 Subject: [PATCH 06/29] Add Dockerfile for frontend --- front-end/Dockerfile | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/front-end/Dockerfile b/front-end/Dockerfile index effa773..a3bece6 100644 --- a/front-end/Dockerfile +++ b/front-end/Dockerfile @@ -1 +1,26 @@ -# ADD YOUR OWN DOCKERFILE \ No newline at end of file +FROM python:3.13-slim + +WORKDIR /app + +ENV PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 + +RUN apt-get update && \ +apt-get install -y --no-install-recommends \ +curl && \ +rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . + +RUN pip install --upgrade pip && \ + pip install -r requirements.txt + +COPY . . + +EXPOSE 8000 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:8000/ || exit 1 + +CMD ["python", "app.py"] \ No newline at end of file From 95d365cca0b2e054abd56b099bfb63b9be4abc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 17:57:21 +0100 Subject: [PATCH 07/29] Add build, push and scand for frontend and backend --- .github/workflows/ci-cd.yml | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 8185192..9c170e6 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -120,3 +120,103 @@ jobs: - name: run tests working-directory: ./front-end run: pytest test_app.py -v + build-push-backend: + name: build and push back-end image + runs-on: ubuntu-latest + needs: [vulnerability-scan, lint, test-backend] + permissions: + contents: read + packages: write + security-events: write + steps: + - uses: actions/checkout@v5 + + - name: log in to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }}/back-end + tags: | + type=sha + type=ref,event=branch + type=raw,value=latest,enable={{is_default_branch}} + + - name: build and push back-end image + uses: docker/build-push-action@v4 + with: + context: ./back-end + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + # scanning built image with trivy + - name: run trivy back-end scan + uses: aquasecurity/trivy-action@master + with: + image-ref: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} + format: 'sarif' + output: 'trivy-backend-image.sarif' + + - name: upload trivy back-end scan + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: trivy-backend-image.sarif + category: 'trivy back-end' + build-push-frontend: + name: build and push front-end image + runs-on: ubuntu-latest + needs: [ vulnerability-scan, lint, test-backend ] + permissions: + contents: read + packages: write + security-events: write + steps: + - uses: actions/checkout@v5 + + - name: log in to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }}/front-end + tags: | + type=sha + type=ref,event=branch + type=raw,value=latest,enable={{is_default_branch}} + + - name: build and push front-end image + uses: docker/build-push-action@v4 + with: + context: ./front-end + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + # scanning built image with trivy + - name: run trivy front-end scan + uses: aquasecurity/trivy-action@master + with: + image-ref: ghcr.io/${{ github.repository }}/front-end:${{ github.sha }} + format: 'sarif' + output: 'trivy-frontend-image.sarif' + + - name: upload trivy front-end scan + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: trivy-frontend-image.sarif + category: 'trivy front-end' \ No newline at end of file From b497e3369a31acc603cee35711bef71508ecc70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:10:27 +0100 Subject: [PATCH 08/29] Update CodeQL SARIF upload action to v4 --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 9c170e6..4674d3a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -39,7 +39,7 @@ jobs: run: bandit -r back-end/ sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports - name: upload backend bandit report - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: bandit-backend.sarif @@ -49,7 +49,7 @@ jobs: run: bandit -r front-end/ sarif -o bandit-frontend.sarif --exit-zero - name : upload frontend bandit report - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: bandit-frontend.sarif From 3a1577038c03a2550ca1f724816373a7aedf513c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:22:18 +0100 Subject: [PATCH 09/29] Add env variables from secrets --- .github/workflows/ci-cd.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 4674d3a..f927efb 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -12,6 +12,18 @@ jobs: vulnerability-scan: name: source vulnerability scan runs-on: ubuntu-latest + env: + POSTGRES_DB: {{secrets.POSTGRES_DB}} + POSTGRES_USER: {{secrets.POSTGRES_USER}} + POSTGRES_PASSWORD: {{secrets.POSTGRES_PASSWORD}} + POSTGRES_HOST: {{secrets.POSTGRES_HOST}} + PORT: {{secrets.PORT}} + JWT_KEY: {{secrets.JWT_KEY}} + APP_PORT: {{secrets.APP_PORT}} + BACKEND_HOSTNAME: {{secrets.BACKEND_HOSTNAME}} + BACKEND_PORT: {{secrets.BACKEND_PORT}} + SECRET_KEY: {{secrets.SECRET_KEY}} + SERVER_PORT: {{secrets.SERVER_PORT}} steps: - uses: actions/checkout@v5 From 2467216e149ce99ca5928c70f34127070edc675e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:26:22 +0100 Subject: [PATCH 10/29] Fix env mapping --- .github/workflows/ci-cd.yml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index f927efb..35113ae 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -12,19 +12,8 @@ jobs: vulnerability-scan: name: source vulnerability scan runs-on: ubuntu-latest - env: - POSTGRES_DB: {{secrets.POSTGRES_DB}} - POSTGRES_USER: {{secrets.POSTGRES_USER}} - POSTGRES_PASSWORD: {{secrets.POSTGRES_PASSWORD}} - POSTGRES_HOST: {{secrets.POSTGRES_HOST}} - PORT: {{secrets.PORT}} - JWT_KEY: {{secrets.JWT_KEY}} - APP_PORT: {{secrets.APP_PORT}} - BACKEND_HOSTNAME: {{secrets.BACKEND_HOSTNAME}} - BACKEND_PORT: {{secrets.BACKEND_PORT}} - SECRET_KEY: {{secrets.SECRET_KEY}} - SERVER_PORT: {{secrets.SERVER_PORT}} steps: + - uses: actions/checkout@v5 - name: python setup @@ -110,6 +99,14 @@ jobs: pip install -r requirements_test.txt - name: run tests + env: + POSTGRES_DB: {{secrets.POSTGRES_DB}} + POSTGRES_USER: {{secrets.POSTGRES_USER}} + POSTGRES_PASSWORD: {{secrets.POSTGRES_PASSWORD}} + POSTGRES_HOST: {{secrets.POSTGRES_HOST}} + PORT: {{secrets.PORT}} + JWT_KEY: {{secrets.JWT_KEY}} + APP_PORT: {{secrets.APP_PORT}} working-directory: ./back-end run: pytest test_app.py -v test-frontend: @@ -130,7 +127,12 @@ jobs: pip install -r requirements_test.txt - name: run tests - working-directory: ./front-end + env: + BACKEND_HOSTNAME: {{secrets.BACKEND_HOSTNAME}} + BACKEND_PORT: {{secrets.BACKEND_PORT}} + SECRET_KEY: {{secrets.SECRET_KEY}} + SERVER_PORT: {{secrets.SERVER_PORT}} + working-directory: ./front-end run: pytest test_app.py -v build-push-backend: name: build and push back-end image From 806768ca7a95b35fe347e2d6f6883e23f126d60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:31:44 +0100 Subject: [PATCH 11/29] Fix bandit command --- .github/workflows/ci-cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 35113ae..8d2894b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -37,7 +37,7 @@ jobs: run: pip install bandit - name: back-end bandit - run: bandit -r back-end/ sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports + run: bandit -r `front-end/` -f sarif -o `bandit-backend.sarif` --exit-zero # exit-zero doesn't fail build, only reports - name: upload backend bandit report uses: github/codeql-action/upload-sarif@v4 @@ -47,9 +47,9 @@ jobs: category: 'bandit backend' - name: front-end bandit - run: bandit -r front-end/ sarif -o bandit-frontend.sarif --exit-zero + run: bandit -r `front-end/` -f sarif -o `bandit-frontend.sarif` --exit-zero - - name : upload frontend bandit report + - name: upload frontend bandit report uses: github/codeql-action/upload-sarif@v4 if: always() with: From d5348a63fbbf85e88b83d1ffe8d949252cef56e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:33:12 +0100 Subject: [PATCH 12/29] Fix env variables --- .github/workflows/ci-cd.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 8d2894b..479eaa9 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -100,13 +100,13 @@ jobs: - name: run tests env: - POSTGRES_DB: {{secrets.POSTGRES_DB}} - POSTGRES_USER: {{secrets.POSTGRES_USER}} - POSTGRES_PASSWORD: {{secrets.POSTGRES_PASSWORD}} - POSTGRES_HOST: {{secrets.POSTGRES_HOST}} - PORT: {{secrets.PORT}} - JWT_KEY: {{secrets.JWT_KEY}} - APP_PORT: {{secrets.APP_PORT}} + POSTGRES_DB: ${{secrets.POSTGRES_DB}} + POSTGRES_USER: ${{secrets.POSTGRES_USER}} + POSTGRES_PASSWORD: ${{secrets.POSTGRES_PASSWORD}} + POSTGRES_HOST: ${{secrets.POSTGRES_HOST}} + PORT: ${{secrets.PORT}} + JWT_KEY: ${{secrets.JWT_KEY}} + APP_PORT: ${{secrets.APP_PORT}} working-directory: ./back-end run: pytest test_app.py -v test-frontend: @@ -128,10 +128,10 @@ jobs: - name: run tests env: - BACKEND_HOSTNAME: {{secrets.BACKEND_HOSTNAME}} - BACKEND_PORT: {{secrets.BACKEND_PORT}} - SECRET_KEY: {{secrets.SECRET_KEY}} - SERVER_PORT: {{secrets.SERVER_PORT}} + BACKEND_HOSTNAME: ${{secrets.BACKEND_HOSTNAME}} + BACKEND_PORT: ${{secrets.BACKEND_PORT}} + SECRET_KEY: ${{secrets.SECRET_KEY}} + SERVER_PORT: ${{secrets.SERVER_PORT}} working-directory: ./front-end run: pytest test_app.py -v build-push-backend: From acd8f3b52813cf050fef08092b2beb4dcf758f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:35:11 +0100 Subject: [PATCH 13/29] Fix dependency in front-end build job --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 479eaa9..4b891fe 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -187,7 +187,7 @@ jobs: build-push-frontend: name: build and push front-end image runs-on: ubuntu-latest - needs: [ vulnerability-scan, lint, test-backend ] + needs: [ vulnerability-scan, lint, test-frontend ] permissions: contents: read packages: write From 70b7b70e038e5ba8ad90dcbc7ec080c3245aeda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:39:51 +0100 Subject: [PATCH 14/29] Lock Python version to 3.13 --- .github/workflows/ci-cd.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 4b891fe..af08846 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -19,7 +19,7 @@ jobs: - name: python setup uses: actions/setup-python@v6 with: - python-version: '3.x' # use latest python 3 version + python-version: '3.13' # use latest python 3 version # use pip-audit to scan dependencies - name: pip-audit install @@ -64,7 +64,7 @@ jobs: - name: python setup uses: actions/setup-python@v6 with: - python-version: '3.x' + python-version: '3.13' - name: install flake8 run: pip install flake8 @@ -90,7 +90,7 @@ jobs: - name: python setup uses: actions/setup-python@v6 with: - python-version: '3.x' + python-version: '3.13' - name: install dependencies working-directory: ./back-end @@ -118,7 +118,7 @@ jobs: - name: python setup uses: actions/setup-python@v6 with: - python-version: '3.x' + python-version: '3.13' - name: install dependencies working-directory: ./front-end From 2c95e2a8f3a2a64dba5b0ea9b35aeda84643e0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:41:21 +0100 Subject: [PATCH 15/29] Fix indentation --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index af08846..057d098 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -132,7 +132,7 @@ jobs: BACKEND_PORT: ${{secrets.BACKEND_PORT}} SECRET_KEY: ${{secrets.SECRET_KEY}} SERVER_PORT: ${{secrets.SERVER_PORT}} - working-directory: ./front-end + working-directory: ./front-end run: pytest test_app.py -v build-push-backend: name: build and push back-end image From 0e5297f036ffa3ac983169a586b3183c71133b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:42:34 +0100 Subject: [PATCH 16/29] Install bandit sarif extras --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 057d098..8dca497 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -34,7 +34,7 @@ jobs: # use bandit to scan source code, output in sarif format - name: bandit install - run: pip install bandit + run: pip install bandit[sarif] - name: back-end bandit run: bandit -r `front-end/` -f sarif -o `bandit-backend.sarif` --exit-zero # exit-zero doesn't fail build, only reports From 976020f9895d24c48f7b26fa05d47e1033733ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:48:11 +0100 Subject: [PATCH 17/29] Fix --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 8dca497..22f3d90 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -37,7 +37,7 @@ jobs: run: pip install bandit[sarif] - name: back-end bandit - run: bandit -r `front-end/` -f sarif -o `bandit-backend.sarif` --exit-zero # exit-zero doesn't fail build, only reports + run: bandit -r front-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports - name: upload backend bandit report uses: github/codeql-action/upload-sarif@v4 @@ -47,7 +47,7 @@ jobs: category: 'bandit backend' - name: front-end bandit - run: bandit -r `front-end/` -f sarif -o `bandit-frontend.sarif` --exit-zero + run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero - name: upload frontend bandit report uses: github/codeql-action/upload-sarif@v4 From 83c5acf0f375b4b76cad78b48a7107661236c70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 18:50:58 +0100 Subject: [PATCH 18/29] Fix bandit --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 22f3d90..4211f9b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -37,7 +37,7 @@ jobs: run: pip install bandit[sarif] - name: back-end bandit - run: bandit -r front-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports + run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports - name: upload backend bandit report uses: github/codeql-action/upload-sarif@v4 @@ -47,7 +47,7 @@ jobs: category: 'bandit backend' - name: front-end bandit - run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero + run: bandit -r front-end/ -f sarif -o bandit-frontend.sarif --exit-zero - name: upload frontend bandit report uses: github/codeql-action/upload-sarif@v4 From 50dc5f21d5c7940db42bca69f2764fc7e4efee1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 19:02:35 +0100 Subject: [PATCH 19/29] Update upload action to v4 --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 4211f9b..438b9d0 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -179,7 +179,7 @@ jobs: output: 'trivy-backend-image.sarif' - name: upload trivy back-end scan - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: trivy-backend-image.sarif @@ -229,7 +229,7 @@ jobs: output: 'trivy-frontend-image.sarif' - name: upload trivy front-end scan - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: trivy-frontend-image.sarif From cba3814586ce5f14d20539bd9454b213bf78d133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 19:09:38 +0100 Subject: [PATCH 20/29] Fix locating built image for trivy scan --- .github/workflows/ci-cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 438b9d0..43d0ba7 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -156,7 +156,7 @@ jobs: id: meta uses: docker/metadata-action@v4 with: - images: ghcr.io/${{ github.repository }}/back-end + images: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} tags: | type=sha type=ref,event=branch @@ -174,7 +174,7 @@ jobs: - name: run trivy back-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} + image-ref: ${{ steps.meta.outputs.tags }} format: 'sarif' output: 'trivy-backend-image.sarif' @@ -224,7 +224,7 @@ jobs: - name: run trivy front-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ghcr.io/${{ github.repository }}/front-end:${{ github.sha }} + image-ref: ${{ steps.meta.outputs.tags }} format: 'sarif' output: 'trivy-frontend-image.sarif' From fe123de0b82aed8457918b5342642424b34218f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 22:43:52 +0100 Subject: [PATCH 21/29] Fix tags --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 43d0ba7..0da5ae5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -156,7 +156,7 @@ jobs: id: meta uses: docker/metadata-action@v4 with: - images: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} + images: ghcr.io/${{ github.repository }}/back-end tags: | type=sha type=ref,event=branch From 21896d816e1834d0d6ee91f087fb2f9854ea71da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 22:53:10 +0100 Subject: [PATCH 22/29] Fix passing docker image to trivy --- .github/workflows/ci-cd.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 0da5ae5..40c462d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -160,6 +160,7 @@ jobs: tags: | type=sha type=ref,event=branch + type=raw,value= ${{ github.sha }} type=raw,value=latest,enable={{is_default_branch}} - name: build and push back-end image @@ -174,7 +175,7 @@ jobs: - name: run trivy back-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ${{ steps.meta.outputs.tags }} + image-ref: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} format: 'sarif' output: 'trivy-backend-image.sarif' @@ -210,6 +211,7 @@ jobs: tags: | type=sha type=ref,event=branch + type=raw,value= ${{ github.sha }} type=raw,value=latest,enable={{is_default_branch}} - name: build and push front-end image @@ -224,7 +226,7 @@ jobs: - name: run trivy front-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ${{ steps.meta.outputs.tags }} + image-ref: ghcr.io/${{ github.repository }}/front-end:${{ github.sha }} format: 'sarif' output: 'trivy-frontend-image.sarif' From 1772968ad9d70c50afb5209d7cc5e869c35159ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:09:45 +0100 Subject: [PATCH 23/29] Fix trivy action not lowercasing image ref automatically --- .github/workflows/ci-cd.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 40c462d..1406ef5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -171,11 +171,15 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + - name: lowercase repository name + id: repo + run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + # scanning built image with trivy - name: run trivy back-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ghcr.io/${{ github.repository }}/back-end:${{ github.sha }} + image-ref: ghcr.io/${{ steps.repo.outputs.name }}/back-end:${{ github.sha }} format: 'sarif' output: 'trivy-backend-image.sarif' @@ -222,11 +226,15 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + - name: lowercase repository name + id: repo + run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + # scanning built image with trivy - name: run trivy front-end scan uses: aquasecurity/trivy-action@master with: - image-ref: ghcr.io/${{ github.repository }}/front-end:${{ github.sha }} + image-ref: ghcr.io/${{ steps.repo.outputs.name }}/front-end:${{ github.sha }} format: 'sarif' output: 'trivy-frontend-image.sarif' From 8caace4e302a02fc2bf78715a226e209b9023bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:29:34 +0100 Subject: [PATCH 24/29] Separate flow into multiple files --- .github/workflows/build-backend.yml | 68 ++++++++++++++++++++++++++++ .github/workflows/build-frontend.yml | 68 ++++++++++++++++++++++++++++ .github/workflows/lint.yml | 35 ++++++++++++++ .github/workflows/security.yml | 58 ++++++++++++++++++++++++ .github/workflows/test.yml | 66 +++++++++++++++++++++++++++ 5 files changed, 295 insertions(+) create mode 100644 .github/workflows/build-backend.yml create mode 100644 .github/workflows/build-frontend.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/security.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/build-backend.yml b/.github/workflows/build-backend.yml new file mode 100644 index 0000000..e4db3cd --- /dev/null +++ b/.github/workflows/build-backend.yml @@ -0,0 +1,68 @@ +name: Build Backend + +on: + workflow_run: + workflows: ["Security Scanning", "Linting", "Tests"] + types: + - completed + branches: + [master, develop] + +jobs: + build-push-backend: + name: build and push back-end image + runs-on: ubuntu-latest + # Only run if all prerequisite workflows succeeded + if: ${{ github.event.workflow_run.conclusion == 'success' }} + permissions: + contents: read + packages: write + security-events: write + steps: + - uses: actions/checkout@v5 + + - name: log in to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }}/back-end + tags: | + type=sha + type=ref,event=branch + type=raw,value= ${{ github.sha }} + type=raw,value=latest,enable={{is_default_branch}} + + - name: build and push back-end image + uses: docker/build-push-action@v4 + with: + context: ./back-end + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: lowercase repository name + id: repo + run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + # scanning built image with trivy + - name: run trivy back-end scan + uses: aquasecurity/trivy-action@master + with: + image-ref: ghcr.io/${{ steps.repo.outputs.name }}/back-end:${{ github.sha }} + format: 'sarif' + output: 'trivy-backend-image.sarif' + + - name: upload trivy back-end scan + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: trivy-backend-image.sarif + category: 'trivy back-end' + diff --git a/.github/workflows/build-frontend.yml b/.github/workflows/build-frontend.yml new file mode 100644 index 0000000..d80bdfe --- /dev/null +++ b/.github/workflows/build-frontend.yml @@ -0,0 +1,68 @@ +name: Build Frontend + +on: + workflow_run: + workflows: ["Security Scanning", "Linting", "Tests"] + types: + - completed + branches: + [master, develop] + +jobs: + build-push-frontend: + name: build and push front-end image + runs-on: ubuntu-latest + # Only run if all prerequisite workflows succeeded + if: ${{ github.event.workflow_run.conclusion == 'success' }} + permissions: + contents: read + packages: write + security-events: write + steps: + - uses: actions/checkout@v5 + + - name: log in to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }}/front-end + tags: | + type=sha + type=ref,event=branch + type=raw,value= ${{ github.sha }} + type=raw,value=latest,enable={{is_default_branch}} + + - name: build and push front-end image + uses: docker/build-push-action@v4 + with: + context: ./front-end + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: lowercase repository name + id: repo + run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + # scanning built image with trivy + - name: run trivy front-end scan + uses: aquasecurity/trivy-action@master + with: + image-ref: ghcr.io/${{ steps.repo.outputs.name }}/front-end:${{ github.sha }} + format: 'sarif' + output: 'trivy-frontend-image.sarif' + + - name: upload trivy front-end scan + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: trivy-frontend-image.sarif + category: 'trivy front-end' + diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..7f1b423 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,35 @@ +name: Linting + +on: + push: + branches: + [master, develop] + pull_request: + branches: + [master, develop] + +jobs: + lint: + name: code linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: install flake8 + run: pip install flake8 + + - name: lint back-end + run: | + flake8 back-end/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 back-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: lint front-end + run: | + flake8 front-end/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 front-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..5c489be --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,58 @@ +name: Security Scanning + +on: + push: + branches: + [master, develop] + pull_request: + branches: + [master, develop] + +jobs: + vulnerability-scan: + name: source vulnerability scan + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' # use latest python 3 version + + # use pip-audit to scan dependencies + - name: pip-audit install + run: pip install pip-audit + + - name: back-end audit + run: pip-audit -r back-end/requirements.txt --desc # add description to output + + - name: front-end audit + run: pip-audit -r front-end/requirements.txt --desc + + + # use bandit to scan source code, output in sarif format + - name: bandit install + run: pip install bandit[sarif] + + - name: back-end bandit + run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports + + - name: upload backend bandit report + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: bandit-backend.sarif + category: 'bandit backend' + + - name: front-end bandit + run: bandit -r front-end/ -f sarif -o bandit-frontend.sarif --exit-zero + + - name: upload frontend bandit report + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: bandit-frontend.sarif + category: 'bandit frontend' + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..8fe89af --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,66 @@ +name: Tests + +on: + push: + branches: + [master, develop] + pull_request: + branches: + [master, develop] + +jobs: + test-backend: + name: back-end tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: install dependencies + working-directory: ./back-end + run: | + pip install -r requirements.txt + pip install -r requirements_test.txt + + - name: run tests + env: + POSTGRES_DB: ${{secrets.POSTGRES_DB}} + POSTGRES_USER: ${{secrets.POSTGRES_USER}} + POSTGRES_PASSWORD: ${{secrets.POSTGRES_PASSWORD}} + POSTGRES_HOST: ${{secrets.POSTGRES_HOST}} + PORT: ${{secrets.PORT}} + JWT_KEY: ${{secrets.JWT_KEY}} + APP_PORT: ${{secrets.APP_PORT}} + working-directory: ./back-end + run: pytest test_app.py -v + + test-frontend: + name: front-end tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: install dependencies + working-directory: ./front-end + run: | + pip install -r requirements.txt + pip install -r requirements_test.txt + + - name: run tests + env: + BACKEND_HOSTNAME: ${{secrets.BACKEND_HOSTNAME}} + BACKEND_PORT: ${{secrets.BACKEND_PORT}} + SECRET_KEY: ${{secrets.SECRET_KEY}} + SERVER_PORT: ${{secrets.SERVER_PORT}} + working-directory: ./front-end + run: pytest test_app.py -v + From 038ba24121d524268492591f9fe0f163518b9d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:39:52 +0100 Subject: [PATCH 25/29] Refactor to use reusable workflows --- .github/workflows/build-backend.yml | 56 ++------------------- .github/workflows/build-frontend.yml | 56 ++------------------- .github/workflows/lint.yml | 30 +++--------- .github/workflows/reusable-build.yml | 65 +++++++++++++++++++++++++ .github/workflows/reusable-lint.yml | 30 ++++++++++++ .github/workflows/reusable-security.yml | 41 ++++++++++++++++ .github/workflows/reusable-test.yml | 44 +++++++++++++++++ .github/workflows/security.yml | 55 ++++----------------- .github/workflows/test.yml | 59 +++------------------- 9 files changed, 211 insertions(+), 225 deletions(-) create mode 100644 .github/workflows/reusable-build.yml create mode 100644 .github/workflows/reusable-lint.yml create mode 100644 .github/workflows/reusable-security.yml create mode 100644 .github/workflows/reusable-test.yml diff --git a/.github/workflows/build-backend.yml b/.github/workflows/build-backend.yml index e4db3cd..261b2ea 100644 --- a/.github/workflows/build-backend.yml +++ b/.github/workflows/build-backend.yml @@ -10,59 +10,9 @@ on: jobs: build-push-backend: - name: build and push back-end image - runs-on: ubuntu-latest + uses: ./.github/workflows/reusable-build.yml # Only run if all prerequisite workflows succeeded if: ${{ github.event.workflow_run.conclusion == 'success' }} - permissions: - contents: read - packages: write - security-events: write - steps: - - uses: actions/checkout@v5 - - - name: log in to container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: extract metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ghcr.io/${{ github.repository }}/back-end - tags: | - type=sha - type=ref,event=branch - type=raw,value= ${{ github.sha }} - type=raw,value=latest,enable={{is_default_branch}} - - - name: build and push back-end image - uses: docker/build-push-action@v4 - with: - context: ./back-end - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: lowercase repository name - id: repo - run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - # scanning built image with trivy - - name: run trivy back-end scan - uses: aquasecurity/trivy-action@master - with: - image-ref: ghcr.io/${{ steps.repo.outputs.name }}/back-end:${{ github.sha }} - format: 'sarif' - output: 'trivy-backend-image.sarif' - - - name: upload trivy back-end scan - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: trivy-backend-image.sarif - category: 'trivy back-end' + with: + service: back-end diff --git a/.github/workflows/build-frontend.yml b/.github/workflows/build-frontend.yml index d80bdfe..d9be6a4 100644 --- a/.github/workflows/build-frontend.yml +++ b/.github/workflows/build-frontend.yml @@ -10,59 +10,9 @@ on: jobs: build-push-frontend: - name: build and push front-end image - runs-on: ubuntu-latest + uses: ./.github/workflows/reusable-build.yml # Only run if all prerequisite workflows succeeded if: ${{ github.event.workflow_run.conclusion == 'success' }} - permissions: - contents: read - packages: write - security-events: write - steps: - - uses: actions/checkout@v5 - - - name: log in to container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: extract metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ghcr.io/${{ github.repository }}/front-end - tags: | - type=sha - type=ref,event=branch - type=raw,value= ${{ github.sha }} - type=raw,value=latest,enable={{is_default_branch}} - - - name: build and push front-end image - uses: docker/build-push-action@v4 - with: - context: ./front-end - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: lowercase repository name - id: repo - run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - # scanning built image with trivy - - name: run trivy front-end scan - uses: aquasecurity/trivy-action@master - with: - image-ref: ghcr.io/${{ steps.repo.outputs.name }}/front-end:${{ github.sha }} - format: 'sarif' - output: 'trivy-frontend-image.sarif' - - - name: upload trivy front-end scan - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: trivy-frontend-image.sarif - category: 'trivy front-end' + with: + service: front-end diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7f1b423..ae4c748 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,27 +9,13 @@ on: [master, develop] jobs: - lint: - name: code linting - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 + lint-backend: + uses: ./.github/workflows/reusable-lint.yml + with: + service: back-end - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install flake8 - run: pip install flake8 - - - name: lint back-end - run: | - flake8 back-end/ --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 back-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - - name: lint front-end - run: | - flake8 front-end/ --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 front-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + lint-frontend: + uses: ./.github/workflows/reusable-lint.yml + with: + service: front-end diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml new file mode 100644 index 0000000..55b4064 --- /dev/null +++ b/.github/workflows/reusable-build.yml @@ -0,0 +1,65 @@ +name: Reusable Build and Push Workflow + +on: + workflow_call: + inputs: + service: + description: 'Service to build (back-end or front-end)' + required: true + type: string + +jobs: + build-push: + name: build and push ${{ inputs.service }} image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + security-events: write + steps: + - uses: actions/checkout@v5 + + - name: log in to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }}/${{ inputs.service }} + tags: | + type=sha + type=ref,event=branch + type=raw,value= ${{ github.sha }} + type=raw,value=latest,enable={{is_default_branch}} + + - name: build and push ${{ inputs.service }} image + uses: docker/build-push-action@v4 + with: + context: ./${{ inputs.service }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: lowercase repository name + id: repo + run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + - name: run trivy ${{ inputs.service }} scan + uses: aquasecurity/trivy-action@master + with: + image-ref: ghcr.io/${{ steps.repo.outputs.name }}/${{ inputs.service }}:${{ github.sha }} + format: 'sarif' + output: 'trivy-${{ inputs.service }}-image.sarif' + + - name: upload trivy ${{ inputs.service }} scan + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: trivy-${{ inputs.service }}-image.sarif + category: 'trivy ${{ inputs.service }}' + diff --git a/.github/workflows/reusable-lint.yml b/.github/workflows/reusable-lint.yml new file mode 100644 index 0000000..a41e5b0 --- /dev/null +++ b/.github/workflows/reusable-lint.yml @@ -0,0 +1,30 @@ +name: Reusable Lint Workflow + +on: + workflow_call: + inputs: + service: + description: 'Service to lint (back-end or front-end)' + required: true + type: string + +jobs: + lint: + name: lint ${{ inputs.service }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: install flake8 + run: pip install flake8 + + - name: lint ${{ inputs.service }} + run: | + flake8 ${{ inputs.service }}/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 ${{ inputs.service }}/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + diff --git a/.github/workflows/reusable-security.yml b/.github/workflows/reusable-security.yml new file mode 100644 index 0000000..4c0d288 --- /dev/null +++ b/.github/workflows/reusable-security.yml @@ -0,0 +1,41 @@ +name: Reusable Security Scan Workflow + +on: + workflow_call: + inputs: + service: + description: 'Service to scan (back-end or front-end)' + required: true + type: string + +jobs: + scan: + name: security scan ${{ inputs.service }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: pip-audit install + run: pip install pip-audit + + - name: ${{ inputs.service }} audit + run: pip-audit -r ${{ inputs.service }}/requirements.txt --desc + + - name: bandit install + run: pip install bandit[sarif] + + - name: ${{ inputs.service }} bandit scan + run: bandit -r ${{ inputs.service }}/ -f sarif -o bandit-${{ inputs.service }}.sarif --exit-zero + + - name: upload ${{ inputs.service }} bandit report + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: bandit-${{ inputs.service }}.sarif + category: 'bandit ${{ inputs.service }}' + diff --git a/.github/workflows/reusable-test.yml b/.github/workflows/reusable-test.yml new file mode 100644 index 0000000..ce4ad22 --- /dev/null +++ b/.github/workflows/reusable-test.yml @@ -0,0 +1,44 @@ +name: Reusable Test Workflow + +on: + workflow_call: + inputs: + service: + description: 'Service to test (back-end or front-end)' + required: true + type: string + +jobs: + test: + name: ${{ inputs.service }} tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: python setup + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: install dependencies + working-directory: ./${{ inputs.service }} + run: | + pip install -r requirements.txt + pip install -r requirements_test.txt + + - name: run tests + env: + POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }} + PORT: ${{ secrets.PORT }} + JWT_KEY: ${{ secrets.JWT_KEY }} + APP_PORT: ${{ secrets.APP_PORT }} + BACKEND_HOSTNAME: ${{ secrets.BACKEND_HOSTNAME }} + BACKEND_PORT: ${{ secrets.BACKEND_PORT }} + SECRET_KEY: ${{ secrets.SECRET_KEY }} + SERVER_PORT: ${{ secrets.SERVER_PORT }} + working-directory: ./${{ inputs.service }} + run: pytest test_app.py -v + diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 5c489be..97f4d45 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -9,50 +9,13 @@ on: [master, develop] jobs: - vulnerability-scan: - name: source vulnerability scan - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' # use latest python 3 version - - # use pip-audit to scan dependencies - - name: pip-audit install - run: pip install pip-audit - - - name: back-end audit - run: pip-audit -r back-end/requirements.txt --desc # add description to output - - - name: front-end audit - run: pip-audit -r front-end/requirements.txt --desc - - - # use bandit to scan source code, output in sarif format - - name: bandit install - run: pip install bandit[sarif] - - - name: back-end bandit - run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports - - - name: upload backend bandit report - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: bandit-backend.sarif - category: 'bandit backend' - - - name: front-end bandit - run: bandit -r front-end/ -f sarif -o bandit-frontend.sarif --exit-zero - - - name: upload frontend bandit report - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: bandit-frontend.sarif - category: 'bandit frontend' + scan-backend: + uses: ./.github/workflows/reusable-security.yml + with: + service: back-end + + scan-frontend: + uses: ./.github/workflows/reusable-security.yml + with: + service: front-end diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8fe89af..fe9df2b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,57 +10,14 @@ on: jobs: test-backend: - name: back-end tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install dependencies - working-directory: ./back-end - run: | - pip install -r requirements.txt - pip install -r requirements_test.txt - - - name: run tests - env: - POSTGRES_DB: ${{secrets.POSTGRES_DB}} - POSTGRES_USER: ${{secrets.POSTGRES_USER}} - POSTGRES_PASSWORD: ${{secrets.POSTGRES_PASSWORD}} - POSTGRES_HOST: ${{secrets.POSTGRES_HOST}} - PORT: ${{secrets.PORT}} - JWT_KEY: ${{secrets.JWT_KEY}} - APP_PORT: ${{secrets.APP_PORT}} - working-directory: ./back-end - run: pytest test_app.py -v + uses: ./.github/workflows/reusable-test.yml + with: + service: back-end + secrets: inherit test-frontend: - name: front-end tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install dependencies - working-directory: ./front-end - run: | - pip install -r requirements.txt - pip install -r requirements_test.txt - - - name: run tests - env: - BACKEND_HOSTNAME: ${{secrets.BACKEND_HOSTNAME}} - BACKEND_PORT: ${{secrets.BACKEND_PORT}} - SECRET_KEY: ${{secrets.SECRET_KEY}} - SERVER_PORT: ${{secrets.SERVER_PORT}} - working-directory: ./front-end - run: pytest test_app.py -v + uses: ./.github/workflows/reusable-test.yml + with: + service: front-end + secrets: inherit From 1b81bd03dd1f62a67fb3352484415ba893587d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:49:07 +0100 Subject: [PATCH 26/29] Create a single workflow --- .github/workflows/ci-cd.yml | 285 +++++++----------------------------- 1 file changed, 53 insertions(+), 232 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 1406ef5..d9f76b5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,4 +1,4 @@ -name: CI/CD pipeline +name: CI/CD Pipeline on: push: @@ -9,238 +9,59 @@ on: [master, develop] jobs: - vulnerability-scan: - name: source vulnerability scan - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' # use latest python 3 version - - # use pip-audit to scan dependencies - - name: pip-audit install - run: pip install pip-audit - - - name: back-end audit - run: pip-audit -r back-end/requirements.txt --desc # add description to output - - - name: front-end audit - run: pip-audit -r front-end/requirements.txt --desc - - - # use bandit to scan source code, output in sarif format - - name: bandit install - run: pip install bandit[sarif] - - - name: back-end bandit - run: bandit -r back-end/ -f sarif -o bandit-backend.sarif --exit-zero # exit-zero doesn't fail build, only reports - - - name: upload backend bandit report - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: bandit-backend.sarif - category: 'bandit backend' - - - name: front-end bandit - run: bandit -r front-end/ -f sarif -o bandit-frontend.sarif --exit-zero - - - name: upload frontend bandit report - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: bandit-frontend.sarif - category: 'bandit frontend' - lint: - name: code linting - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install flake8 - run: pip install flake8 - - - name: lint back-end - run: | - flake8 back-end/ --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 back-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - - name: lint front-end - run: | - flake8 front-end/ --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 front-end/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - - + # Testing jobs test-backend: - name: back-end tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install dependencies - working-directory: ./back-end - run: | - pip install -r requirements.txt - pip install -r requirements_test.txt + name: Test Backend + uses: ./.github/workflows/reusable-test.yml + with: + service: back-end + secrets: inherit - - name: run tests - env: - POSTGRES_DB: ${{secrets.POSTGRES_DB}} - POSTGRES_USER: ${{secrets.POSTGRES_USER}} - POSTGRES_PASSWORD: ${{secrets.POSTGRES_PASSWORD}} - POSTGRES_HOST: ${{secrets.POSTGRES_HOST}} - PORT: ${{secrets.PORT}} - JWT_KEY: ${{secrets.JWT_KEY}} - APP_PORT: ${{secrets.APP_PORT}} - working-directory: ./back-end - run: pytest test_app.py -v test-frontend: - name: front-end tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: python setup - uses: actions/setup-python@v6 - with: - python-version: '3.13' - - - name: install dependencies - working-directory: ./front-end - run: | - pip install -r requirements.txt - pip install -r requirements_test.txt - - - name: run tests - env: - BACKEND_HOSTNAME: ${{secrets.BACKEND_HOSTNAME}} - BACKEND_PORT: ${{secrets.BACKEND_PORT}} - SECRET_KEY: ${{secrets.SECRET_KEY}} - SERVER_PORT: ${{secrets.SERVER_PORT}} - working-directory: ./front-end - run: pytest test_app.py -v - build-push-backend: - name: build and push back-end image - runs-on: ubuntu-latest - needs: [vulnerability-scan, lint, test-backend] - permissions: - contents: read - packages: write - security-events: write - steps: - - uses: actions/checkout@v5 - - - name: log in to container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: extract metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ghcr.io/${{ github.repository }}/back-end - tags: | - type=sha - type=ref,event=branch - type=raw,value= ${{ github.sha }} - type=raw,value=latest,enable={{is_default_branch}} - - - name: build and push back-end image - uses: docker/build-push-action@v4 - with: - context: ./back-end - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: lowercase repository name - id: repo - run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - # scanning built image with trivy - - name: run trivy back-end scan - uses: aquasecurity/trivy-action@master - with: - image-ref: ghcr.io/${{ steps.repo.outputs.name }}/back-end:${{ github.sha }} - format: 'sarif' - output: 'trivy-backend-image.sarif' - - - name: upload trivy back-end scan - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: trivy-backend-image.sarif - category: 'trivy back-end' - build-push-frontend: - name: build and push front-end image - runs-on: ubuntu-latest - needs: [ vulnerability-scan, lint, test-frontend ] - permissions: - contents: read - packages: write - security-events: write - steps: - - uses: actions/checkout@v5 - - - name: log in to container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: extract metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ghcr.io/${{ github.repository }}/front-end - tags: | - type=sha - type=ref,event=branch - type=raw,value= ${{ github.sha }} - type=raw,value=latest,enable={{is_default_branch}} - - - name: build and push front-end image - uses: docker/build-push-action@v4 - with: - context: ./front-end - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: lowercase repository name - id: repo - run: echo "name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - # scanning built image with trivy - - name: run trivy front-end scan - uses: aquasecurity/trivy-action@master - with: - image-ref: ghcr.io/${{ steps.repo.outputs.name }}/front-end:${{ github.sha }} - format: 'sarif' - output: 'trivy-frontend-image.sarif' + name: Test Frontend + uses: ./.github/workflows/reusable-test.yml + with: + service: front-end + secrets: inherit + + # Linting jobs + lint-backend: + name: Lint Backend + uses: ./.github/workflows/reusable-lint.yml + with: + service: back-end + + lint-frontend: + name: Lint Frontend + uses: ./.github/workflows/reusable-lint.yml + with: + service: front-end + + # Security scanning jobs + scan-backend: + name: Security Scan Backend + uses: ./.github/workflows/reusable-security.yml + with: + service: back-end + + scan-frontend: + name: Security Scan Frontend + uses: ./.github/workflows/reusable-security.yml + with: + service: front-end + + # Build jobs - only run after all checks pass + build-backend: + name: Build Backend + needs: [test-backend, lint-backend, scan-backend] + uses: ./.github/workflows/reusable-build.yml + with: + service: back-end + + build-frontend: + name: Build Frontend + needs: [test-frontend, lint-frontend, scan-frontend] + uses: ./.github/workflows/reusable-build.yml + with: + service: front-end - - name: upload trivy front-end scan - uses: github/codeql-action/upload-sarif@v4 - if: always() - with: - sarif_file: trivy-frontend-image.sarif - category: 'trivy front-end' \ No newline at end of file From b360cf7f2393ca4a5a753a961197014e5ab54c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:53:49 +0100 Subject: [PATCH 27/29] Remove the separate workflows (now using reusable workflows) --- .github/workflows/build-backend.yml | 18 ------------------ .github/workflows/build-frontend.yml | 18 ------------------ .github/workflows/lint.yml | 21 --------------------- .github/workflows/security.yml | 21 --------------------- .github/workflows/test.yml | 23 ----------------------- 5 files changed, 101 deletions(-) delete mode 100644 .github/workflows/build-backend.yml delete mode 100644 .github/workflows/build-frontend.yml delete mode 100644 .github/workflows/lint.yml delete mode 100644 .github/workflows/security.yml delete mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/build-backend.yml b/.github/workflows/build-backend.yml deleted file mode 100644 index 261b2ea..0000000 --- a/.github/workflows/build-backend.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Build Backend - -on: - workflow_run: - workflows: ["Security Scanning", "Linting", "Tests"] - types: - - completed - branches: - [master, develop] - -jobs: - build-push-backend: - uses: ./.github/workflows/reusable-build.yml - # Only run if all prerequisite workflows succeeded - if: ${{ github.event.workflow_run.conclusion == 'success' }} - with: - service: back-end - diff --git a/.github/workflows/build-frontend.yml b/.github/workflows/build-frontend.yml deleted file mode 100644 index d9be6a4..0000000 --- a/.github/workflows/build-frontend.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Build Frontend - -on: - workflow_run: - workflows: ["Security Scanning", "Linting", "Tests"] - types: - - completed - branches: - [master, develop] - -jobs: - build-push-frontend: - uses: ./.github/workflows/reusable-build.yml - # Only run if all prerequisite workflows succeeded - if: ${{ github.event.workflow_run.conclusion == 'success' }} - with: - service: front-end - diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index ae4c748..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Linting - -on: - push: - branches: - [master, develop] - pull_request: - branches: - [master, develop] - -jobs: - lint-backend: - uses: ./.github/workflows/reusable-lint.yml - with: - service: back-end - - lint-frontend: - uses: ./.github/workflows/reusable-lint.yml - with: - service: front-end - diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index 97f4d45..0000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Security Scanning - -on: - push: - branches: - [master, develop] - pull_request: - branches: - [master, develop] - -jobs: - scan-backend: - uses: ./.github/workflows/reusable-security.yml - with: - service: back-end - - scan-frontend: - uses: ./.github/workflows/reusable-security.yml - with: - service: front-end - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index fe9df2b..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Tests - -on: - push: - branches: - [master, develop] - pull_request: - branches: - [master, develop] - -jobs: - test-backend: - uses: ./.github/workflows/reusable-test.yml - with: - service: back-end - secrets: inherit - - test-frontend: - uses: ./.github/workflows/reusable-test.yml - with: - service: front-end - secrets: inherit - From c110aca32a6aa34e02021d9e26e443e6dbc03ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:57:06 +0100 Subject: [PATCH 28/29] Add workflow_dispatch to trigger workflow manually --- .github/workflows/ci-cd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d9f76b5..85e3cbe 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -4,6 +4,7 @@ on: push: branches: [master, develop] + workflow_dispatch: pull_request: branches: [master, develop] From 0159f92f8a8ef33f842c5fa64fbae9324272796b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zychowicz?= Date: Sat, 1 Nov 2025 23:57:20 +0100 Subject: [PATCH 29/29] Add workflow_dispatch to trigger workflow manually --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 85e3cbe..3055871 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,10 +1,10 @@ name: CI/CD Pipeline on: + workflow_dispatch: push: branches: [master, develop] - workflow_dispatch: pull_request: branches: [master, develop]