Skip to content

Commit 299a7bb

Browse files
committed
Created new CI workflow
1 parent 04ea919 commit 299a7bb

1 file changed

Lines changed: 255 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
env:
10+
PYTHON_VERSION: '3.11'
11+
NODE_VERSION: '18'
12+
13+
jobs:
14+
test-backend:
15+
name: Test Backend
16+
runs-on: ubuntu-latest
17+
18+
services:
19+
postgres:
20+
image: postgres:15
21+
env:
22+
POSTGRES_PASSWORD: postgres
23+
POSTGRES_USER: postgres
24+
POSTGRES_DB: test_db
25+
options: >-
26+
--health-cmd pg_isready
27+
--health-interval 10s
28+
--health-timeout 5s
29+
--health-retries 5
30+
ports:
31+
- 5432:5432
32+
33+
steps:
34+
- name: Checkout code
35+
uses: actions/checkout@v4
36+
37+
- name: Set up Python
38+
uses: actions/setup-python@v4
39+
with:
40+
python-version: ${{ env.PYTHON_VERSION }}
41+
42+
- name: Install UV (fast Python package installer)
43+
run: |
44+
curl -LsSf https://astral.sh/uv/install.sh | sh
45+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
46+
47+
- name: Install dependencies
48+
working-directory: ./backend
49+
run: |
50+
uv venv
51+
source .venv/bin/activate
52+
uv pip install -r requirements.txt
53+
uv pip install pytest pytest-asyncio httpx
54+
55+
- name: Run backend tests
56+
working-directory: ./backend
57+
env:
58+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
59+
run: |
60+
source .venv/bin/activate
61+
pytest tests/ -v --tb=short
62+
63+
- name: Run API integration tests
64+
working-directory: ./backend
65+
env:
66+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
67+
run: |
68+
source .venv/bin/activate
69+
# Start the server in background
70+
uvicorn main:app --host 0.0.0.0 --port 8000 &
71+
sleep 10
72+
# Run curl tests
73+
python test_curl_examples.py
74+
75+
test-frontend:
76+
name: Test Frontend
77+
runs-on: ubuntu-latest
78+
79+
steps:
80+
- name: Checkout code
81+
uses: actions/checkout@v4
82+
83+
- name: Set up Node.js
84+
uses: actions/setup-node@v4
85+
with:
86+
node-version: ${{ env.NODE_VERSION }}
87+
cache: 'npm'
88+
cache-dependency-path: frontend/package-lock.json
89+
90+
- name: Install frontend dependencies
91+
working-directory: ./frontend
92+
run: npm ci
93+
94+
- name: Run frontend linter
95+
working-directory: ./frontend
96+
run: npm run lint
97+
98+
- name: Build frontend
99+
working-directory: ./frontend
100+
run: npm run build
101+
102+
- name: Run frontend tests (if any)
103+
working-directory: ./frontend
104+
run: |
105+
if [ -f "package.json" ] && grep -q '"test"' package.json; then
106+
npm test
107+
else
108+
echo "No frontend tests found, skipping..."
109+
fi
110+
111+
security-scan:
112+
name: Security Scan
113+
runs-on: ubuntu-latest
114+
needs: [test-backend, test-frontend]
115+
116+
steps:
117+
- name: Checkout code
118+
uses: actions/checkout@v4
119+
120+
- name: Run Trivy vulnerability scanner
121+
uses: aquasecurity/trivy-action@master
122+
with:
123+
scan-type: 'fs'
124+
scan-ref: '.'
125+
format: 'sarif'
126+
output: 'trivy-results.sarif'
127+
128+
- name: Upload Trivy scan results to GitHub Security tab
129+
uses: github/codeql-action/upload-sarif@v2
130+
if: always()
131+
with:
132+
sarif_file: 'trivy-results.sarif'
133+
134+
code-quality:
135+
name: Code Quality
136+
runs-on: ubuntu-latest
137+
138+
steps:
139+
- name: Checkout code
140+
uses: actions/checkout@v4
141+
142+
- name: Set up Python
143+
uses: actions/setup-python@v4
144+
with:
145+
python-version: ${{ env.PYTHON_VERSION }}
146+
147+
- name: Install Python quality tools
148+
run: |
149+
pip install black flake8 mypy bandit safety
150+
151+
- name: Run Black (code formatter check)
152+
working-directory: ./backend
153+
run: black --check --diff .
154+
155+
- name: Run Flake8 (linting)
156+
working-directory: ./backend
157+
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
158+
159+
- name: Run MyPy (type checking)
160+
working-directory: ./backend
161+
run: mypy . --ignore-missing-imports
162+
163+
- name: Run Bandit (security linting)
164+
working-directory: ./backend
165+
run: bandit -r . -x tests/
166+
167+
- name: Run Safety (dependency security check)
168+
working-directory: ./backend
169+
run: safety check -r requirements.txt
170+
171+
build-and-push:
172+
name: Build and Push Docker Images
173+
runs-on: ubuntu-latest
174+
needs: [test-backend, test-frontend, security-scan, code-quality]
175+
if: github.ref == 'refs/heads/main'
176+
177+
steps:
178+
- name: Checkout code
179+
uses: actions/checkout@v4
180+
181+
- name: Set up Docker Buildx
182+
uses: docker/setup-buildx-action@v3
183+
184+
- name: Login to Docker Hub
185+
uses: docker/login-action@v3
186+
with:
187+
username: ${{ secrets.DOCKER_USERNAME }}
188+
password: ${{ secrets.DOCKER_PASSWORD }}
189+
190+
- name: Build and push backend image
191+
uses: docker/build-push-action@v5
192+
with:
193+
context: ./backend
194+
push: true
195+
tags: |
196+
${{ secrets.DOCKER_USERNAME }}/crud-api-backend:latest
197+
${{ secrets.DOCKER_USERNAME }}/crud-api-backend:${{ github.sha }}
198+
cache-from: type=gha
199+
cache-to: type=gha,mode=max
200+
201+
- name: Build and push frontend image
202+
uses: docker/build-push-action@v5
203+
with:
204+
context: ./frontend
205+
push: true
206+
tags: |
207+
${{ secrets.DOCKER_USERNAME }}/crud-api-frontend:latest
208+
${{ secrets.DOCKER_USERNAME }}/crud-api-frontend:${{ github.sha }}
209+
cache-from: type=gha
210+
cache-to: type=gha,mode=max
211+
212+
generate-docs:
213+
name: Generate and Deploy Documentation
214+
runs-on: ubuntu-latest
215+
needs: [test-backend]
216+
if: github.ref == 'refs/heads/main'
217+
218+
steps:
219+
- name: Checkout code
220+
uses: actions/checkout@v4
221+
222+
- name: Set up Python
223+
uses: actions/setup-python@v4
224+
with:
225+
python-version: ${{ env.PYTHON_VERSION }}
226+
227+
- name: Install dependencies
228+
working-directory: ./backend
229+
run: |
230+
pip install -r requirements.txt
231+
232+
- name: Generate OpenAPI schema
233+
working-directory: ./backend
234+
run: |
235+
python export_openapi.py
236+
python generate_curl_snippets.py
237+
238+
- name: Upload OpenAPI artifacts
239+
uses: actions/upload-artifact@v3
240+
with:
241+
name: openapi-docs
242+
path: |
243+
backend/openapi_schema.json
244+
backend/curl_examples.md
245+
backend/curl_examples.json
246+
247+
- name: Deploy to GitHub Pages (if enabled)
248+
if: github.ref == 'refs/heads/main'
249+
uses: peaceiris/actions-gh-pages@v3
250+
with:
251+
github_token: ${{ secrets.GITHUB_TOKEN }}
252+
publish_dir: ./backend
253+
destination_dir: api-docs
254+
keep_files: true
255+
publish_branch: gh-pages

0 commit comments

Comments
 (0)