Automating the day away: An annoying Moodle plugin and bash scripts

I’ve spent a lot of time working with Git submodules as a part of my journey in systems admin. They have been a key tool for me in improving my upgrade and deployment strategies for Moodle by making the process faster, less prone to error, and more secure. Meaning, there is less downtime and less risk when I do upgrades. All it takes to update all my site plugins is:

sudo git submodule update –remote

Anyway, the above is my justification for working with submodules. But there are struggles sometimes. They work great with 98% of Moodle plugins, as most plugins are published in publicly accessible Github repositories. However, there are those cases where a plugin is not published publicly — usually a premium plugin that is only available to download directly from a vendor website. When I need to use these, I just make a git repository in the plugin folder on my local computer and push to a private repository I can add to my project as a submodule. When a new version comes out, I swap in the new code in the folder, commit and push changes, and am good to go.

So the thorn in my side are the Kaltura plugins. UP uses Kaltura for video and they have a very extensive and robust set of Moodle plugins. My problem is, they host all 10(!) plugins in a single Github repository. The plugins are all in subdirectories as if they were installed in the root directory of a Moodle site, like mod/kalvidassign. That makes it impossible to track them as submodules. I’ve opened a Github issue to see if they would change this but I doubt they will, so I need to rely on the manual method of creating private repos for each one. When an update comes out, that means an annoying, repetitive process of copying new files into folders, and then adding, committing, and pushing ten git repos. No thank you!

I thought this would be a good chance to improve my bash scripting skills. I know the basic programming/scripting techniques but am not very experienced writing in bash. So I did a little research and came up with the script below. Now my process to update the Kaltura plugins in my repo is:

  • Download and unzip the new version (a single folder that contains all the updated code)
  • Move that folder into the root of my existing local Kaltura plugins repository
  • Run my gitcomitter script

The script does the following:

  • asks for the name of the folder containing the updated code
  • asks for a commit message
  • iterates through each plugin directory and copies over the new code, adds and commits changes, and pushes to the remote repo.
# this helper script will go into each plugin directory and add/commit/push any changes
# (assuming you have initialized git repos and set up remotes in them)
# use from the root of the Kaltura plugins folder
# copy in the updated code folder and run this script

#get the name of the folder with the updated plugin code
read -p "Directory of of updated code: " updatedir
#get a commit message
read -p "Commit description: " desc

#create array of plugin paths

