Skip to content

Feat/cross repo dispatch to lms#1921

Open
ChandanaSRooman wants to merge 8 commits into
openedx:masterfrom
PunithRooman:feat/cross-repo-dispatch-to-lms
Open

Feat/cross repo dispatch to lms#1921
ChandanaSRooman wants to merge 8 commits into
openedx:masterfrom
PunithRooman:feat/cross-repo-dispatch-to-lms

Conversation

@ChandanaSRooman
Copy link
Copy Markdown

No description provided.

Drops in the workflow template from upstream Rooman LMS repo
(edx/ops/mfe/workflow.example.yml). On every push to rooman/main:

  - Build the upstream Dockerfile (which the MFE already ships)
  - Push to ghcr.io/punithrooman/rooman-frontend-app-learning with
    both :latest and a :rooman-main-<short-sha> tag (reproducible
    for prod deploys)
  - GHA cache cuts subsequent builds from ~6 min to ~90s

After this lands, the LMS box can pull the resulting image by setting
MFE_LEARNING_DOCKER_IMAGE in ~/.local/share/tutor/config.yml.

Branch base: open-release/sumac.master (the latest stable Open edX
MFE release as of May 2026). When Verbena MFE release branches drop,
rebase rooman/main onto open-release/verbena.master.
Upstream `openedx/frontend-app-learning` doesn't ship a Dockerfile —
Tutor's mfe plugin builds the image itself using its own template.
For our fork we need a Dockerfile so the GHA workflow can build a
production image and push it to GHCR.

