Skip to content

Liber Tertius · Chapter 3 · Keeping a project current

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.

≈5 min 5 steps A clean working tree A running stack
Source

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 up

The ritual, in order

Five steps. Only the second changes the project, and the fifth is repeated on every other machine that has the project.

  1. Read the plan

    Nothing is written. The dry run of grim update with 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.4 that 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.

  2. Take the fix

    The same plan, applied. The module's checkout under src/ moves to the new tag and grim.lock is written again.

    $ grim update cart
    
    Applying updates...
      Installing cart (2.4.1)... OK
    
    ✓ 1 item(s) updated

    Core is not copied, no file of the project is removed, and neither composer install nor the migrations run. In the lock, the entry of cart gets 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.

  3. 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 artisan runs it in the app container.

    $ grim artisan migrate

    Nothing to migrate. is the normal answer for a fix that only changed code.

  4. 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 test agrees.

    $ 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.lock with a new version and commit, and nothing else. The module's own files live under src/, which the project's repository ignores.

  5. Land it on the other machines

    A colleague gets the fix from the lock, not from running the update again. grim install lands every module at the version grim.lock records, so the checkout of cart moves to the same tag and commit you tested.

    $ git pull
    $ grim install

    Install 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 install

The 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.