Skip to content

feat: add Canvas due date sync functionality#788

Open
xitij2000 wants to merge 3 commits into
mitodl:mainfrom
open-craft:kshitij/due-date-sync
Open

feat: add Canvas due date sync functionality#788
xitij2000 wants to merge 3 commits into
mitodl:mainfrom
open-craft:kshitij/due-date-sync

Conversation

@xitij2000
Copy link
Copy Markdown

@xitij2000 xitij2000 commented May 8, 2026

What are the relevant tickets?

N/A

Description (What does it do?)

This change introduces functionality to synchronize due dates between Open edX and Canvas within the ol_openedx_canvas_integration plugin. It allows Canvas to act as the source of truth for assignment due dates.

Key features include:

  • New Course Setting: Added use_canvas_due_dates to course settings to toggle this behavior.
  • Assignment Sync Logic: When enabled, pushing grades or assignments to Canvas will no longer overwrite Canvas due dates with Open edX dates.
  • Canvas to Open edX Sync: A new Celery task sync_canvas_due_dates fetches due_at dates from Canvas assignments and updates the corresponding subsection blocks in Open edX.
  • Management Command: Added python manage.py sync_canvas_due_dates to allow manual triggering of the due date sync for specific courses or globally.
  • Improved Testing: Updated the integration test runner to support CMS-based tests for this plugin.

How can this be tested?

  1. Enable the Setting: In Open edX course settings (Other Course Settings), set "use_canvas_due_dates": true.
  2. Push to Canvas: Verify that when assignments are created or updated in Canvas via the plugin, the due dates in Canvas remain unchanged (or are not sent if being created).
  3. Sync from Canvas:
    • Change a due date for an assignment in Canvas.
    • Run the management command: python manage.py sync_canvas_due_dates <course_id>.
    • Verify in Studio/LMS that the subsection's due date has been updated to match Canvas.
  4. Automated Tests:
    • Run the plugin tests using the integration script: ./run_edx_integration_tests.sh --plugin ol_openedx_canvas_integration.
    • Specifically check src/ol_openedx_canvas_integration/ol_openedx_canvas_integration/test_cms_tasks.py for coverage of the sync logic.

Additional Context

This change requires a mechanism to run management command on schedule. If there are currently no other scheduled tasks, then this might require installing a plugin. tutor-contrib-grove for instance support creating cron jobs.

private-ref: https://tasks.opencraft.com/browse/BB-10752

Copy link
Copy Markdown
Contributor

@tecoholic tecoholic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xitij2000 Hi, this is pretty close to done. My canvas installation is out of order. I will set it up and test the flow fully. Meanwhile, kindly take a look at the comments.

Nice work setting up the testing infrastructure. I learnt about the cms specific utilities through this PR. Thank you for that.

