Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- uses: actions/setup-python@v4
with:
python-version: 3.11

- run: pip install -r requirements.txt

- name: Lint code
run: ruff check app/ tests/ --fix


test:
name: Run Tests
runs-on: ubuntu-latest
Expand All @@ -28,6 +38,15 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- uses: actions/setup-python@v4
with:
python-version: 3.11

- run: pip install -r requirements.txt

- name: Run coverage test
run: pytest --cov=app --cov-report=html --cov-fail-under=80

build:
name: Build Docker Image
runs-on: ubuntu-latest
Expand All @@ -40,3 +59,26 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Build docker image
run: docker build -t ${{ secrets.REGISTRY_USERNAME }}/fastapi-gitops-starter:latest -f docker/Dockerfile .

- name: Add tag image on release
if: github.event_name == 'release'
run: |
docker tag ${{ secrets.REGISTRY_USERNAME }}/fastapi-gitops-starter:latest \
${{ secrets.REGISTRY_USERNAME }}/fastapi-gitops-starter:${{ github.ref_name }}

- name: Login to Container Registry
uses: docker/login-action@v1
with:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- name: Push Docker image
run: |
docker push ${{ secrets.REGISTRY_USERNAME }}/fastapi-gitops-starter:latest
if [ "${GITHUB_EVENT_NAME}" = "release" ]; then
docker push ${{ secrets.REGISTRY_USERNAME }}/fastapi-gitops-starter:${GITHUB_REF_NAME}
fi

2 changes: 1 addition & 1 deletion .github/workflows/markdown2pdf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

- name: Replace links
run: |
cp README.md README_WITH_LINKS.md
cp README.md README_WITH_LINKS.md
sed -i -e "s#\(^\!\[[^]]\+\](\)\(images/\)#\1$URL/\2#g" README_WITH_LINKS.md
for file in sources/*; do sed -i -e "s#($file)#($URL/$file)#g" README_WITH_LINKS.md ; done

Expand Down
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ repos:
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: check-added-large-files
- id: check-yaml
exclude: "helm/.*\\.yaml"
- id: requirements-txt-fixer
- id: detect-private-key
- id: check-ast
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -35,7 +35,7 @@ In this tutorial, we use GitOps practices with FastAPI, including CI/CD pipeline



# 2. Tutorial
# 2. Tutorial

The steps of this tutorial are as follows:
- [Building REST APIs with FastAPI](#21-setting-up-the-project)
Expand All @@ -60,17 +60,17 @@ Prerequisites:
```

* Set Up the Python Environmentt:

```bash
# Create a virtual environment
python -m venv venv

# Activate the virtual environment
# On Linux/MacOS:
source venv/bin/activate
# On Windows:
venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt
```
Expand Down Expand Up @@ -110,7 +110,7 @@ Prerequisites:
```bash
# Check for issues
ruff check app/ tests/

# Fix auto-fixable issues
ruff check app/ tests/ --fix
```
Expand All @@ -120,7 +120,7 @@ Prerequisites:
```bash
# Check formatting
black --check app/ tests/

# Format code
black app/ tests/
```
Expand All @@ -134,19 +134,19 @@ Pre-commit hooks automatically run checks before each commit to ensure consisten
```bash
# Install pre-commit
pip install pre-commit

# Install the git hooks
pre-commit install
```

* Using Pre-commit:

Pre-commit will now run automatically on `git commit`. You can also run it manually:

```bash
# Run on all files
pre-commit run --all-files

# Run on staged files
pre-commit run
```
Expand Down Expand Up @@ -200,14 +200,14 @@ This repository includes a Helm chart for deploying the application to Kubernete
- Kubernetes 1.19+
- Helm 3.0+

* Install the Helm Chart:
* Install the Helm Chart:

```bash
helm install my-release ./helm/fastapi-gitops-starter
```

* Uninstall the Helm Chart:
* Uninstall the Helm Chart:

```bash
helm uninstall my-release
```
Expand Down Expand Up @@ -239,7 +239,7 @@ including host and paths.
* To make sure we do not commit secrets
* To check code style


## 3.2 Add a New Endpoint

1. Open `app/main.py`
Expand Down
6 changes: 6 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,11 @@ 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)
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ COPY ../requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY ../app ./app/
COPY app/ ./app/

# Expose port 8000
EXPOSE 8000
Expand Down
31 changes: 16 additions & 15 deletions helm/fastapi-gitops-starter/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
replicaCount: 1

image:
repository: ghcr.io/qcdis/fastapi-gitops-starter
pullPolicy: IfNotPresent
repository: voshiii/fastapi-gitops-starter
# pullPolicy: IfNotPresent
pullPolicy: Never
# Overrides the image tag whose default is the chart appVersion.
tag: "v0.4"
tag: latest

registry:
createImagePullSecret: true
secretName: image-pull-secret
server: ghcr.io
createImagePullSecret: false
secretName: ""
server: ""
token: ""

imagePullSecrets:
- name: image-pull-secret
#imagePullSecrets:
# - name: image-pull-secret

nameOverride: ""
fullnameOverride: ""
Expand Down Expand Up @@ -50,7 +51,7 @@ securityContext:

service:
type: ClusterIP
port: 80
port: 8000
targetPort: 8000
annotations: {}

Expand Down Expand Up @@ -79,27 +80,27 @@ resources:

livenessProbe:
httpGet:
path: /GitOps-Starter/health
port: http
path: /health #/GitOps-Starter/health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

readinessProbe:
httpGet:
path: /GitOps-Starter/health
port: http
path: /health #/GitOps-Starter/health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3

autoscaling:
enabled: false
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetCPUUtilizationPercentage: 10
targetMemoryUtilizationPercentage: 80

# Additional volumes on the output Deployment definition.
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
black==24.10.0
fastapi==0.115.5
uvicorn[standard]==0.32.1
httpx==0.28.1
pytest==8.3.4
pytest-cov==6.0.0
httpx==0.28.1
ruff==0.8.4
black==24.10.0
uvicorn[standard]==0.32.1
14 changes: 14 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_item():
"""Test the post an item to endpoint."""
response = client.post(
"/api/items",
params={"name": "NewItem", "description": "This is a newly added item"},
)
assert response.status_code == 200
data = response.json()
assert data["id"] == 999
assert data["name"] == "NewItem"
assert data["description"] == "This is a newly added item"
assert data["created"]
Loading