Two stages:

  1. node:20-bookworm-slim builder
     - apt-get the toolchain fedx-scripts needs (git, python3, build-essential)
     - npm ci with patches/ pre-copied so patch-package runs in postinstall
     - generate env.config.jsx from the upstream example if missing
       (Tutor injects the real runtime config at container start, not here)
     - npm run build → dist/

  2. caddy:2-alpine server
     - COPY --from=builder /app/dist → /usr/share/caddy
     - Caddyfile with try_files fallback for SPA routes
     - listen on :8080 (matches Tutor's expected MFE container port)

Tutor's MFE plugin injects runtime config (LMS_BASE_URL etc.) via
env vars + a generated /static/env.config.js at container start;
this image deliberately doesn't bake anything host-specific in so
the same image works in dev + prod.

Build locally with: `docker build -t test .` (takes ~6 min cold,
~90s cached).
env.config.jsx is gitignored in the upstream MFE — it's meant to be
per-deployment local config, not committed. So my last attempt (a
checked-in env.config.jsx) couldn't be staged.

Better: generate the minimal file inline in the Dockerfile via a
heredoc. The file ends up the same — exposes process.env + an empty
pluginSlots map — but the build remains self-contained and doesn't
fight upstream's .gitignore.

When Rooman adds custom plugin slots (AI tutor sidebar etc.),
replace the heredoc with a checked-in file at a non-ignored path:

    config/env.config.jsx           # added to fork, not gitignored
    COPY config/env.config.jsx ./   # before npm run build

Until then the heredoc is the simplest path.
Adds a new sidebar (alongside Discussions + Notifications) that gives
the learner an in-context chat with the Rooman tutor backend. Wired
to POST /api/practice/tutor/chat on the lab platform.

What learners see
─────────────────
- New chat-bubble icon in the courseware sidebar trigger column,
  topmost in the order.
- Click → 30rem-wide panel slides in from the right with the title
  "Rooman AI Tutor".
- Empty state: "Ask anything about this lesson…"
- Type a question, press Enter (Shift+Enter for newline), get a reply
  from the LLM via the lab platform.
- Multi-turn: history persists in component state for the session;
  refresh wipes (deliberate for v0.1 — no per-learner server-side
  history yet).
- On error: the learner's typed message is restored so they can edit
  and retry without losing what they wrote.

Files added (all additive — no upstream-file edits except the sidebars
registry, which is intentionally a small, stable file that rarely
moves):

  src/courseware/course/sidebar/sidebars/rooman-tutor/
  ├── index.js                     re-exports
  ├── messages.ts                  i18n strings
  ├── RoomanTutorTrigger.jsx       sidebar trigger button
  └── RoomanTutorSidebar.jsx       the chat panel

  src/courseware/course/sidebar/sidebars/index.js
    Added roomanTutor entry to SIDEBARS map + SIDEBAR_ORDER.

Configuration
─────────────
Lab platform host comes from `process.env.LAB_PLATFORM_BASE_URL` with
a default of `https://dev-labs.13-232-120-92.sslip.io`. Override per
deployment via Tutor's MFE_CONFIG_OVERRIDES in config.yml:

  MFE_CONFIG_OVERRIDES:
    learning:
      LAB_PLATFORM_BASE_URL: https://dev-labs.13-232-120-92.sslip.io

CORS: this sidebar issues a cross-origin POST from apps.dev-lms.<host>
to dev-labs.<host>. The lab platform's CORS middleware allows `*`,
but browsers reject the `*`-origin + `allow_credentials=true`
combination. We send `credentials: 'omit'` — the chat endpoint is
unauth so we don't need them.

Rebase discipline
─────────────────
Everything lives in a new sidebar directory (additive), with one
small touch to `sidebars/index.js` (the registry — stable file that
rarely moves upstream). Rebases of this work onto the next Open edX
release should be ~5 minutes.
…sets correctly

Without this, webpack emits src="/runtime.xxx.js" (root-relative) but
Tutor's MFE Caddyfile only handles /learning/* paths. Root-level JS
requests return empty 200s, so React never mounts and the page is blank.

With PUBLIC_URL=/learning/, webpack emits src="/learning/runtime.xxx.js"
which the Caddyfile's @mfe_learning handler serves correctly.
…platform init

Without APP_ID=learning, the config fetch goes to ?mfe=undefined and
initialization fires APP_INIT_ERROR, showing the error boundary page.
MFE_CONFIG_API_URL=/api/mfe_config/v1 is a relative URL so Caddy proxies
it to the LMS. Both are set by Tutor's own MFE Dockerfile template.
@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Jun 1, 2026
@openedx-webhooks
Copy link
Copy Markdown

Thanks for the pull request, @ChandanaSRooman!

This repository is currently maintained by @openedx/committers-frontend-app-learning.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Submit a signed contributor agreement (CLA)

⚠️ We ask all contributors to the Open edX project to submit a signed contributor agreement or indicate their institutional affiliation.
Please see the CONTRIBUTING file for more information.

If you've signed an agreement in the past, you may need to re-sign.
See The New Home of the Open edX Codebase for details.

Once you've signed the CLA, please allow 1 business day for it to be processed.
After this time, you can re-run the CLA check by adding a comment below that you have signed it.
If the CLA check continues to fail, you can tag the @openedx/cla-problems team in a comment for further assistance.

🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

…push

Adds a final step to build-and-push.yml that calls the GitHub Actions
repository_dispatch API on ChandanaSRooman/LMS with event_type=
mfe-source-updated. The LMS-side workflow build-mfe-bundle.yml listens
for that event and rebuilds the unified MFE bundle (this MFE + 10
other MFEs) into one Docker image pushed to GHCR, then deploys to the
dev EC2.

Why: the LMS-side build needs to clone the MFE source at the exact sha
that triggered the build (not pull an image), because Tutor's
`tutor images build mfe` combines all 11 MFE source repos into one
container. So we pass GITHUB_SHA along in the dispatch payload.

The step only fires on push events (not workflow_dispatch re-runs) to
prevent build loops.

Requires a PAT secret `LMS_MONOREPO_DISPATCH_PAT` set on this repo
with fine-grained access to ChandanaSRooman/LMS:
  Repository contents = read
  Actions = write
Without the secret, the step emits a warning and exits 0, so the MFE
image build still succeeds.

(Renamed type from ci -> build to satisfy OEP-51 commitlint type-enum;
upstream openedx commitlint config doesn't allow ci:.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ChandanaSRooman ChandanaSRooman force-pushed the feat/cross-repo-dispatch-to-lms branch from 17e38b0 to f0255c3 Compare June 1, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

3 participants