diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index a98b15e..b76652b 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,41 @@ jobs: steps: - 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 }} + + # RENAMED to match your screenshot + - name: Prepare Docker image tags + 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: . + file: docker/Dockerfile + # 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 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/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. 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/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 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