Versioning & releases

Coordinating changes across the malariaverse

Note

This is a maintainer-facing page, and part of the packages pillar of maintenance. If you just want to use the packages, start with the tutorials.

The malariaverse packages are released independently, but some of them are coupled through the data they exchange. A change in one package can break another even when there is no DESCRIPTION dependency between them. This page describes which packages are coupled, how to check compatibility before you release, and a lightweight process for coordinating a breaking change across repositories.

The approach mirrors the coordinated-release pattern used by the odin/dust/monty ecosystem: each package keeps its own semantic version, and a shared “ecosystem” git tag marks sets of versions that are known to work together.

What is coupled to what

If you change… …watch these downstream Why
malariasimulation parameter list or output structure site, cali, postie, om site builds the parameter list; cali runs the model; postie parses the output; om consumes post-processed output
site site-file structure scene, cali, and any saved analysis scene edits site files; cali recalibrates them; users pin analyses to a site-file layout
postie output columns om, downstream user code om and user analyses read postie output directly
netz site, and the site-file pipeline netz is in site’s Suggests: and Remotes:, and netz::net_loss_map is called when deriving ITN input distributions — a real code dependency, not just a data one
umbrella, peeps, treasure mostly self-contained feed site/om via data, so changes surface as changed inputs rather than build failures

The two hard code dependencies (site → malariasimulation, cali → malariasimulation) are the easy cases — R will refuse to install an incompatible combination. The dangerous couplings are the implicit data contracts: the site-file layout and the malariasimulation output layout. These have no compiler to catch them, so they are the focus below.

Checking compatibility before a release

Before releasing a change to a “hub” package (malariasimulation, site, or postie), check it against its downstreams rather than in isolation.

  1. Install the development versions together. Point at your working branches so the whole chain is built from source:

    pak::pak(c(
      "mrc-ide/malariasimulation@my-feature-branch",
      "mrc-ide/site",
      "mrc-ide/postie",
      "mrc-ide/cali"
    ))
  2. Run the downstream packages’ own test suites against your dev version — this is a lightweight reverse-dependency check:

    # from a checkout of each downstream package, with the dev upstream installed
    devtools::test()      # or: R CMD check
  3. Run one end-to-end example through the pipeline (site → malariasimulation → postie), ideally the example used in Tutorial part 1. If the tutorials still knit, the data contracts still hold.

  4. Check Remotes are current. Packages that depend on other mrc-ide packages pin them in DESCRIPTION under Remotes: (e.g. site lists mrc-ide/malariasimulation). If a dependency moved to a new tag/branch, update Remotes: in step.

If any downstream breaks, that is a breaking change — follow the process below.

Coordinating a breaking change

Keep this lightweight. The goal is that (a) users are warned, and (b) old analyses stay reproducible.

  1. Announce intent. Open an issue on each affected repo (a shared label such as breaking-change makes them easy to find) describing what will change and which packages are affected.

  2. Work on branches across all affected repos and update them in step so the pipeline stays internally consistent.

  3. Bump each package’s own version (semver: a breaking change is at least a minor bump pre-1.0, or a major bump post-1.0) and update its NEWS.md.

  4. If the site files are moving too, cut the archival snapshot tag. See How package tags relate to site-file releases below — a package-only breaking change does not need one, and relies on semver and NEWS.md instead.

  5. Publish a “Latest changes” note. The canonical template already exists as the site package vignette Latest-changes.Rmd — copy its structure: what changed, an explicit “code written against the previous versions will likely not run unchanged” warning, and how to reproduce existing work (older site files via fetch_site() + the frozen tag above).

  6. Email the user list at malariaverse@imperial.ac.uk pointing at the note.

How package tags relate to site-file releases

The malariaverse_<MM_YYYY> git tags on the package repos are archival markers, not concurrent release tags. The rule that makes them work is a single invariant:

The current site-file release works with the current main branches of the malariaverse packages.

So while a site-file release is current, there is deliberately no tag naming it on the package side — main is the supported combination, and users installing normally get something that works.

Tags are cut at the moment a new site-file release supersedes the old one. At that point every package is tagged with the name of the site-file release being retired, freezing the last package state that works with it. main is then free to move on to support the new site files.

That is why the tags currently read malariaverse_01_2025 while site files are at malariaverse_06_2026: 01_2025 is the frozen previous world, preserved so that anyone still running the older site files can identify the package versions that go with them. It is not drift.

What this means in practice

If a user is on… They should install…
The current site-file release The packages normally — no tag needed
An older site-file release The package tag named after that site-file release
# Reproducing work built against the retired site files
pak::pak(c(
  "mrc-ide/site@malariaverse_01_2025",
  "mrc-ide/postie@malariaverse_01_2025",
  "mrc-ide/malariasimulation@malariaverse_01_2025"
))

What this asks of maintainers

  • Do not cut an ecosystem tag on every package release. Only a site-file release triggers one.
  • Do tag every package at a site-file release, not only the ones that changed — the point is to name a complete working set.
  • Name the tag after the site-file release being retired, so a user holding an old site file can find its package set by name alone.
Nothing enforces the invariant automatically

“Current site files work with current main” is a promise the group keeps by hand. It is exactly what the compatibility checks above are protecting: a breaking change merged to main without checking it against the current site files silently breaks every user who is up to date, and there is no tag to fall back on because main is supposed to be the good combination.

Steps 5 and 6 are the user-facing half of a release. Guidance on writing them well — what a Latest changes note has to answer, and why a site-file change needs the same announcement even though no package version moves — is on Users & support.

Keeping the status badges in sync

The package “Project Status” badges on the home page are hand-authored in index.qmd (static repostatus.org images), so they can drift from each package’s own README. When you change a package’s status — or when you cut a coordinated release — update the badge in index.qmd to match the package’s README, and vice versa. There is no automatic sync, and no record of when the two were last reconciled — treat a coordinated release as the moment to check them.