#loop through array, copy over new files, and do git stuff
for i in ${MODPATHS[@]}


   cp -r $updatedir/$i/* $i
   ( cd $i && git add . && git add -u && git commit -m "$desc" && git push )


#delete the update folder, we don't need it anymore
rm -r updatedir

Photo by Markus Spiske on Unsplash

My Top 3 Moodle Plugins of the Year

Year-end lists are an easy excuse to write a blog post, and I thought this year I would shout out some of the Moodle plugins I found to be really cool/helpful/inspiring. They aren’t necessarily new, just new to me. These are all plugins I either added recently to UP’s Moodle or am rolling out next semester. So, here goes, in no particular order:

Group Self-Selection

Moodle is at it’s best when used as a social collaborative learning environment and Moodle groups are a key method to support that pedagogical approach. But sometimes groups can be a chore to manage. This awesome plugin lets students opt into joining the groups of their choice or even provision their own groups. More learner agency and less work for instructors is a win-win.

Boost Campus Theme

I’ve had our site rocking the Boost theme since it first became the standard and have had few complaints. But, what complaints I’ve had, the Boost Campus theme addresses. It keeps the layout and overall look very familiar offers the option to enable all sorts of little quality of life improvements.

My favorite things about Boost Campus are the subtle re-organizing of the navigation drawer that somehow makes it much more intuitive, the improved settings menu, and the return of an ever-present “Editing On” button!

Kickstart Course Format

Our faculty often struggle with their new, blank-slate course shells. It’s generally a lot of support work to guide them in importing past course content or in figuring out how to provide useful course templates. The Kickstart format looked like it could solve that problem for us, giving faculty a useful dashboard of options when they first hit their new semester courses. We tried the free version which allows three templates and we were impressed enough that we purchased the premium version which allows unlimited templates and course imports. A bonus feature, strangely unadvertised, is that when courses are imported via the premium version of this plugin, it automatically updates the due dates for assignments based on the start date of the new course. A simple thing, but I had multiple faculty sending me overjoyed emails as they found out they didn’t have to manually change a bunch of dates!

Photo by Clint Patterson on Unsplash

A Guide to Collecting Drafts in Moodle Assignments

I recently completed my graduate studies, and after 3+ years of intensive study and a lot of writing, I have an ardent belief that scholarly writing is NOT a solitary activity. Good teachers show students to that writing is a process. Usually, this requires collecting drafts and creating opportunities for feedback and iterative improvement.

But, how to be paperless and also manage lots and lots of student drafts? I know that from an instructor’s standpoint, it’s not always apparent how to best set-up Moodle assignments to support drafts, feedback, and revisions. With that in mind, I wanted to write up a quick post on some of the possible workflow options for instructors to collect multiple drafts with Moodle Assignments. There is no perfect combination of settings, but these are some important settings to consider.

Submission types

There are a few powerful settings under the Submission types heading in the Assignment settings.

Files: One or Many?

The question here is: when collecting work at various stages, do you want students to upload a new file each time that sits alongside the previous draft, or replace the previous draft with a new one? If you expect multiple versions to be uploaded at once, ensure that the Maximum number of uploaded files is set to a number that will allow for this. Conversely, if you’d rather just deal with a single file from each student, make sure to set this to 1. As they move through different drafts, students will be able to replace their previous drafts with a new version of their document.

The other settings are less crucial for drafts but may still be on interest. For instance, if you depend on using Track Changes in Microsoft Word, you can use the Accepted file types option to prevent students from submitting PDFs or Apple Pages files.

Pro tip

If you are adventurous, you can skip students uploading files altogether. Instead, ask them to upload a file to a cloud service (at UP we have Microsoft OneDrive) and share a link to an online document with you. This allows a more involved and collaborative feedback process. To try this out, disable the File submissions option under Submission types and enable Online text that students can paste a sharing link to. Note that students may need an extra bit of support if they have not shared writing in this way before.

Submission settings

You’ll want to attend carefully to these settings as they determine how Moodle treats submissions.

Use the Submit Button?

One approach is to let students decide when to share a work-in-progress and when to ask you to consider a submission as final. Moodle assignments can allow for this if you enable the optional Submit button. This works with multiple file or single file submissions.

When the Submit button is on, students can upload files to an assignment, but they will be considered a draft until the student clicks the Submit button. You can provide feedback or grades for a student to review and they can choose what (if any) changes to make to their submission before hitting the Submit button.

One other possible benefit of this approach is that students can no longer make changes to their submissions after clicking the Submit button. When a file is submitted automatically upon upload, their file is considered submitted, but they can still make changes to it unless you manually lock submissions.

You can find this option under Submission settings by clicking Show more… to reveal the Require student to click the submit button selection field.

Note: because our default setting for Assignments is for the Submit button to be off, you should proactively remind students that they will need to click the submit button for your assignment.


If you want to allow students to optionally resubmit to work towards a higher grade, you can set the Maximum number of allowed attempts option to a specific number, or to unlimited attempts. You can then set the Attempts reopened setting to Manually if you want to reopen attempts yourself, or Automatically until pass if you set a Passing grade for the assignment.


If you feel it would be helpful to get email notices when a student submits, look under the Notifications options and set Notify graders about submissions to Yes.

One Assignment, or Many?

A final piece to consider is if you might want to use separate assignment activities for each draft. In the end this might be the simplest approach, especially if the drafts have different due dates or if you would like to grade each one separately. Another option that I have enjoyed as a student is to use an ungraded activity, like a forum, for learners to post early drafts. This allows the instructor and peers to give constructive feedback that the whole class might benefit from. Longer drafts and the final submission would then be uploaded to a separate Moodle Assignment for grading.


Moodle assignments offer a lot of choices to customize how you want to collect drafts. It can be a bit complex, but hopefully you see how these options can be combined to create a workflow that supports an effective digital writing, feedback and revision process.

Photo by ron dyar on Unsplash

Reflection: A Year of Moodle Admin & a Big Project

Note: I wanted to write up a piece that reflected on a year of Moodle admin, talked about how I tackled my biggest upgrade project so far, and also laid out my current approach to performing upgrades. Obviously, that is a lot and turned into too much for a post. So here is part 1 with some reflections. I’ll lay out my upgrade process in a shorter, pt. 2 post, coming (hopefully) soon.

I’m approaching a year of Moodle sys-admin-life and wanted to take a moment to reflect. I remember the uncertainty (sheer terror?) I felt just starting out: I had a lot to learn. Getting used to Linux CLI, Git, working with webservers and MySQL databases were all pretty new. I remember struggling through the first minor point upgrade I ran on my institution’s production Moodle site. I scheduled downtime for the evening hours and worked into the late night. A year later, this process takes me just a few minutes…there was definitely some newbie confusion and just a need to blindly go in and figure things out on my part that led to things taking way longer than they should have (especially figuring out those Git submodules). Yup, I was sweating the details….but I also remember the satisfaction and relief I felt, and the rush of seeing the update script complete and my upgraded site loading for the first time.

Throughout the last year, I kept practicing. I set up sandbox environments to get more experience on test sites (thanks AWS). I ran two more minor updates on production and became more confident each time. I got to experience installing, removing, and updating plugins, and worked with a contract developer to update a custom plugin. I even built out a brand new production Moodle site in the cloud, using Moodle with the Snap theme for a MOOC flavored side-project.

This is all to say that this Summer when it came time to plan not a minor-point update, but a major one – 3.4 to 3.6 – I felt not only ready to tackle the job but to make real improvements to my process.

Making a plan

Since this was the biggest Moodle project I had yet taken on I knew it was critical to come into the upgrade with a solid plan. So first I pored over the official Moodle Docs guide to updating. I made sure my server environment would continue to meet all recommendations, and painstakingly went through all extra plugins to check for compatability and available upgrades.

For the main piece of the update – the Moodle code – I initially researched updating in much the same way I had done the smaller point updates. Since I use Git for version control with submodules for plugins, that would simply entail changing the tracked branch from the official Moodle Git repo and doing a git merge. Unfortunately, this was not as easy as it first seemed, and I found that others in the community struggled with this approach. Unlike minor point updates, merging a major update requires resolving many conflicts or differences between your existing code base and the updated code. I quickly decided instead to use a clean copy of the 3.6 code.

So, I simply cloned the MOODLE_36_STABLE branch from the Moodle GitHub page into a new project directory. All I migrated over from my old folder was my config.php file and my .gitmodules file.

That introduced two new challenges:

  1. How to decouple any existing code customization that was tracked in my main Moodle Git repo (and therefore was not present in a fresh version of Moodle core)
  2. How to update plugins and efficiently migrate them as Git submodules to my new project

Decoupling customization

This was pretty straight-forward if somewhat time-consuming. Since Moodle treats basically everything as a plugin, I simply went to the Site Admin -> Plugins -> Plugins overview -> Additional plugins screen and compared that with my .gitmodules file (the file in git that keeps track of all of your project’s submodules). This let me identify any custom items that were being tracked in my main repository.

Last year I got UP signed up with a GitHub for Education plan, so I had unlimited free private repositories. So I just created new repos for the few items that were either homegrown (a custom HTML block) or that vendors for whatever reason do not make available through a public GitHub. The most annoying was Kaltura’s video plugins, which they put on GitHub as a whole repo with multiple plugins in various directories in a way that won’t work as a submodule, meaning I had to make my own repo for each individual included plugin. If anyone has an idea of how to include something like that wholesale as a submodule, I’d love to hear from you in the comments!

Anyhow, once I had moved everything into it’s own Git repo, I just added those to my .gitmodules file in the new project.

Migrating submodules

To make sure I was getting updated versions of my plugins that were compatible with 3.6, I just updated my .gitmodules file as needed. Honestly, most Moodle developers do a great job of providing branches for multiple Moodle versions and use the same naming convention so doing a find an replace for “MOODLE_34_STABLE” to “MOODLE_36_STABLE” took care of 75% of the work. But the remainder of plugins that needed updating either used non-standard branch naming conventions or had changed remote URLs or maintainers, so there was a fair bit of drudgy manual work to get everything pointed to the right place.

The problem of migrating submodules was a bit less straight-forward. You can’t just copy a .gitmodules file into a new repo, and as far as I can tell there are no easy commands to run that will look through your list of modules and actually add them to your project – maybe I’m wrong… That said: scripts to the rescue. I genuinely wish I had kept a bookmark so I could give proper credit but I found a script posted online somewhere and modified it to suit my needs. It took a bit of experimentation to get it right, but I was able to just put the script below in my 3.6 project directory (with a .gitmodules file copied from my 3.4 project) and run it to add all of my submodules to the project. If this looks useful to you, note that it requires all of the entries in .gitmodules to include the optional branch = branchname line, which you may not have if you are tracking master. So you may need to manually add a line like branch = master to your .gitmodules entries.


 ## script that looks in a .gitmodules file and re-adds all of the submodules to the git repo
 ## for future improvement - currently fails if branch not listed in gitmodules. should roll back to default master

 set -e

 git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
     while read path_key path
         url_key=$(echo $path_key | sed 's/\.path/.url/')
         url=$(git config -f .gitmodules --get "$url_key")
         branch_key=$(echo $path_key | sed 's/\.path/.branch/')
         branch=$(git config -f .gitmodules --get "$branch_key")
         git submodule add -f -b $branch $url $path


With that work done, I had a fresh copy of the 3.6 code with ALL local modifications exiting as submodules that pointed to a 3.6 compatible version of a plugin. I ran the update script and….boom! Everything went through and installed fine on the first try.

Photo by Joshua Chun on Unsplash

It’s All About the Data

This is going to sound stupid, but…One thing I didn’t really think about enough prior to starting my current job is just how much working with data is involved. Yes, I know. Information systems. It’s kind of all about data. But when I imagined what this job would entail, I thought a lot about building things, about creating systems that support and spark teaching and learning. The reams and reams of data that go along for the – names, email addresses, course CRNs, logs, files, etc – just didn’t seem that sexy to me.

But after a few months of being a sysadmin, I’m thinking about data more and more. There are the obvious things: am I doing enough to keep data safe in the age of constant breaches? Are we thinking about giving users control of their data in any meaningful way in light of evolving views about digital privacy? These are big questions. But in the day to day, I’m just working with like, rows and rows and rows.

It turns out, people have questions they want answered about the digital systems that play such an important role in our schools. These are all questions I’ve answered in the last month:

Which instructors used the accessible Moodle theme we provided in their courses?

I accidentally deleted a quiz, is there any way to get the grades each student in my class got on it?

Can you tell me who at the University has not yet completed this mandatory training?

How many people logged into Moodle on the first day of classes?

Here is the CRN numbers of 50 courses – can you get me the course full name, id number, and the instructor of record?

So what have I learned?

Sometimes this data is readily available within an application itself. For example in the recent versions of Moodle each course has a very powerful completion tracking and activity tracking report built-in. It is also be possible to extend this functionality with plugins.

Reports or logs can also generally be exported into a .csv or spreadsheet format. I was already pretty proficient with Excel but I’ve upped my game in the last few months just due to the amount of time I’ve spent in spreadsheets. (I don’t think I’ve opened PowerPoint in that time, I’ve kind of flip-flopped in that regard. Less presenting polished data and more churning through raw data).

In addition to a sheets tool, a good plain-text editor is your friend when data needs to be manipulated to be useful. I’ve been using VS Code and find it really useful for manipulating text, especially the ability to find and replace with a regex expression. This is incredibly handy when you have a comma separated list but it just has to have each item on a new-line to import wherever it is you need it to go.

If built-in reports or exported info isn’t cutting it, I’ve been going straight to the source itself: typically the Moodle database accessed by PHPMyAdmin. This lets me run SQL queries in a pretty friendly GUI environment and export the results. I’ve found that simple SQL itself is relatively easy to write – it’s understanding the complex structure of a huge relational database, how the tables need to be joined, and thinking through the links between tables that takes a bit of time. But, I am getting faster at this process – I find sketching the query out and making kind of a map of the relevant tables and fields helpful – and this is what has allowed me to do things like recover the grades of a deleted quiz or return a list of instructors who have used a certain theme.

Sketching out a SQL query
Sketching out a SQL query

Photo by Markus Spiske on Unsplash