Add generic /api/v1/webhooks/learning_resources/ endpoint (Cohort 2 webhook delivery)#3557
Draft
blarghmatey wants to merge 3 commits into
Draft
Add generic /api/v1/webhooks/learning_resources/ endpoint (Cohort 2 webhook delivery)#3557blarghmatey wants to merge 3 commits into
blarghmatey wants to merge 3 commits into
Conversation
…oint Cohort 2 moves the LearningResource transform onto the OL Data Platform, which pushes pre-computed canonical payloads to MIT Learn instead of MIT Learn re-deriving them. This adds the single generic endpoint all pushed sources (the 4 Cohort 2 REST sources plus YouTube and Podcasts) deliver to, matching MITLearnApiClient.notify_learning_resources() in ol-data-platform. The handler groups resources by (etl_source, resource_type) and routes each group to the existing loader (load_courses / load_programs / load_videos / load_podcasts), which already upsert the OpenSearch index via their per-item update_index calls, so no separate reindex is needed. Resource types without a loader (e.g. mit_climate "article") are logged and skipped rather than failing the whole batch, so one unsupported source can't reject a mixed delivery. Signature validation is inherited from BaseWebhookView (HMAC, shared secret). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OpenAPI Changes25 changes: 0 error, 9 warning, 16 info Unexpected changes? Ensure your branch is up-to-date with |
MIT Climate articles are delivered as resource_type "document" (matching the legacy load_documents path and the corrected ol-data-platform webhook asset). Add the document -> load_documents(etl_source, items) route so they ingest instead of being skipped, and cover it with a test. The skip-unsupported-type test now uses a genuinely unknown type. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Member
Author
|
Update — the MIT Learn has no
Net: MIT Climate articles ingest through the same |
…rces webhook Add missing /api/v1/webhooks/learning_resources/ endpoint and LearningResourceWebhookRequestRequest schema to the v1 spec/client; CI's openapi_spec_check.sh was failing because these were out of date. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Jul 2, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are the relevant tickets?
Part of the MIT Learn ETL → OL Data Platform migration, Cohort 2 (REST API sources via dlt + webhook): https://github.com/mitodl/hq/issues/11511
Description (What does it do?)
Adds the single generic webhook endpoint that the OL Data Platform pushes pre-computed canonical
LearningResourcepayloads to. This is the MIT Learn receiving half of the "webhook push" delivery pattern; the platform side is ol-data-platform PR mitodl/ol-data-platform#2277 (MITLearnApiClient.notify_learning_resources()).POST /api/v1/webhooks/learning_resources/—LearningResourceWebhookView(BaseWebhookView). HMAC signature validation (X-MITLearn-Signature, sharedWEBHOOK_SECRET) is inherited fromBaseWebhookView.{"resources": [ <canonical LearningResource dict>, ... ]}. Each resource must carry at minimumreadable_id,etl_source,resource_type; all other keys pass through untouched to the loaders.process_learning_resources_webhook()groups resources by(etl_source, resource_type)and dispatches each group to the existing loaders —course → load_courses(etl_source, items),program → load_programs(etl_source, items),video → load_videos(items),podcast → load_podcasts(items).update_index(), so indexing happens automatically (same path as the existing Celery ETL).clear_views_cache()is called after processing, mirroring the OVS webhook view.resource_typewith no loader (e.g.mit_climatecurrently sends"article", which has noLearningResourceTypemember) is logged and skipped rather than 500-ing, so one unsupported source can't reject an otherwise-valid mixed batch.All 4 Cohort 2 sources (MIT Climate, MIT PE, OLL, edX programs) plus YouTube and Podcasts (Cohort 3) will deliver through this one endpoint.
Files:
webhooks/views.py,webhooks/serializers.py,webhooks/urls.py,webhooks/learning_resources_webhook_test.py.How can this be tested?
Automated (added in this PR):
webhooks/learning_resources_webhook_test.pycovers course routing, grouping by(etl_source, resource_type), video/podcast routing, unsupported-type skip, missing-required-field → 400, invalid-signature rejection, and malformed-JSON → 400.Run locally (Postgres + Redis via
docker-compose.services.yml, env per.github/workflows/ci.ymlTests step):```
uv run pytest webhooks/ --no-cov -q
```
Result on this branch: full
webhooks/suite 38 passed; pre-commit (ruff, ruff-format, detect-secrets, DRF Serializer ORM Check) all pass.Manual:
POSTa signed{"resources":[...]}batch and confirm resources are grouped and passed to the matching loader.Additional Context
Draft — one open product decision before this should merge:
mit_climatedeliversresource_type: "article", which has no MIT LearnLearningResourceType/ loader. This handler currently logs-and-skips unsupported types, so Climate articles would not ingest until "article" is mapped to a real resource type (or a loader is added). Flagging for platform/product input.Depends on the delivery contract in mitodl/ol-data-platform#2277 (
notify_learning_resources()→POST /api/v1/webhooks/learning_resources/, HMAC-signed{"resources":[...]}).