Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
38 changes: 38 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "Alpha One Labs — Dev",
"dockerComposeFile": "../docker-compose.dev.yml",
"service": "web",
"workspaceFolder": "/app",
"forwardPorts": [
8000,
3306,
6379
],
"postCreateCommand": "pip install poetry==1.8.3 && poetry config virtualenvs.create false --local && poetry install --no-interaction",
"postStartCommand": "python manage.py migrate --no-input && python manage.py collectstatic --noinput",
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-python.isort",
"ms-python.flake8",
"batisteo.vscode-django",
"monosans.djlint"
]
}
},
"features": {
"ghcr.io/devcontainers/features/git:1": {}
}
}
100 changes: 100 additions & 0 deletions .github/workflows/onboarding-smoke-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# =============================================================================
# Onboarding Smoke Test
#
# Ensures that the setup script and dev server work on every PR.
# Uses SQLite (no Docker/MySQL needed) so the CI job is fast and simple.
#
# This test guards against regressions that would break new-contributor
# onboarding — if this job fails, someone can't get started.
# =============================================================================
name: Onboarding Smoke Test

on:
push:
branches: [main]
paths:
- "scripts/**"
- "package.json"
- "pyproject.toml"
- "poetry.lock"
- ".env.sample"
- ".github/workflows/onboarding-smoke-test.yml"
pull_request:
paths:
- "scripts/**"
- "package.json"
- "pyproject.toml"
- "poetry.lock"
- ".env.sample"
- ".github/workflows/onboarding-smoke-test.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
smoke-test:
name: Setup & Boot
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "poetry"

- name: Set up Node.js (for npm run commands)
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Run setup script
run: |
npm run setup

- name: Run doctor
run: |
npm run doctor

- name: Boot server and hit health endpoint
run: |

# Start the dev server in the background
npm run dev &
SERVER_PID=$!

# Wait for the server to be ready (up to 30 seconds)
echo "Waiting for server to start..."
for i in $(seq 1 30); do
if curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/en/ | grep -qE "200|301|302"; then
echo "Server is up! (attempt ${i})"
break
fi
if [ $i -eq 30 ]; then
echo "Server failed to start within 30 seconds"
kill "${SERVER_PID}" 2>/dev/null || true
exit 1
fi
sleep 1
done

# Verify the response
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/en/)
echo "HTTP response code: ${HTTP_CODE}"

if echo "${HTTP_CODE}" | grep -qE "200|301|302"; then
echo "✔ Health check passed!"
else
echo "✖ Health check failed with HTTP ${HTTP_CODE}"
kill "${SERVER_PID}" 2>/dev/null || true
exit 1
fi

# Clean shutdown
kill "${SERVER_PID}" 2>/dev/null || true
wait "${SERVER_PID}" 2>/dev/null || true
echo "✔ Server stopped cleanly"
36 changes: 21 additions & 15 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
merge_group:

permissions:
Expand All @@ -17,17 +18,16 @@ jobs:
name: Linting
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Prepare pip cache dir
run: mkdir -p ~/.cache/pip

- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
python-version: "3.10"
cache: "pip"

- name: Install Poetry and dependencies (lint env)
run: |
Expand All @@ -39,7 +39,6 @@ jobs:
pre-commit install
pre-commit run --all-files


tests:
name: Run Tests
runs-on: ubuntu-latest
Expand All @@ -61,16 +60,16 @@ jobs:
--health-retries=3

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Prepare pip cache dir
run: mkdir -p ~/.cache/pip

- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
python-version: "3.10"
cache: "pip"

- name: Configure MySQL and run tests (Poetry env)
env:
Expand All @@ -84,7 +83,7 @@ jobs:
DJANGO_SETTINGS_MODULE: web.settings
run: |
cp .env.sample .env
sed -i 's|DATABASE_URL=.*|DATABASE_URL=${DATABASE_URL}|g' .env
sed -i "s|DATABASE_URL=.*|DATABASE_URL=${DATABASE_URL}|g" .env

sudo apt-get update
sudo apt-get install -y default-libmysqlclient-dev
Expand All @@ -103,13 +102,20 @@ jobs:
name: Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Prepare pip cache dir
run: mkdir -p ~/.cache/pip

- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
python-version: "3.10"
cache: "pip"

- name: Run Bandit Security Scan
run: |
pip install bandit==1.7.5
bandit -r . -ll -ii -x ./venv,.venv,./tests

# Trigger CI
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ backup.json
ansible/inventory.yml
education-website-*.json
*.sql
node_modules/
.venv/
Empty file.
22 changes: 22 additions & 0 deletions dev_output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

> alphaonelabs-education-website@1.0.0 dev
> bash scripts/dev.sh

Pre-flight checks...
 ✔ .env file found
 ✔ Python: /Users/lakshyagupta/Desktop/GSOC'26/OSL/alphaonelabs-education-website/.venv/bin/python
 ⚠ Redis CLI not found — skipping Redis check.
 ⚠ WebSocket features (chat, whiteboard) require Redis at runtime.
Collecting static files...
Sentry DSN not configured; error events will not be sent.
Using console email backend with Slack notifications for development
Warning: Service account file not found at /Users/lakshyagupta/Desktop/GSOC'26/OSL/alphaonelabs-education-website/your-service-account-file-path
 ✔ Static files ready

══════════════════════════════════════════════════════════
 Alpha One Labs — Development Server
══════════════════════════════════════════════════════════

Local: http://localhost:8000
Network: http://0.0.0.0:8000
Admin: http://localhost:8000/a-dmin-url123/
105 changes: 105 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# =============================================================================
# docker-compose.dev.yml — Local development services
#
# Usage: docker compose -f docker-compose.dev.yml up
#
# Provides: Django (hot-reload), MySQL 8, Redis 7
# Data persists across restarts via named volumes.
# =============================================================================

services:
# ---------------------------------------------------------------------------
# MySQL 8 — relational database
# ---------------------------------------------------------------------------
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: education_website
MYSQL_USER: django
MYSQL_PASSWORD: django_password
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test:
[
"CMD",
"mysqladmin",
"ping",
"-h",
"127.0.0.1",
"-u",
"root",
"-prootpassword",
]
interval: 10s
timeout: 5s
retries: 5

# ---------------------------------------------------------------------------
# Redis 7 — channel layer for Django Channels (WebSockets)
# ---------------------------------------------------------------------------
redis:
image: redis:7-alpine
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5

# ---------------------------------------------------------------------------
# Django web application — development server with hot-reload
# ---------------------------------------------------------------------------
web:
build:
context: .
dockerfile: Dockerfile
command: >
bash -c "
echo 'Waiting for MySQL...' &&
while ! mysqladmin ping -h db -u django -pdjango_password --silent 2>/dev/null; do
sleep 1
done &&
echo 'MySQL is ready!' &&
python manage.py migrate --no-input &&
python manage.py create_test_data &&
python manage.py collectstatic --noinput &&
echo '========================================' &&
echo ' Dev server: http://localhost:8000' &&
echo '========================================' &&
python manage.py runserver 0.0.0.0:8000
"
volumes:
# Bind-mount the source code for hot-reload
- .:/app
# Prevent the container's venv from being overwritten by the bind mount
- /app/.venv
ports:
- "8000:8000"
environment:
- DATABASE_URL=mysql://django:django_password@db:3306/education_website
- REDIS_URL=redis://redis:6379/0
- ENVIRONMENT=development
- DEBUG=True
- SECRET_KEY=docker-dev-secret-key-not-for-production
- DJANGO_SETTINGS_MODULE=web.settings
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped

volumes:
mysql_data:
driver: local
redis_data:
driver: local
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "alphaonelabs-education-website",
"version": "1.0.0",
"private": true,
"description": "Script runner for Alpha One Labs Education Platform — no Node dependencies required.",
"scripts": {
"setup": "bash scripts/setup.sh",
"dev": "bash scripts/dev.sh",
"doctor": "bash scripts/doctor.sh",
"test": "bash -c 'python manage.py test'"
}
}
3 changes: 2 additions & 1 deletion poetry.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[virtualenvs]
create = false
create = true
in-project = true
Loading