Take one module fix mid-train
A patch release of one module does not need the whole project to move. The update stays inside the train the lock names, touches one checkout and one entry of the lock, and refuses as soon as a newer train is waiting.
Before you start
The module is one you required yourself. It has a line under requires in grim.json, and that line is the name you pass. A module that came in as a dependency of another cannot be moved alone.
Commit what you are working on. The update rewrites grim.lock and moves a checkout under src/, and a clean tree keeps the commit of step four down to one file.
Bring the stack up. A single-module update runs nothing in the container, and the migrations and the suite of the later steps need it.
$ git status --short
$ grim upThe ritual, in order
Five steps. Only the second changes the project, and the fifth is repeated on every other machine that has the project.
Read the plan
Nothing is written. The dry run of
grim updatewith a module name checks that the module can be had, looks for a newer train, and prints the one row that would move.$ grim update cart --dry-run Checking for updates... Train 2.4 (core 2.4.2 → 2.4.2) cart 2.4.0 → 2.4.1 (~2.4) Dry run — no changes applied.The row reads: the module, the version in the lock, the newest release on train
2.4that the constraint in brackets allows.Everything is up to date on train 2.4.in its place means the fix has no release on your train yet.The headline names core with the same version on both sides of the arrow. That is how a single-module plan says core stays where it is. No core row in the table means no core change.
Take the fix
The same plan, applied. The module's checkout under
src/moves to the new tag andgrim.lockis written again.$ grim update cart … Applying updates... Installing cart (2.4.1)... OK ✓ 1 item(s) updatedCore is not copied, no file of the project is removed, and neither
composer installnor the migrations run. In the lock, the entry ofcartgets the new version and commit. Every other module, every theme, the train and the core version are carried over as they were.If the checkout would overwrite untracked files inside the module, the update stops, lists them and asks. Read the list before you answer.
Run the module's migrations
Optional. A fix that ships a migration needs it applied by hand, because a single-module update leaves the container alone.
grim artisanruns it in the app container.$ grim artisan migrateNothing to migrate.is the normal answer for a fix that only changed code.Test, then commit the lock
The lock is the record of what this project runs, and it is the only file that changed. Commit it once
grim testagrees.$ grim test $ git diff grim.lock $ git add grim.lock $ git commit -m "chore: cart 2.4.1"The diff shows one entry of
grim.lockwith a new version and commit, and nothing else. The module's own files live undersrc/, which the project's repository ignores.Land it on the other machines
A colleague gets the fix from the lock, not from running the update again.
grim installlands every module at the versiongrim.lockrecords, so the checkout ofcartmoves to the same tag and commit you tested.$ git pull $ grim installInstall also runs the migrations, so step three is not repeated there. A newer tag published in the meantime changes nothing: the lock wins.
What you have now
One entry of the lock moved. The train and everything else on it are the same as before.
{
"train": "2.4",
"core_version": "2.4.2",
"modules": {
"cart": { "version": "2.4.1" }
}
}Nothing is deployed yet. The fix reaches a server the way every change does, as a new image built from this commit.
When it does not work
“Train 2.5 available; run grim update (train)”
The core constraint in grim.json allows a newer train than the one in the lock, and a module is never moved alone across that line. Either take the whole train with Move a project to a new train, or pin the project to its train with "core": "2.4.*" and run the single-module update again. The pin is a decision to stay behind, so write it down in the commit.
“Module "payments" not found in grim.json”
The name is not under requires. Either it is spelled differently there, and only the spelling of grim.json is accepted, or the module is a dependency of another one. grim why shows which. A dependency moves with a bare grim update: while no newer train exists, that brings every unit to its newest release on the current train. Read its dry run first.
“grim.lock does not record a train”
The lock was written before trains existed, so there is no train to stay inside. Run grim update --dry-run and then grim update once. The lock it writes names the train, and single-module updates work from then on.
The suite fails with the fix in
Until you commit, the old lock is still in git. Restore it and let install land what it records.
$ git checkout grim.lock
$ grim installThe checkout of cart goes back to the old tag. A migration the fix applied is not rolled back, so look at what step three ran before you go on.
Next recipe
Add, trace and remove modules
Find a module in the catalogue, require it on the project's train, trace what came along with it, and later remove it, sweep the leftovers and write the lock again.
Read itSpells used here
grim update
Board the newest train
Move core, every module and every theme onto the newest release train grim.json allows, or a single module within the train it is on.
grim artisan
Run artisan in the container
Run an artisan command inside the app container, where the app's PHP, extensions and environment are.
grim test
Run the test suite
Run the project's tests in the app container against a separate test database that grim creates and migrates for you.
grim install
Assemble the whole project
Turn grim.json into a working project by fetching core, every module and theme, writing grim.lock, building the image and starting the stack.
grim why
Ask why a module is here
Show the chain of requirements that leads from grim.json to an installed module, and what that module requires in turn.