|
| 1 | +# Lehrer – Copilot Instructions |
| 2 | + |
| 3 | +## What This Is |
| 4 | + |
| 5 | +A [Dagger](https://dagger.io/) Python module that builds and publishes Open edX platform images (edx-platform, codejail, edx-notes, MFEs) for MIT ODL deployments. It replaces an Earthly-based build pipeline. |
| 6 | + |
| 7 | +All logic lives in a single file: `src/lehrer/main.py`. |
| 8 | + |
| 9 | +## Local Dev Setup |
| 10 | + |
| 11 | +```bash |
| 12 | +uv sync # install deps (uses local editable sdk/ as dagger-io) |
| 13 | +dagger functions # list all available module functions |
| 14 | +dagger call build-platform --help |
| 15 | +``` |
| 16 | + |
| 17 | +The `sdk/` directory is a local editable install of the Dagger Python SDK — do not treat it as application code. |
| 18 | + |
| 19 | +## Running the Module |
| 20 | + |
| 21 | +```bash |
| 22 | +# Run a single build step |
| 23 | +dagger call apt-base --python-version 3.11 stdout |
| 24 | + |
| 25 | +# Full platform build |
| 26 | +dagger call build-platform \ |
| 27 | + --deployment-name mitxonline \ |
| 28 | + --release-name sumac \ |
| 29 | + --pip-package-lists ./pip_package_lists \ |
| 30 | + --pip-package-overrides ./pip_package_overrides \ |
| 31 | + --custom-settings ./settings \ |
| 32 | + --edx-platform-git-branch open-release/sumac.master \ |
| 33 | + --theme-git-repo https://github.com/mitodl/mitxonline-theme \ |
| 34 | + --theme-git-branch main |
| 35 | +``` |
| 36 | + |
| 37 | +There are no automated tests in this repository. |
| 38 | + |
| 39 | +## Architecture |
| 40 | + |
| 41 | +The `Lehrer` class (`@object_type`) contains one `@function`-decorated method per build step. Each step takes a `dagger.Container` and returns a modified one. `build_platform` chains them all together. |
| 42 | + |
| 43 | +Pipeline stages (in order): |
| 44 | +1. `apt_base` → base Python + system deps + uv binary |
| 45 | +2. `locales` → openedx-i18n locale files at `/openedx/locale` |
| 46 | +3. `get_code` → edx-platform source at `/openedx/edx-platform` + venv creation |
| 47 | +4. `install_deps` → Python (uv) + Node.js (nodeenv) deps |
| 48 | +5. `themes` → theme files at `/openedx/themes/{deployment_name}` |
| 49 | +6. `collected` → assembles dockerize, tutor bin, custom settings, creates `app` user |
| 50 | +7. `fetch_translations` → atlas pull + compilemessages |
| 51 | +8. `build_static_assets` → sass compile, collectstatic, webpack |
| 52 | +9. `docker_image` → bytecode compile, SSH config, finalize |
| 53 | + |
| 54 | +Additional top-level functions: `build_codejail`, `build_notes`, `build_mfe`, `watch_mfe`, `publish_platform`. |
| 55 | + |
| 56 | +## Key Conventions |
| 57 | + |
| 58 | +**Function naming**: Python `snake_case` methods become `kebab-case` CLI commands automatically. `build_platform` → `dagger call build-platform`. |
| 59 | + |
| 60 | +**`async def` vs `def`**: Functions that do I/O or return values (publish, build_*, watch_*) are `async`. Pure container-builder steps that chain operations are synchronous. |
| 61 | + |
| 62 | +**`dag.current_module().source().directory(...)`**: Used in `build_codejail`, `build_notes`, and `build_mfe` to reference bundled config directories from within the module at runtime. This is the pattern for optional directory parameters that default to a repo-local path. |
| 63 | + |
| 64 | +**Config directories bundled in repo**: |
| 65 | +- `codejail_config/` — `01-sandbox` sudoers file for codejail |
| 66 | +- `notes_config/` — `env_config.py` settings for edx-notes |
| 67 | +- `mfe_slot_config/` — JSX slot configs and SCSS; per-deployment subdirs (`mitx/`, `mitxonline/`, `mitx-staging/`, `xpro/`) each contain `common-mfe-config.env.jsx` |
| 68 | + |
| 69 | +**pip_package_lists/** and **pip_package_overrides/**: Organized as `{release_name}/{deployment_name}.txt`. Releases: `master`, `teak`, `ulmo` (older: `sumac`, `redwood`). Deployments: `mitx`, `mitxonline`, `mitx-staging`. |
| 70 | + |
| 71 | +**Python version logic**: `3.12` for `release_name == "master"`, `3.11` for all other releases. Applies to `build_platform`, `build_codejail`, and is a fixed `3.11` default for `build_notes`. |
| 72 | + |
| 73 | +**MFE config file resolution**: |
| 74 | +- Learning MFE: uses `learning-mfe-config.env.jsx` + `{deployment}/common-mfe-config.env.jsx` |
| 75 | +- All other MFEs: uses `{deployment}/common-mfe-config.env.jsx` as `env.config.jsx` |
| 76 | + |
| 77 | +**lxml/xmlsec override pattern**: `install_deps` uses `uv pip install` for most packages, then switches to plain `pip install --no-cache-dir` for the override file because it contains `--no-binary` flags that need special handling. |
| 78 | + |
| 79 | +**settings/ directory**: Passed as `custom_settings` to `build_platform`. Contains `lms.env.yml`, `cms.env.yml`, and `lms/`/`cms/` subdirectories with `assets.py` and `i18n.py` settings modules (placed at `lms/envs/mitol/` and `cms/envs/mitol/` in the container). |
0 commit comments