Workflow for JupyterHubs with with nbgitpuller and JupyterLab. Extension Needed?

Question summary: How do we deal with students needing to update/reset notebooks in course notes pulled into a jupyterhub’s with nbgitpuller. Would a simple extension for jupyterlab with select git commands make sense?

More Background:
After teaching a few classes and working on several online course notes for relatively non-technical students (on the PIMS syzygy infrastructure), I have that (1) students absolutely love the JupyterLab+JupyterHub environment; (2) nbgitpuller is a spectacular way to launch lecture notes; but (3) there are missing pieces of the workflow for updating and refreshing notebooks.

In particular, consider 3 frequent scenarios of students working on distributed lecture notes:

  1. The instructor updates the notebooks and wants students to refresh new ones
  2. The student wants to reset the notebooks they may have modified
  3. The student wants to do full reset and refresh to the latest version of the notes

Nbgitpuller, does its best to refresh files/etc. if users click on the nbgitpuller link again, but it is pretty clunky workflow and involves lots of manually deleting files/etc.

The alternative which seemed to work for my recent classes was that I put a utilities.ipynb notebook in the root of the nbgitpuller pulled repository, which had roughly the following separate cells:

# Pull Latest... (Less Useful than You Think)
! git pull

# Undo All Local Changes
! git reset --hard HEAD

# Update Tracked Notebooks to Latest
! git fetch; git reset --hard origin/master

# Nuke all Changes
! git clean -qfdx; git fetch; git reset --hard origin/master

Keep in mind that we have to assume users are introductory and they shouldn’t need to know about “git” to get started, so this looks scary to them. Many users would never even used a terminal before, so having them run git commands on their own turned out to be difficult.

How did this workflow work? Better than manually deleting folders/directories and going to the link, but not great. Besides the aesthetics, the big issue is that the file itself gets modified when cells are executed. This is a nasty hack, but the easiest workflow we could think of.

Proposal for Discussion: A full git extension like https://github.com/jupyterlab/jupyterlab-git is not the solution. We want to hide git (just as we did with nbgitpuller), not give them the full workflow.

But what if an extension simply added in a file browser context menu, which could execute the git commands? Forgetting bells and whistles, but basically if the user right clicks on a folder, they get additional commands like

  • “Pull Latest”
  • “Reset Local Changes”
  • “Reset All to Latest Version”
  • “Reset Repository” - though we could live without this one

I think in all cases we would want a confirmation dialog.

Which assume that git is shell accessible and execute the above. The extension could also check that a .git folder exists and only show the menu if it does, etc. No features would be added for the cloning of repositories themselves.

2 Likes

It would be great if such an extension existed.

1 Like

Great. Based on the response Is customization of the JupyterLab file browser possible? it sounds like this is technically feasible. Can I ask for some hints on the direction, if possible:

  • Can you point me to the simplest example of a jupyterlab extension you can think of that we could use as a template? i.e. no themes or UI elements required.
  • Any examples you can think of that show how to run a shell command from within a jupyterhub extension.
  • Any thoughts on the naming of the menu items for this that would be intuitive for the typical nbgitpuller users? How about:
    • “Update Modified Notebooks” = git pull
    • “Undo Local Changes” = git reset --hard HEAD
    • “Replace all Notebooks with Latest” = git fetch; git reset --hard origin/master
    • I think there could be equivalent functions for a single file (e.g. git checkout -- filename)
1 Like

Ping @jasongrout for the JupyterLab questions :point_up: