Skip to content

Commit f644db4

Browse files
authored
chore: add GitHub Actions CI/CD workflows (#83) (#84)
1 parent dfa9ef0 commit f644db4

File tree

6 files changed

+274
-0
lines changed

6 files changed

+274
-0
lines changed

.github/workflows/ci-dashboard.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Dashboard CI
2+
3+
on:
4+
push:
5+
branches: [main, rebranding/bishop-state]
6+
paths:
7+
- "codebenders-dashboard/**"
8+
- ".github/workflows/ci-dashboard.yml"
9+
pull_request:
10+
branches: [main, rebranding/bishop-state]
11+
paths:
12+
- "codebenders-dashboard/**"
13+
- ".github/workflows/ci-dashboard.yml"
14+
15+
defaults:
16+
run:
17+
working-directory: codebenders-dashboard
18+
19+
jobs:
20+
ci:
21+
name: Type check · Lint · Build
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: "20"
30+
cache: "npm"
31+
cache-dependency-path: codebenders-dashboard/package-lock.json
32+
33+
- name: Install dependencies
34+
run: npm ci
35+
36+
- name: TypeScript type check
37+
run: npx tsc --noEmit
38+
39+
- name: Lint
40+
run: npm run lint
41+
42+
- name: Build
43+
run: npm run build
44+
env:
45+
# Provide placeholder values so the build doesn't fail on missing env assertions.
46+
# API routes and Supabase calls are opt-in at runtime; they are not executed during build.
47+
NEXT_PUBLIC_SUPABASE_URL: https://placeholder.supabase.co
48+
NEXT_PUBLIC_SUPABASE_ANON_KEY: placeholder-anon-key
49+
DB_HOST: localhost
50+
DB_PORT: 5432
51+
DB_USER: postgres
52+
DB_PASSWORD: postgres
53+
DB_NAME: postgres

.github/workflows/ci-python.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Python CI
2+
3+
on:
4+
push:
5+
branches: [main, rebranding/bishop-state]
6+
paths:
7+
- "ai_model/**"
8+
- "operations/**"
9+
- "requirements.txt"
10+
- ".github/workflows/ci-python.yml"
11+
pull_request:
12+
branches: [main, rebranding/bishop-state]
13+
paths:
14+
- "ai_model/**"
15+
- "operations/**"
16+
- "requirements.txt"
17+
- ".github/workflows/ci-python.yml"
18+
19+
jobs:
20+
ci:
21+
name: Lint · Deps · Syntax check
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-python@v5
28+
with:
29+
python-version: "3.11"
30+
cache: "pip"
31+
32+
- name: Install ruff
33+
run: pip install ruff
34+
35+
- name: Lint (ruff)
36+
run: ruff check ai_model/ operations/
37+
38+
- name: Install dependencies
39+
run: pip install -r requirements.txt
40+
41+
- name: Syntax check — entry points
42+
run: |
43+
python -m py_compile ai_model/complete_ml_pipeline.py
44+
python -m py_compile operations/db_config.py
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Deploy Preview
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
jobs:
8+
deploy:
9+
name: Vercel preview deployment
10+
runs-on: ubuntu-latest
11+
# Only run when Vercel secrets are configured (skips forks / contributors without access)
12+
if: ${{ vars.VERCEL_PROJECT_ID != '' }}
13+
14+
permissions:
15+
pull-requests: write # needed to post the preview URL comment
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: actions/setup-node@v4
21+
with:
22+
node-version: "20"
23+
24+
- name: Install Vercel CLI
25+
run: npm install --global vercel@latest
26+
27+
- name: Pull Vercel environment (preview)
28+
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
29+
env:
30+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
31+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
32+
33+
- name: Build
34+
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
35+
env:
36+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
37+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
38+
39+
- name: Deploy
40+
id: deploy
41+
run: |
42+
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
43+
echo "url=$url" >> "$GITHUB_OUTPUT"
44+
env:
45+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
46+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
47+
48+
- name: Post preview URL to PR
49+
uses: actions/github-script@v7
50+
with:
51+
script: |
52+
github.rest.issues.createComment({
53+
issue_number: context.issue.number,
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
body: `## Preview deployment\n\n🚀 **${{ steps.deploy.outputs.url }}**\n\nDeployed from ${context.sha.slice(0, 7)}.`,
57+
})
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Deploy Production
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
deploy:
9+
name: Vercel production deployment
10+
runs-on: ubuntu-latest
11+
# Only run when Vercel secrets are configured
12+
if: ${{ vars.VERCEL_PROJECT_ID != '' }}
13+
14+
environment:
15+
name: production
16+
url: ${{ steps.deploy.outputs.url }}
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- uses: actions/setup-node@v4
22+
with:
23+
node-version: "20"
24+
25+
- name: Install Vercel CLI
26+
run: npm install --global vercel@latest
27+
28+
- name: Pull Vercel environment (production)
29+
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
30+
env:
31+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
32+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
33+
34+
- name: Build
35+
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
36+
env:
37+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
38+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
39+
40+
- name: Deploy
41+
id: deploy
42+
run: |
43+
url=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
44+
echo "url=$url" >> "$GITHUB_OUTPUT"
45+
env:
46+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
47+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Security Audit
2+
3+
on:
4+
schedule:
5+
- cron: "0 9 * * 1" # Every Monday at 09:00 UTC
6+
push:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
audit-npm:
12+
name: npm audit (dashboard)
13+
runs-on: ubuntu-latest
14+
15+
defaults:
16+
run:
17+
working-directory: codebenders-dashboard
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- uses: actions/setup-node@v4
23+
with:
24+
node-version: "20"
25+
cache: "npm"
26+
cache-dependency-path: codebenders-dashboard/package-lock.json
27+
28+
- name: Install dependencies
29+
run: npm ci
30+
31+
- name: Audit
32+
run: npm audit --audit-level=high
33+
34+
audit-python:
35+
name: pip-audit (ML pipeline)
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- uses: actions/setup-python@v5
42+
with:
43+
python-version: "3.11"
44+
cache: "pip"
45+
46+
- name: Install pip-audit
47+
run: pip install pip-audit
48+
49+
- name: Audit
50+
run: pip-audit -r requirements.txt

ruff.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Ruff configuration for the ML pipeline and operations code.
2+
#
3+
# Rule selection is intentionally narrow to give a green CI baseline
4+
# from the existing codebase. Expand select/remove ignores incrementally
5+
# as the code is cleaned up.
6+
#
7+
# Selected rules:
8+
# E9xx — syntax errors (always fatal)
9+
# F — pyflakes: undefined names, bad imports, redefinitions
10+
#
11+
# Ignored rules (existing code baseline):
12+
# F401 — imported but unused (common in ML notebooks-style scripts)
13+
# F541 — f-string without placeholders (style, not a bug)
14+
# F841 — local variable assigned but never used (acceptable in data scripts)
15+
16+
[lint]
17+
select = ["E9", "F"]
18+
19+
ignore = [
20+
"F401",
21+
"F541",
22+
"F841",
23+
]

0 commit comments

Comments
 (0)