Institutions and plugins¶
An institution is a folder under institutions/ holding only data. CI builds every folder whose
name doesn't start with _ into its own image.
| File | Holds |
|---|---|
composer.json |
the plugins, each pinned to a commit or a version tag |
composer.lock |
what Composer resolved; commit it with every change |
settings.json |
Moodle settings: defaults and locked, never connection or path settings (Configuration) |
Add an institution¶
cp -r institutions/_example institutions/<name>
bin/composer <name> update --no-install # writes composer.lock
bin/smoke <name>
The name becomes the image ghcr.io/tropotek/moodle-<name> on the next release.
Plugins¶
Composer gets a plugin in one of two ways, depending on whether its repository ships a
composer.json with "type": "moodle-<plugintype>".
| The plugin's repo | In composer.json |
Managed with |
|---|---|---|
has a typed composer.json |
a vcs repository entry, and require by its declared name |
bin/plugin (version tag) or by hand |
| has none (most) | an inline package entry: name, version, type, git URL and commit |
bin/plugin |
With bin/plugin¶
bin/plugin <name> add https://github.com/moodle-an-hochschulen/moodle-theme_boost_union.git v5.2-r12
bin/plugin <name> bump theme_boost_union v5.2-r12
bin/plugin <name> remove theme_boost_union
bin/plugin reads the plugin's version.php at the tag, branch or commit, writes the entry
and re-locks. Review the diff and commit it. If a step fails part-way, it puts
composer.json and composer.lock back as they were.
- The URL is
https://<host>/<owner>/<repo>on any git host. An inline entry's package is named<owner>/moodle-<component>. Deeper paths, such as GitLab subgroups, aren't supported. - A plugin whose repository has a typed
composer.jsongets avcsentry instead, required by its own package name. It takes a tag only, and the tag must read as a version, such as2026081302orv5.5.1. - It tells an unreachable URL apart from a ref that doesn't exist.
It is a stopgap: Moodle's own Composer repository, once it carries Marketplace plugins, will
make each plugin one require line.
By hand¶
To add a vcs plugin without bin/plugin, add the repository and require it:
{ "type": "vcs", "url": "https://github.com/jonof/moodle-block_completion_progress.git", "no-api": true }
bin/composer <name> require --no-update jonof/moodle-block_completion_progress:2026101200
bin/composer <name> update jonof/moodle-block_completion_progress --no-install
To remove one, delete its repository entry and run
bin/composer <name> remove <package> --no-install.
"no-api": true makes Composer clone with git rather than ask GitHub's API, so no token is needed.
Rules¶
- Keep the
configblock from_example.composer/installersmust stay disabled, or plugins land outside Moodle's folders; the audit setting lets Moodle 5.3.0's pinned Guzzle install. moodle/moodlemust match the base's version exactly.bin/check-lockchecks it, and lint fails on a mismatch.- A plugin with git submodules (H5P's
mod_hvp) arrives without them. Add apost-install-cmdscript:git -C moodle/public/mod/hvp submodule update --init --recursive. - Always run Composer through
bin/composer, so the lock is resolved by the image's PHP.
Removing a plugin from sites¶
Remove it from the institution and release. Each site uninstalls it, dropping its tables and settings, on the start after it moves to that release; cron then clears its leftover blocks. The plugin's own uninstall code doesn't run, because its code is already gone. For a plugin that keeps data elsewhere, uninstall it in Moodle first, then remove it from the institution.