From 930e4b1ecc20f5e3ea5a6f5193024ce8fd984287 Mon Sep 17 00:00:00 2001 From: Jasper Wink <117076930+JasperWink@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:59:23 +0100 Subject: [PATCH 1/4] Add amazing feature --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79bb814..d43d870 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ GitOps with FastAPI ***University of Amsterdam*** -# 1. Introduction +# 1. Introduction In this tutorial, we use GitOps practices with FastAPI, including CI/CD pipelines, code quality tools, and automated testing. From 6f9a786fd5c848b538a89dab78672a6d11341c32 Mon Sep 17 00:00:00 2001 From: Jasper Wink <117076930+JasperWink@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:53:01 +0100 Subject: [PATCH 2/4] Added to ci-cd yaml --- .github/workflows/ci-cd.yml | 53 +++++++++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 32 ++++++++++++++++++++++ app/main.py | 11 ++++++++ tests/test_main.py | 14 ++++++++++ 4 files changed, 110 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index a98b15e..31d8ed5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -19,6 +19,17 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.14.3" + + - name: Install Ruff + run: pip install ruff + + - name: Run Ruff + run: ruff check . + test: name: Run Tests runs-on: ubuntu-latest @@ -28,6 +39,18 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.14.3" + + - name: Install dependencies + run: | + pip install -r requirements.txt + + - name: Run tests with coverage + run: pytest --cov=. --cov-fail-under=80 + build: name: Build Docker Image runs-on: ubuntu-latest @@ -40,3 +63,33 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + if: github.event_name == 'release' + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + # On a push (non-release), tag with the git short commit SHA + type=sha,enable=${{ github.event_name == 'push' }} + # On release, tag with the release version (e.g. v1.0.0) + type=semver,pattern={{version}} + # On release, also tag with 'latest' + type=raw,value=latest,enable=${{ github.event_name == 'release' }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + # Only push if the workflow was triggered by a release + push: ${{ github.event_name == 'release' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d337d10..b3c0618 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,3 +3,35 @@ repos: rev: v5.0.0 hooks: - id: trailing-whitespace + # Prevent committing large files + - id: check-added-large-files + # Check YAML files for syntax errors + - id: check-yaml + # Excluding Helm charts + exclude: ^(helm|charts?)/ + + # Sort imports in Python files + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + + # Check code style + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + + # Check for security issues + - repo: https://github.com/PyCQA/bandit + rev: 1.8.2 + hooks: + - id: bandit + # Exclude test files from security scans + exclude: ^tests/ + + # Make sure we do not commit secrets + - repo: https://github.com/gitleaks/gitleaks + rev: v8.23.3 + hooks: + - id: gitleaks \ No newline at end of file diff --git a/app/main.py b/app/main.py index ae8adc6..364bed9 100644 --- a/app/main.py +++ b/app/main.py @@ -49,5 +49,16 @@ async def get_item(item_id: int): } +@app.post("/api/items") +async def create_item(name: str, description: str): + """Create a new item.""" + return { + "id": 999, + "name": name, + "description": description, + "created": True + } + + if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/tests/test_main.py b/tests/test_main.py index db89e2f..0dcd03a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -41,3 +41,17 @@ def test_get_item(): assert data["id"] == 5 assert data["name"] == "Item 5" assert "item number 5" in data["description"] + + +def test_post_items(): + """Test the list items endpoint.""" + response = client.post( + "/api/items", + params={"name": "Hallo", "description": "Dag"} + ) + assert response.status_code == 200 + data = response.json() + assert data["id"] == 999 + assert data["name"] == "Hallo" + assert data["description"] == "Dag" + assert "created" in data From 9db3bd6bb45022bacadd3f37a8cd93e35a32ac38 Mon Sep 17 00:00:00 2001 From: Jasper Wink <117076930+JasperWink@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:07:14 +0100 Subject: [PATCH 3/4] Added docker path to ci-cd.yaml --- .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 31d8ed5..dc27e62 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -89,6 +89,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . + file: docker/Dockerfile # Only push if the workflow was triggered by a release push: ${{ github.event_name == 'release' }} tags: ${{ steps.meta.outputs.tags }} From 64970990e7219e4f34765b14cdb515739a0120e8 Mon Sep 17 00:00:00 2001 From: Jasper Wink <117076930+JasperWink@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:01:41 +0100 Subject: [PATCH 4/4] Changed docker file to push to registry --- .github/workflows/ci-cd.yml | 13 ++++++++++--- helm/fastapi-gitops-starter/custom-values.yaml | 5 +++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 helm/fastapi-gitops-starter/custom-values.yaml diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index dc27e62..b76652b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -64,15 +64,21 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + # ADDED: Set up Docker Buildx (matches your screenshot) + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to GitHub Container Registry uses: docker/login-action@v3 + # Remove the next line if you want to push on regular commits, not just releases if: github.event_name == 'release' with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker + # RENAMED to match your screenshot + - name: Prepare Docker image tags id: meta uses: docker/metadata-action@v5 with: @@ -90,7 +96,8 @@ jobs: with: context: . file: docker/Dockerfile - # Only push if the workflow was triggered by a release + # Change this to `push: true` if you want it to push on every commit push: ${{ github.event_name == 'release' }} tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + labels: ${{ steps.meta.outputs.labels }} + \ No newline at end of file diff --git a/helm/fastapi-gitops-starter/custom-values.yaml b/helm/fastapi-gitops-starter/custom-values.yaml new file mode 100644 index 0000000..3de5f9c --- /dev/null +++ b/helm/fastapi-gitops-starter/custom-values.yaml @@ -0,0 +1,5 @@ +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 10 + targetCPUUtilizationPercentage: 10