Skip to content

Commit 2fc93b3

Browse files
committed
first commit
0 parents  commit 2fc93b3

40 files changed

+7571
-0
lines changed

.github/workflows/ci.yml

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
name: Red Hat Learning Paths CI
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
workflow_dispatch:
9+
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME_BACKEND: ${{ github.repository }}-backend
13+
IMAGE_NAME_FRONTEND: ${{ github.repository }}-frontend
14+
15+
jobs:
16+
test-backend:
17+
name: Test Backend
18+
runs-on: ubuntu-latest
19+
20+
services:
21+
postgres:
22+
image: postgres:15-alpine
23+
env:
24+
POSTGRES_PASSWORD: password
25+
POSTGRES_USER: postgres
26+
POSTGRES_DB: test_db
27+
ports:
28+
- 5432:5432
29+
options: >-
30+
--health-cmd pg_isready
31+
--health-interval 10s
32+
--health-timeout 5s
33+
--health-retries 5
34+
35+
steps:
36+
- name: Checkout code
37+
uses: actions/checkout@v4
38+
39+
- name: Set up Python
40+
uses: actions/setup-python@v4
41+
with:
42+
python-version: '3.9'
43+
cache: 'pip'
44+
45+
- name: Install dependencies
46+
working-directory: ./backend
47+
run: |
48+
python -m pip install --upgrade pip
49+
pip install -r requirements.txt
50+
pip install pytest-cov pytest-mock
51+
52+
- name: Run tests
53+
working-directory: ./backend
54+
env:
55+
DATABASE_URL: postgresql://postgres:password@localhost:5432/test_db
56+
OLLAMA_BASE_URL: http://localhost:11434
57+
run: |
58+
python -m pytest test_main.py -v --cov=. --cov-report=xml --cov-report=term-missing
59+
60+
- name: Upload coverage to Codecov
61+
uses: codecov/codecov-action@v3
62+
with:
63+
file: ./backend/coverage.xml
64+
flags: backend
65+
name: backend-coverage
66+
67+
test-frontend:
68+
name: Test Frontend
69+
runs-on: ubuntu-latest
70+
71+
steps:
72+
- name: Checkout code
73+
uses: actions/checkout@v4
74+
75+
- name: Set up Node.js
76+
uses: actions/setup-node@v3
77+
with:
78+
node-version: '18'
79+
cache: 'npm'
80+
cache-dependency-path: ./frontend/package-lock.json
81+
82+
- name: Install dependencies
83+
working-directory: ./frontend
84+
run: npm ci
85+
86+
- name: Run unit tests
87+
working-directory: ./frontend
88+
run: npm test -- --coverage --watchAll=false
89+
90+
- name: Upload coverage to Codecov
91+
uses: codecov/codecov-action@v3
92+
with:
93+
file: ./frontend/coverage/lcov.info
94+
flags: frontend
95+
name: frontend-coverage
96+
97+
lint-and-format:
98+
name: Lint and Format Check
99+
runs-on: ubuntu-latest
100+
101+
steps:
102+
- name: Checkout code
103+
uses: actions/checkout@v4
104+
105+
- name: Set up Python
106+
uses: actions/setup-python@v4
107+
with:
108+
python-version: '3.9'
109+
110+
- name: Set up Node.js
111+
uses: actions/setup-node@v3
112+
with:
113+
node-version: '18'
114+
cache: 'npm'
115+
cache-dependency-path: ./frontend/package-lock.json
116+
117+
- name: Install Python linting tools
118+
run: |
119+
python -m pip install --upgrade pip
120+
pip install black flake8 isort mypy
121+
122+
- name: Lint Python code
123+
working-directory: ./backend
124+
run: |
125+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
126+
black --check .
127+
isort --check-only .
128+
129+
- name: Install frontend dependencies
130+
working-directory: ./frontend
131+
run: npm ci
132+
133+
- name: Lint frontend code
134+
working-directory: ./frontend
135+
run: npm run lint
136+
137+
security-scan:
138+
name: Security Scan
139+
runs-on: ubuntu-latest
140+
141+
steps:
142+
- name: Checkout code
143+
uses: actions/checkout@v4
144+
145+
- name: Run Trivy vulnerability scanner
146+
uses: aquasecurity/trivy-action@master
147+
with:
148+
scan-type: 'fs'
149+
scan-ref: '.'
150+
format: 'sarif'
151+
output: 'trivy-results.sarif'
152+
153+
- name: Upload Trivy scan results to GitHub Security tab
154+
uses: github/codeql-action/upload-sarif@v2
155+
if: always()
156+
with:
157+
sarif_file: 'trivy-results.sarif'
158+
159+
build-images:
160+
name: Build Container Images
161+
runs-on: ubuntu-latest
162+
needs: [test-backend, test-frontend, lint-and-format]
163+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
164+
165+
steps:
166+
- name: Checkout code
167+
uses: actions/checkout@v4
168+
169+
- name: Set up Podman
170+
run: |
171+
sudo apt-get update
172+
sudo apt-get install -y podman
173+
174+
- name: Log in to Container Registry
175+
uses: redhat-actions/podman-login@v1
176+
with:
177+
registry: ${{ env.REGISTRY }}
178+
username: ${{ github.actor }}
179+
password: ${{ secrets.GITHUB_TOKEN }}
180+
181+
- name: Extract metadata for backend
182+
id: meta-backend
183+
uses: docker/metadata-action@v4
184+
with:
185+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}
186+
tags: |
187+
type=ref,event=branch
188+
type=ref,event=pr
189+
type=sha,prefix={{branch}}-
190+
type=raw,value=latest,enable={{is_default_branch}}
191+
192+
- name: Extract metadata for frontend
193+
id: meta-frontend
194+
uses: docker/metadata-action@v4
195+
with:
196+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}
197+
tags: |
198+
type=ref,event=branch
199+
type=ref,event=pr
200+
type=sha,prefix={{branch}}-
201+
type=raw,value=latest,enable={{is_default_branch}}
202+
203+
- name: Build backend image
204+
working-directory: ./backend
205+
run: |
206+
podman build \
207+
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:latest \
208+
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:${{ github.sha }} \
209+
--file Containerfile .
210+
211+
- name: Build frontend image
212+
working-directory: ./frontend
213+
run: |
214+
podman build \
215+
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:latest \
216+
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:${{ github.sha }} \
217+
--file Containerfile .
218+
219+
- name: Push backend image
220+
run: |
221+
podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:latest
222+
podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:${{ github.sha }}
223+
224+
- name: Push frontend image
225+
run: |
226+
podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:latest
227+
podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:${{ github.sha }}
228+
229+
e2e-tests:
230+
name: E2E Tests
231+
runs-on: ubuntu-latest
232+
needs: [build-images]
233+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
234+
235+
steps:
236+
- name: Checkout code
237+
uses: actions/checkout@v4
238+
239+
- name: Set up Podman
240+
run: |
241+
sudo apt-get update
242+
sudo apt-get install -y podman
243+
244+
- name: Set up Node.js
245+
uses: actions/setup-node@v3
246+
with:
247+
node-version: '18'
248+
cache: 'npm'
249+
cache-dependency-path: ./frontend/package-lock.json
250+
251+
- name: Install frontend dependencies
252+
working-directory: ./frontend
253+
run: npm ci
254+
255+
- name: Install Playwright
256+
working-directory: ./frontend
257+
run: npx playwright install --with-deps
258+
259+
- name: Pull container images
260+
run: |
261+
podman pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:${{ github.sha }}
262+
podman pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:${{ github.sha }}
263+
podman pull docker.io/postgres:15-alpine
264+
podman pull docker.io/ollama/ollama:latest
265+
266+
- name: Tag images for local use
267+
run: |
268+
podman tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_BACKEND }}:${{ github.sha }} localhost/redhat-learning-paths-backend:latest
269+
podman tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_FRONTEND }}:${{ github.sha }} localhost/redhat-learning-paths-frontend:latest
270+
271+
- name: Start application with Podman
272+
run: |
273+
# Create volumes
274+
podman volume create postgres-data || true
275+
podman volume create ollama-data || true
276+
277+
# Start the pod
278+
podman play kube podman-pod.yaml
279+
280+
# Wait for services to be ready
281+
sleep 30
282+
283+
# Check health
284+
timeout 60 bash -c 'until curl -f http://localhost:30000/health; do sleep 5; done'
285+
timeout 60 bash -c 'until curl -f http://localhost:30001/health; do sleep 5; done'
286+
287+
- name: Run E2E tests
288+
working-directory: ./frontend
289+
env:
290+
PLAYWRIGHT_BASE_URL: http://localhost:30000
291+
run: npx playwright test
292+
293+
- name: Upload Playwright report
294+
uses: actions/upload-artifact@v3
295+
if: always()
296+
with:
297+
name: playwright-report
298+
path: frontend/playwright-report/
299+
retention-days: 30
300+
301+
- name: Stop application
302+
if: always()
303+
run: |
304+
podman pod stop redhat-learning-paths || true
305+
podman pod rm redhat-learning-paths || true
306+
307+
deploy-staging:
308+
name: Deploy to Staging
309+
runs-on: ubuntu-latest
310+
needs: [e2e-tests]
311+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
312+
environment:
313+
name: staging
314+
url: https://staging.redhat-learning-paths.example.com
315+
316+
steps:
317+
- name: Checkout code
318+
uses: actions/checkout@v4
319+
320+
- name: Deploy to staging
321+
run: |
322+
echo "Deploying to staging environment..."
323+
echo "Image tags: ${{ github.sha }}"
324+
# Add your staging deployment steps here
325+
# This could include updating Kubernetes manifests,
326+
# triggering deployment pipelines, etc.
327+
328+
notification:
329+
name: Notification
330+
runs-on: ubuntu-latest
331+
needs: [test-backend, test-frontend, lint-and-format, security-scan]
332+
if: always()
333+
334+
steps:
335+
- name: Notify on success
336+
if: ${{ needs.test-backend.result == 'success' && needs.test-frontend.result == 'success' && needs.lint-and-format.result == 'success' }}
337+
run: |
338+
echo "✅ All checks passed successfully!"
339+
340+
- name: Notify on failure
341+
if: ${{ needs.test-backend.result == 'failure' || needs.test-frontend.result == 'failure' || needs.lint-and-format.result == 'failure' || needs.security-scan.result == 'failure' }}
342+
run: |
343+
echo "❌ Some checks failed. Please review the logs."
344+
exit 1

0 commit comments

Comments
 (0)