diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index a98b15e..631ba94 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -19,6 +19,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
+ - name: Install dependencies
+ run: pip install -r requirements.txt
+
+ - name: Lint with Ruff
+ run: ruff check app tests
+
test:
name: Run Tests
runs-on: ubuntu-latest
@@ -28,6 +34,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
+ - name: Install dependencies
+ run: pip install -r requirements.txt
+
+ - name: Run tests with coverage
+ run: pytest --cov=app --cov-report=term --cov-fail-under=80
+
build:
name: Build Docker Image
runs-on: ubuntu-latest
@@ -40,3 +52,22 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
+
+ - name: Build Docker image
+ run: docker build -t fastapi-gitops-starter .
+
+ - name: Log in to GitHub Container Registry
+ if: github.event_name == 'release'
+ run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
+
+ - name: Tag Docker image
+ if: github.event_name == 'release'
+ run: |
+ docker tag fastapi-gitops-starter ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
+ docker tag fastapi-gitops-starter ghcr.io/${{ github.repository }}:latest
+
+ - name: Push Docker image
+ if: github.event_name == 'release'
+ run: |
+ docker push ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
+ docker push ghcr.io/${{ github.repository }}:latest
\ No newline at end of file
diff --git a/.github/workflows/markdown2pdf.yml b/.github/workflows/markdown2pdf.yml
index fcb4671..4177b58 100644
--- a/.github/workflows/markdown2pdf.yml
+++ b/.github/workflows/markdown2pdf.yml
@@ -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
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..ab1f416
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/fastapi-gitops.iml b/.idea/fastapi-gitops.iml
new file mode 100644
index 0000000..55a63f1
--- /dev/null
+++ b/.idea/fastapi-gitops.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..2ecead1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..f954136
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d337d10..6753910 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,3 +3,29 @@ repos:
rev: v5.0.0
hooks:
- id: trailing-whitespace
+ - id: check-added-large-files
+ - id: check-yaml
+ exclude: ^helm/
+
+ - repo: https://github.com/pycqa/isort
+ rev: 5.13.2
+ hooks:
+ - id: isort
+
+ - repo: https://github.com/PyCQA/bandit
+ rev: 1.7.8
+ hooks:
+ - id: bandit
+ pass_filenames: false
+ args: ["-r", "app", "-x", "tests"]
+
+ - repo: https://github.com/Yelp/detect-secrets
+ rev: v1.5.0
+ hooks:
+ - id: detect-secrets
+
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.11.0
+ hooks:
+ - id: ruff
+ - id: ruff-format
\ No newline at end of file
diff --git a/README.md b/README.md
index 79bb814..057f54d 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.
@@ -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)
@@ -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
```
@@ -110,7 +110,7 @@ Prerequisites:
```bash
# Check for issues
ruff check app/ tests/
-
+
# Fix auto-fixable issues
ruff check app/ tests/ --fix
```
@@ -120,7 +120,7 @@ Prerequisites:
```bash
# Check formatting
black --check app/ tests/
-
+
# Format code
black app/ tests/
```
@@ -134,7 +134,7 @@ 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
```
@@ -142,11 +142,11 @@ Pre-commit hooks automatically run checks before each commit to ensure consisten
* 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
```
@@ -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
```
@@ -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`
diff --git a/app/main.py b/app/main.py
index ae8adc6..de09c12 100644
--- a/app/main.py
+++ b/app/main.py
@@ -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)
+ uvicorn.run(app, host="0.0.0.0", port=8000) # nosec B104
diff --git a/tests/test_main.py b/tests/test_main.py
index db89e2f..c179e26 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_create_item():
+ """Test the create item endpoint."""
+ response = client.post(
+ "/api/items", params={"name": "Test Item", "description": "Created from test"}
+ )
+
+ assert response.status_code == 200
+ data = response.json()
+ assert data["id"] == 999
+ assert data["name"] == "Test Item"
+ assert data["description"] == "Created from test"
+ assert data["created"] is True