Comment on lines +83 to +89
for course_id in courses:
try:
sync_canvas_due_dates.delay(str(course_id))
except Exception as ex:
self.stderr.write(
self.style.ERROR(f"Error processing course {course_id}: {str(ex)}")
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How often does this error occur? Since things are being queued with "delay", the errors should happen only in the background worker right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! wait a sec, tutor dev runs celery in "immediate mode". So errors bubble up..

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I added this because I initially did this without celery since that's easier to test. Either way if any error can reach here, it's better it get logged and to break other courses from processing.

_sync_canvas_due_dates(course_id)


def _sync_canvas_due_dates(course_id: str):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xitij2000 Kindly add a docstring for this function.

Comment thread run_edx_integration_tests.sh
Comment thread src/ol_openedx_canvas_integration/tests/test_cms_tasks.py
Comment thread src/ol_openedx_canvas_integration/tests/test_cms_tasks.py Outdated
@xitij2000 xitij2000 force-pushed the kshitij/due-date-sync branch from 94e3210 to b2b8037 Compare May 11, 2026 08:17
@tecoholic
Copy link
Copy Markdown
Contributor

@xitij2000 The instructor dashboard on tutor-main didn't work for me. It seems to have been caused by this PR introducing instructor.legacy_instructor_dashboard Waffle flag.

However, after setting the waffle flag, I couldn't get any of the buttons to work on the legacy dashboard to trigger the actual sync to go through.

Screencast_20260511_220052.webm

@tecoholic
Copy link
Copy Markdown
Contributor

@xitij2000 I tried to switch to a Ulmo release based devstack to avoid the instructor-dashboard issue. It didn't work either

image

It looks like the Canvas integration on Ulmo might be broken?

@xitij2000
Copy link
Copy Markdown
Author

@tecoholic I just directly ran the management commant via tutor dev exec ...

@tecoholic
Copy link
Copy Markdown
Contributor

@xitij2000 Ah! I thought we need to do the initial sync from the UI to get the Open edX assignments appear on the Canvas course and then the managemnent command we introduce in this PR, keeps the dates in sync on the Open edX end.

It's pretty late here, so maybe I am not thinking straight. I will test it again tomorrow.

@xitij2000 xitij2000 force-pushed the kshitij/due-date-sync branch 2 times, most recently from d5e92db to d715633 Compare May 11, 2026 18:34
@tecoholic
Copy link
Copy Markdown
Contributor

tecoholic commented May 12, 2026

@xitij2000 👍 I was able to test this. I have completely overlooked the fact that the assingments are actually automatically synced on "XBLOCK_PUBLISHED" signals. All I needed to do was just add an extra block and hit publish. The due date syncing works as expected.

  • Can you kindly bump the version in "pyproject.toml"?
  • Add the feature to the README?
  • Fix the CI failure. ruff format....................................Failed

👍

  • I tested this: verified that the command syncs the assignment due dates and canvas dates are not overwritten when changed in Open edX.
  • I read through the code
  • I checked for accessibility issues
  • Includes documentation - requested.

@xitij2000 xitij2000 force-pushed the kshitij/due-date-sync branch from c0190b6 to 16f3b1c Compare May 20, 2026 15:10
due_date = parse_datetime(
existing_assignments_map[str(grade_instance.usage_key)]["due_at"]
)
if due_date and due_date < datetime.now():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xitij2000 Grade syncing fails here with the following errors:

lms-1  | 2026-05-21 06:18:41,782 ERROR 53 [celery.app.trace] [user 5] [ip 172.24.0.1] trace.py:309 - Task ol_openedx_canvas_integration.tasks.sync_user_grade_with_canvas[cb184043-eb80-4c9d-85c1-593a2a34d9d0] raised unexpected: TypeError("can't compare offset-naive and offset-aware datetimes")
lms-1  | Traceback (most recent call last):
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/celery/app/trace.py", line 585, in trace_task
lms-1  |     R = retval = fun(*args, **kwargs)
lms-1  |                  ^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/ol_openedx_canvas_integration/tasks.py", line 92, in sync_user_grade_with_canvas
lms-1  |     _sync_user_grade_with_canvas(grade_id)
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/ol_openedx_canvas_integration/tasks.py", line 125, in _sync_user_grade_with_canvas
lms-1  |     if due_date and due_date < datetime.now():
lms-1  |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  | TypeError: can't compare offset-naive and offset-aware datetimes

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprising that I didn't get this error. Will fix.

xitij2000 added 2 commits May 21, 2026 17:27
Introduce new functionality for syncing Canvas assignment due dates with Open edX. This includes:
- A management command (`sync_canvas_due_dates`) for syncing due dates across courses.
- New Celery task `_sync_canvas_due_dates` to update due dates on Open edX from Canvas.
- New test suite (`CanvasDueDateSyncTests`) to verify due date syncing logic.
- Adjustments to `run_edx_integration_tests.sh` to include `ol_openedx_canvas_integration` tests.
- Extended `CanvasClient` to fetch `due_at` data for assignments.

Added pytest configuration for warning filters to reduce unnecessary warnings.
Previous tests for the canvas integration were not running since the integration script only runs tests in the tests folder so the tests were moved there.
The previous tests were not updated after a change to `diff_assignments` in a previous PR. This went unnoticed since the tests weren't running.
- Added validation to skip grade sync for assignments past their due date.
- Added missing test suite for Canvas grade sync tasks under `tests/`.
- Minor code cleanup in `api.py` and `client.py`.
@xitij2000 xitij2000 force-pushed the kshitij/due-date-sync branch 2 times, most recently from 0e1ae41 to a13f6eb Compare May 21, 2026 14:01
- Added `sync_canvas_due_date_extensions` to handle due date extensions for specific students in Canvas.
- Extended `_sync_canvas_due_dates` to update due dates with overrides.
- Added `get_emails_by_student_ids` method in `client.py` to fetch student emails by ID from Canvas.
- Updated `list_canvas_assignments` to support fetching overrides with assignments.
@xitij2000 xitij2000 force-pushed the kshitij/due-date-sync branch from a13f6eb to a87ef4e Compare May 22, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants